About Question enthuware.oce-jpad.v6.2.602 :

Moderator: admin

Post Reply
cosminvacaroiu

About Question enthuware.oce-jpad.v6.2.602 :

Post by cosminvacaroiu »

If it were bidirectional: if you remove B which has ManyToOne and also the FK Column in its table, you wouldn't break any FK Constraints in the DB, but you will remain with a A which has a reference (in the list) to a deleted B entity. Wouldn't also throw an exception ?

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.oce-jpad.v6.2.602 :

Post by admin »

Yes, I would think so.

-Paul.
If you like our products and services, please help us by posting your review here.

ericrlessa
Posts: 5
Joined: Thu Oct 17, 2013 9:26 pm
Contact:

Re: About Question enthuware.oce-jpad.v6.2.602 :

Post by ericrlessa »

When in the same transaction, it's possible call Persist twice to the same Entity instance? The second call to persist makes some difference in this case? If yes, shouldn't be merge instead of persist?

Deleted User 621

Re: About Question enthuware.oce-jpad.v6.2.602 :

Post by Deleted User 621 »

Bump!

I'm confused too. em.persist(a) is called twice? That's not allowed, is it?

Also, what is it really that makes you say in the explanation that "The given code seems to imply that [...] B refers to an A"? I don't see that. We set the list of Bs for A, but we set no A for the B.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.oce-jpad.v6.2.602 :

Post by admin »

Ideally, neither persist nor merge is required because it is a managed entity and any changes will be propagated to the DB automatically on commit.
But as per section 3.2.2 of JPA 2.0 specification:
If X is a preexisting managed entity, it is ignored by the persist operation.
So calling persist the second time in this case is not a problem.
Also, what is it really that makes you say in the explanation that "The given code seems to imply that [...] B refers to an A"? I don't see that. We set the list of Bs for A, but we set no A for the B.
The problem statement mentions that the beans have @OneToMany and @ManyToOne applied to them in appropriate places. @ManyToOne implies that B has a refers to A.

HTH,
Paul.
If you like our products and services, please help us by posting your review here.

himaiMinh
Posts: 358
Joined: Fri Nov 29, 2013 8:26 pm
Contact:

Re: About Question enthuware.oce-jpad.v6.2.602 :

Post by himaiMinh »

Ideally, neither persist nor merge is required because it is a managed entity and any changes will be propagated to the DB automatically on commit.
But as per section 3.2.2 of JPA 2.0 specification:
Quote:
If X is a preexisting managed entity, it is ignored by the persist operation.

So calling persist the second time in this case is not a problem.
When we call the persist(a) in the second time, will this call be ignore and any changes to a is not committed?
If that is the case,

Code: Select all

A a = new A();
em.persist(a); // this is not ignored.
....
a.setBs(bs);
em.persist(a); // This should be ignore and when the transaction commits, a does not even have 
any reference to any B in the list?
If a does not have any reference to B, removing B will not cause any exception.

himaiMinh
Posts: 358
Joined: Fri Nov 29, 2013 8:26 pm
Contact:

Re: About Question enthuware.oce-jpad.v6.2.602 :

Post by himaiMinh »

It sounds to me that the second em.persist(a) is ignored, but updates to a after the first em.persist(a) is still committed at the end.

himaiMinh
Posts: 358
Joined: Fri Nov 29, 2013 8:26 pm
Contact:

Re: About Question enthuware.oce-jpad.v6.2.602 :

Post by himaiMinh »

In the explanation, it says "another option is to remove a and then remove b."
But if we remove a first, the A_B table has a foreign key referring to a. That will violate the foreign key violation rule.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.oce-jpad.v6.2.602 :

Post by admin »

In case of a unidirectional one to many, if you remove a, the JPA provider will first remove the row from the join table.
If you like our products and services, please help us by posting your review here.

himaiMinh
Posts: 358
Joined: Fri Nov 29, 2013 8:26 pm
Contact:

Re: About Question enthuware.oce-jpad.v6.2.602 :

Post by himaiMinh »

Ok. I see the difference between the two solutions now:
1. Since a has @OneToMany relationship with b, removing a will cause b to be removed successfully.
But in this question, I don't see any orphanRemoval=true specified.

2. Since b has @ManyToOne relationship with a, we have to break the relationship between a and b to avoid foreign key violation in the A_B join table.

himaiMinh
Posts: 358
Joined: Fri Nov 29, 2013 8:26 pm
Contact:

Re: About Question enthuware.oce-jpad.v6.2.602 :

Post by himaiMinh »

I tried this in the ToyAppForJPA:

Code: Select all

 A a = em.find(A.class, (long)113);
List bs = a.getBs();
B b = em.find(B.class, (long)112);
bs.remove(b);
em.persist(a);
em.remove(b);
I am curious why it works without throwing EntityExistException ?
a with id 113 has already existed in the table A. We modify a by removing b in its list, I expect to see EntityExistException. But I don't.

himaiMinh
Posts: 358
Joined: Fri Nov 29, 2013 8:26 pm
Contact:

Re: About Question enthuware.oce-jpad.v6.2.602 :

Post by himaiMinh »

One more try I did :

Code: Select all

//I have persisted A with id = 116 and it has a B.
A a = em.find(A.class, (long)116);
em.remove(a);
After a is removed, its B and its reference in A_B table are removed as well.
So, removing a is good enough. I don't need to explicitly remove its b.

himaiMinh
Posts: 358
Joined: Fri Nov 29, 2013 8:26 pm
Contact:

Re: About Question enthuware.oce-jpad.v6.2.602 :

Post by himaiMinh »

Regarding to my previous post:
Code:
A a = em.find(A.class, (long)113);
List bs = a.getBs();
B b = em.find(B.class, (long)112);
bs.remove(b);
em.persist(a);
em.remove(b);
I am curious why it works without throwing EntityExistException ?
The spec 3.2.2 says "If X is a preexisting managed entity, it is ignored by the persist operation".
So, I understand why EntityExistsException is not thrown because it is not a new entity or detached entity.
But I assume the persist (a) is ignored.
But in this example, persist (a) is not ignored. It persists the a with the b removed.

Instead, I merge a instead of persist a :

Code: Select all

A a = em.find(A.class, (long)108);
List bs = a.getBs(); 
B b = em.find(B.class, (long)109);
bs.remove(b);
em.merge(a);
em.remove(b);
It also works.

admin
Site Admin
Posts: 10036
Joined: Fri Sep 10, 2010 9:26 pm
Contact:

Re: About Question enthuware.oce-jpad.v6.2.602 :

Post by admin »

himaiMinh wrote:Ok. I see the difference between the two solutions now:
1. Since a has @OneToMany relationship with b, removing a will cause b to be removed successfully.
But in this question, I don't see any orphanRemoval=true specified.
No, b will not be removed automatically. The row in the join table that links a with b will be removed if you remove a.
2. Since b has @ManyToOne relationship with a, we have to break the relationship between a and b to avoid foreign key violation in the A_B join table.
Correct.
If you like our products and services, please help us by posting your review here.

himaiMinh
Posts: 358
Joined: Fri Nov 29, 2013 8:26 pm
Contact:

Re: About Question enthuware.oce-jpad.v6.2.602 :

Post by himaiMinh »

Hi,
I tried this :

Code: Select all

A a = em.find(A.class, (long)108);
em.remove(a);
I expect a is removed and the a in the A_B table is removed, but b should be there.
But Hibernate remove a, b and the relationship in the A_B table.

Post Reply

Who is online

Users browsing this forum: No registered users and 37 guests