understanding persistence

Hi,

I'm trying to understand how persistence works and have been experimenting with a small app. Please read on and help me to understand if my findings are correct.

Note that given a class Foo that has a collection of Bar objects like so:

@Entity

@Table (name = "FOOS")

public class Foo

{

...

@OneToMany(mappedBy = "foo")

private Collection<Bar> BARS = new ArrayList<Bar>();

...

//getters and setters

}

Let us say that we have loaded the collection with three Bar objects. Now, let us say that we want to remove one of the Bar objects from the collection. My experimental app seems to indicate that it is not enough to simply call the remove(Object o) method on the collection, but one has to also call the remove(Object o) method on the EntityManager as well in order to get that record out of the BARS table of the database. Correct?

Furthormore, what if I wanted to remove the entire instance of the Foo object (this would include any and all remaining Bar objects in the collection)? Do I have to clear the entire collection of Bars first and those instances from the BARS table before I can remove the instance of the Foo object from the FOOS table of the database? Is there a way to do this all in one go with one method call? Does cascading help in some way in this scenario?

Please advise,

Alan

[1421 byte] By [ashiersa] at [2007-11-26 18:03:28]
# 1

> My experimental app seems to indicate that it is not

> enough to simply call the remove(Object o) method on

> the collection, but one has to also call the

> remove(Object o) method on the EntityManager as well

> in order to get that record out of the BARS table of

> the database. Correct?

If you want to remove a bar from this relationship, then call collection.remove(); if you want to remove a bar from persistence store (schedule it for removal), then call EntityManager.remove().

>

> Furthormore, what if I wanted to remove the entire

> instance of the Foo object (this would include any

> and all remaining Bar objects in the collection)? Do

> I have to clear the entire collection of Bars first

> and those instances from the BARS table before I can

> remove the instance of the Foo object from the FOOS

> table of the database? Is there a way to do this all

> in one go with one method call? Does cascading help

> in some way in this scenario?

You can annotate this relationship with cascadeType=REMOVE such that removing foo will cause all bars associated with foo to be removed from persistence store.

I don't think you need to explicitly empty the collection. After the tx commit or EntityManager.flush(), the in-memory collection will be synchronized with the db.

-cheng

cheng-fanga at 2007-7-9 5:33:37 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...
# 2

So, if I want to delete the instance of Foo and all associated instances that are part of internal collections, by using the following code:

EntityManager em1 = emf.createEntityManager();

EntityTransaction tx1 = em1.getTransaction();

tx1.begin();

Foo foo = em1.find(Foo.class, new Long(1));

em1.remove(foo);

tx1.commit();

em1.close();

Should I then add the additional annotations to the class?

@Entity

@Table (name = "FOOS")

public class Foo

{

...

@OneToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, mappedBy="foo")

@org.hibernate.annotations.Cascade org.hibernate.annotations.CascadeType.DELETE_ORPHAN)

@org.hibernate.annotations.CollectionOfElements

@joinTable(name = "BARS", joinColumns = @JoinColumn(name = "BAR_ID"))

private Collection<Bar> BARS = new ArrayList<Bar>();

...

//getters and setters

}

WhenI tried to run the app with the original annotation while doing a EntityManager.remove(), hibernate threw an exception because, according to the SQL log, it tried to perform a delete on one of the collection instances, and of course that instance wasn't in scope of the persistence context. This is why I'm asking these questions because hibernates behaviour seems to indicate that it was trying to also remove that instance from the collection even though my mapping was simply thus:

@Entity

@Table (name = "FOOS")

public class Foo

{

...

@OneToMany(mappedBy="foo")

private Collection<Bar> BARS = new ArrayList<Bar>();

...

//getters and setters

}

Which is the best way to map this scenario? Perhaps it's better to be more explicit with the cascade annotations?

Alan

ashiersa at 2007-7-9 5:33:37 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...