Hi Jonathan, Gimme a day or two to give you the patch or the work around to the problem. Because of the holiday season I could not fix it until now.
Thanks Sandhya Turaga --- On Mon, 1/5/09, Jonatan Samoocha <[email protected]> wrote: From: Jonatan Samoocha <[email protected]> Subject: Re: Unexpected merge/cascade behavior To: [email protected] Date: Monday, January 5, 2009, 2:58 AM Hi Sandhya, I tried to run the test case on JPA2.0, but got the same result. Anyway, I seem to be bound to JPA1.0.0 due to project constraints. You mention "debugging the problem", does that mean the behavior displayed in this test case is incorrect? How can I assist in debugging? Do you know of any workaround? Thanks, Jonatan Sandhya Kishore wrote: > > Please ignore my previous email on this. I have reproduced the problem and > I am trying to debug it. If I do not understand what is going on I will > post the testcase. > > --- On Wed, 12/17/08, Jonatan Samoocha <[email protected]> wrote: > From: Jonatan Samoocha <[email protected]> > Subject: Unexpected merge/cascade behavior > To: [email protected] > Date: Wednesday, December 17, 2008, 7:22 AM > > Hi all, > > I'm quite new to (Open)JPA and am experiencing unexpected behavior of the > merge() operation. I'm dealing with a parent and child entity that are > defined as follows: > > //Parent: > @Entity > @Table(name="TEST_PARENT") > public class TestParent { > @Id > @Column(name="ID", nullable=false) > private String id = new String(); > > @Column(name="name") > private String name = new String(); > > @OneToMany(mappedBy="parent", fetch=FetchType.EAGER, > cascade={CascadeType.ALL}) > private Set<TestChild> children = new HashSet<TestChild>(); > > @Override > public boolean equals(Object other) { > if (other != null && other instanceof TestParent) { > return ((TestParent)other).getId().equals(this.id); > } > > return false; > } > > @Override > public int hashCode() { > return id.hashCode(); > } > > // skipping getters/setters > > public void addChild(TestChild c) { > this.children.add(c); > c.setParent(this); > } > } > > //Child: > @Entity > @Table(name="TEST_CHILD") > public class TestChild { > @Id > @Column(name="ID", nullable=false) > private String id = new String(); > > @Column(name="NAME") > private String name = new String(); > > @ManyToOne(cascade={CascadeType.ALL}) > @JoinColumn(name="PARENT_ID", nullable=false) > private TestParent parent = new TestParent(); > > @Override > public boolean equals(Object other) { > if (other != null && other instanceof TestChild) { > return ((TestChild)other).getId().equals(this.id); > } > > return false; > } > > @Override > public int hashCode() { > return id.hashCode(); > } > > //Skipping getters/setters > } > > > The class testing the merge() behavior looks as follows: > public class PCTester { > private EntityManager em = null; > > public PCTester() { > EntityManagerFactory emf = > Persistence.createEntityManagerFactory( > "testFactory"); > em = emf.createEntityManager(); > } > > public void mergeParent(TestParent p) { > em.getTransaction().begin(); > p = em.merge(p); > em.getTransaction().commit(); > } > > public static void main(String[] args) { > TestParent p = new TestParent(); > p.setId("1"); > p.setName("parent-1-update"); > > TestChild c = new TestChild(); > c.setId("1"); > c.setName("child-1-update"); > > p.addChild(c); > > PCTester t = new PCTester(); > t.mergeParent(p); > } > } > > Finally, the entity manager is configured as follows in persistence.xml: > <persistence-unit name="testFactory"> > > <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider> > > <class>com.lmco.jsf.alis.obphm.afrs.session.model.TestParent</class> > <class>com.lmco.jsf.alis.obphm.afrs.session.model.TestChild</class> > > <properties> > <property name="openjpa.ConnectionURL" > > > value="jdbc:oracle:thin:@PROPRIETARY"/> > <property name="openjpa.ConnectionDriverName" > value="oracle.jdbc.OracleDriver"/> > <property name="openjpa.ConnectionUserName" > value="PROPRIETARY"/> > <property name="openjpa.ConnectionPassword" > value="PROPRIETARY"/> > <property name="openjpa.Log" value="SQL=TRACE"/> > <property name="openjpa.ConnectionFactoryProperties" > value="PrettyPrint=true, PrettyPrintLineLength=72"/> > <property name="openjpa.jdbc.SchemaFactory" > value="native(foreignKeys=true)" /> > </properties> > > </persistence-unit> > > In case the database already contains parent and child records with id > "1", > the test runs without problems and both parent and child names are > correctly > updated. The SQL trace shows the following statements being executed: > > SELECT t0.NAME, t1.PARENT_ID, t1.ID, t1.NAME > FROM AFRS_USER.TEST_PARENT t0, AFRS_USER.TEST_CHILD t1 > WHERE t0.ID = ? AND t0.ID = t1.PARENT_ID(+) > ORDER BY t1.PARENT_ID ASC > [params=(String) 1] > > UPDATE AFRS_USER.TEST_PARENT > SET NAME = ? > WHERE ID = ? > [params=(String) parent-1-update, (String) 1] > > UPDATE AFRS_USER.TEST_CHILD > SET PARENT_ID = ?, NAME = ? > WHERE ID = ? > [params=(String) 1, (String) child-1-update, (String) 1] > > > However, when parent and child do not exist in the database, the merge() > operation throws an exception because the database tries to insert NULL > into > the parent table for reasons unknown to me: > > SELECT t0.NAME, t1.PARENT_ID, t1.ID, t1.NAME > FROM AFRS_USER.TEST_PARENT t0, AFRS_USER.TEST_CHILD t1 > WHERE t0.ID = ? AND t0.ID = t1.PARENT_ID(+) > ORDER BY t1.PARENT_ID ASC > [params=(String) 1] > > SELECT t0.NAME, t1.ID, t1.NAME > FROM AFRS_USER.TEST_CHILD t0, AFRS_USER.TEST_PARENT t1 > WHERE t0.ID = ? AND t0.PARENT_ID = t1.ID(+) > [params=(String) 1] > > // Unexpected!! > SELECT t0.NAME, t1.PARENT_ID, t1.ID, t1.NAME > FROM AFRS_USER.TEST_PARENT t0, AFRS_USER.TEST_CHILD t1 > WHERE t0.ID = ? AND t0.ID = t1.PARENT_ID(+) > ORDER BY t1.PARENT_ID ASC > [params=(String) ] > > INSERT INTO AFRS_USER.TEST_PARENT (ID, NAME) > VALUES (?, ?) > [params=(String) 1, (String) parent-1-update] > > INSERT INTO AFRS_USER.TEST_CHILD (ID, PARENT_ID, NAME) > VALUES (?, ?, ?) > [params=(String) 1, (String) 1, (String) child-1-update] > > // Unexpected!! > INSERT INTO AFRS_USER.TEST_PARENT (ID, NAME) > VALUES (?, ?) > [params=(String) , (String) ] > > Leading to > > Exception in thread "main" <openjpa-1.0.0-r420667:568756 fatal > store error> > org.apache.openjpa.persistence.RollbackException: The transaction has been > rolled back. See the nested exceptions for details on the errors that > occurred. > Etc... > > When creating a new parent only (i.e. without children) in the test > method, > it is correctly persisted into the database with the merge() operation, so > it seems that something goes wrong with cascading the merge to the child > object. > > Does anyone know what's the reason for the unexpected SQL statements? > > Any help is highly appreciated. > > Thanks, > > Jonatan Samoocha > > Using: > OpenJPA 1.0.0 > JDK 1.5.0_14 > Oracle 10G > > -- > View this message in context: > http://n2.nabble.com/Unexpected-merge-cascade-behavior-tp1668355p1668355.html > Sent from the OpenJPA Users mailing list archive at Nabble.com. > > -- View this message in context: http://n2.nabble.com/Unexpected-merge-cascade-behavior-tp1668355p2112406.html Sent from the OpenJPA Users mailing list archive at Nabble.com.
