Page 1 of 1

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

Posted: Sat Aug 25, 2012 1:52 pm
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 ?

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

Posted: Sat Aug 25, 2012 3:36 pm
by admin
Yes, I would think so.

-Paul.

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

Posted: Sun Oct 27, 2013 8:02 pm
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?

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

Posted: Sat May 03, 2014 12:23 pm
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.

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

Posted: Sat May 03, 2014 8:34 pm
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.

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

Posted: Sat Jul 08, 2017 8:27 pm
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.

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

Posted: Sat Jul 08, 2017 8:30 pm
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.

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

Posted: Thu Jul 20, 2017 2:05 pm
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.

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

Posted: Thu Jul 20, 2017 10:03 pm
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.

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

Posted: Fri Jul 21, 2017 8:53 am
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.

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

Posted: Fri Jul 21, 2017 9:48 am
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.

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

Posted: Fri Jul 21, 2017 10:10 am
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.

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

Posted: Fri Jul 21, 2017 11:54 am
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.

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

Posted: Fri Jul 21, 2017 9:34 pm
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.

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

Posted: Sat Jul 22, 2017 5:22 pm
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.