Reputation: 20889
I need to create a bunch of objects programatically and persist them all.
There are 1:n
, 1:1
and n:n
relations involved at the same time.
All relations are defined with CascadeType.All
.
When I now create all the object instances and set their relations, only the first persist()
operation will work. The others will fail with the message, that a detached entity has been passed to persist.
Example:
A a1 = new A();
A a2 = new A();
A a3 = new A();
CommonB = new B();
SpecialB = new B();
Set<B> set1 = new HashSet<B>();
set1.add(CommonB);
set1.add(SpecialB);
Set<B> set2 = new HashSet<B>();
set2.add(CommonB);
a1.setBs(set1);
a2.setBs(set2);
a3.setBs(set2);
Now, i'm using our dataservice to persist a1, a2 and a3. (It basically just calls persist() on the entitymanager)
The first attempt works well, Both, CommonB
and SpecialB
are persisted along with a1
(also the relations are created. However, when i try to persist a2
, Hibernate says org.hibernate.PersistentObjectException: detached entity passed to persist: my.namespace.B
Classes look like this:
class A(){
@ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.ALL })
@JoinTable
private Set<B> bs;
//get set
}
class B(){
@ManyToMany(fetch = FetchType.EAGER, cascade = { CascadeType.ALL }, mappedBy = "bs")
private Set<A> as;
}
The example has been stripped down, in fact there are multiple n:n
relations between 5 entities.
--- update
I missed to add the "As" to the "Bs" Set as well:
CommonB.setAs(/* a1, a2, a3 */);
SpecialB.setAs(/* a1 */);
So, saying the complete relations are set on the object level.
Shouldn't Cascade.All
actually take care of persisting ALL objects within a certain relation bunch, whenever I save ONE of those objects?
If i give like em.persist(a1)
, shouldn't hibernate notice:
However that is not going to happen..
Upvotes: 0
Views: 1887
Reputation: 5439
When you persist a1
, it also persists the CommonB
and sets id into that object. Persisting a2
will try to persist CommonB
again while it has been persisted once. I assume your dataservice is Transactional, so after persisting a1
it closes TX and Hibernate's session then CommonB
becomes a detached object. You need to reload(re-attach) CommonB
when persisting a2
and a3
.
Upvotes: 2