You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by mi...@apache.org on 2009/12/16 05:17:47 UTC
svn commit: r891121 - in /openjpa/branches/1.3.x:
openjpa-kernel/src/main/java/org/apache/openjpa/kernel/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence...
Author: mikedd
Date: Wed Dec 16 04:17:47 2009
New Revision: 891121
URL: http://svn.apache.org/viewvc?rev=891121&view=rev
Log:
OPENJPA-714:
Check l1 cache when looking for managed instances when cascading.
Submitted By: Jody Grassel
Added:
openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/
openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/TestCascadeOneToManyMerge.java (with props)
openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/model/
openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/model/Toy.java (with props)
openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/model/ToyBox.java (with props)
Modified:
openjpa/branches/1.3.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachStrategy.java
Modified: openjpa/branches/1.3.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachStrategy.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachStrategy.java?rev=891121&r1=891120&r2=891121&view=diff
==============================================================================
--- openjpa/branches/1.3.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachStrategy.java (original)
+++ openjpa/branches/1.3.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/AttachStrategy.java Wed Dec 16 04:17:47 2009
@@ -265,21 +265,27 @@
* Return a managed, possibly hollow reference for the given detached
* object.
*/
- protected Object getReference(AttachManager manager, Object toAttach,
- OpenJPAStateManager sm, ValueMetaData vmd) {
+ protected Object getReference(AttachManager manager, Object toAttach, OpenJPAStateManager sm, ValueMetaData vmd) {
if (toAttach == null)
return null;
- if (manager.getBroker().isNew(toAttach)
- || manager.getBroker().isPersistent(toAttach)) {
+ if (manager.getBroker().isNew(toAttach)) {
+ // Check if toAttach is already mapped to a managed instance
+ PersistenceCapable pc = manager.getAttachedCopy(toAttach);
+ if (pc != null) {
+ return pc;
+ } else {
+ return toAttach;
+ }
+ } else if (manager.getBroker().isPersistent(toAttach)) {
return toAttach;
} else if (manager.getBroker().isDetached(toAttach)) {
Object oid = manager.getDetachedObjectId(toAttach);
- if (oid != null)
+ if (oid != null) {
return manager.getBroker().find(oid, false, null);
+ }
}
- throw new UserException(_loc.get("cant-cascade-attach", vmd))
- .setFailedObject(toAttach);
+ throw new UserException(_loc.get("cant-cascade-attach", vmd)).setFailedObject(toAttach);
}
/**
Added: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/TestCascadeOneToManyMerge.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/TestCascadeOneToManyMerge.java?rev=891121&view=auto
==============================================================================
--- openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/TestCascadeOneToManyMerge.java (added)
+++ openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/TestCascadeOneToManyMerge.java Wed Dec 16 04:17:47 2009
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.merge;
+
+import javax.persistence.EntityManager;
+
+import org.apache.openjpa.persistence.merge.model.Toy;
+import org.apache.openjpa.persistence.merge.model.ToyBox;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+public class TestCascadeOneToManyMerge extends SingleEMFTestCase {
+ public void setUp() {
+ setUp(Toy.class, ToyBox.class, CLEAR_TABLES);
+ }
+
+ /**
+ * Create an instance of Toy and Toybox, establish the bidirectional relationship between the two, and call
+ * em.merge() on the instance of Toybox. The merge should cascade across the inverse relationship, adding both
+ * entities to the persistence context. The reference to Toy by the owning side of the relationship should be
+ * updated to point to the managed instance (Toy' because of the merge op).
+ *
+ */
+ public void testOneToManyCascadeMergeSingleEntity() {
+ EntityManager em = emf.createEntityManager();
+
+ try {
+ // Create toy
+ Toy toy = new Toy(1);
+ toy.setToyName("Toy Train");
+
+ // Create toybox
+ ToyBox toybox = new ToyBox(1);
+ toybox.setOwnerName("Evan");
+
+ // Establish relationship
+ toy.setToybox(toybox);
+ toybox.getToyList().add(toy);
+
+ // Perform the merge
+ em.getTransaction().begin();
+ ToyBox mergedToyBox = em.merge(toybox);
+ assertNotNull("Assert em.merge() didn't return null", mergedToyBox);
+
+ // Verify the merge
+ ToyBox toyboxFind = em.find(ToyBox.class, 1);
+ Toy toyFind = em.find(Toy.class, 1);
+ assertNotNull("Assert em.find() for ToyBox(id=1) did not return null.", toyboxFind);
+ assertNotNull("Assert em.find() for Toy(id=1) did not return null.", toyFind);
+ assertTrue("Assert em.find() returns the ToyBox returned by em.merge()", mergedToyBox == toyboxFind);
+ assertTrue("Assert tahat ToyBox(id=1).toyList is size 1", toyboxFind.getToyList().size() == 1);
+ assertTrue("Assert that ToyBox(id=1).toyList contains the managed Toy(id=1).", toyboxFind.getToyList()
+ .contains(toyFind));
+ assertTrue("Assert that Toy(id=1) references the managed ToyBox(id=1).", toyFind.getToybox() == toyboxFind);
+
+ em.getTransaction().commit();
+
+ // Verify successful save to the database
+ em.clear();
+ assertNotNull("Assert em.find(Toy.class, 1) doesn't return null.", em.find(Toy.class, 1));
+ assertNotNull("Assert em.find(ToyBox.class, 1) doesn't return null.", em.find(ToyBox.class, 1));
+ } finally {
+ if (em != null) {
+ if (em.getTransaction().isActive())
+ em.getTransaction().rollback();
+ em.close();
+ }
+ }
+ }
+
+ /**
+ * Create an instance of Toys (2) and Toybox, establish the bidirectional relationship between the two, and call
+ * em.merge() on the instance of Toybox. The merge should cascade across the inverse relationship, adding all
+ * entities to the persistence context. The reference to the Toys by the owning side of the relationship should be
+ * updated to point to the managed instance (Toy' because of the merge op).
+ *
+ */
+ public void testOneToManyCascadeMergeDoubleEntity() {
+ EntityManager em = emf.createEntityManager();
+
+ try {
+ // Create toys
+ Toy toy1 = new Toy(1);
+ toy1.setToyName("Toy Train");
+
+ Toy toy2 = new Toy(2);
+ toy2.setToyName("Toy Plane");
+
+ // Create toybox
+ ToyBox toybox = new ToyBox(1);
+ toybox.setOwnerName("Evan");
+
+ // Establish relationship
+ toy1.setToybox(toybox);
+ toy2.setToybox(toybox);
+ toybox.getToyList().add(toy1);
+ toybox.getToyList().add(toy2);
+
+ // Perform the merge
+ em.getTransaction().begin();
+ ToyBox mergedToyBox = em.merge(toybox);
+ assertNotNull("Assert em.merge() didn't return null", mergedToyBox);
+ em.getTransaction().commit();
+
+ // Verify the merge
+ ToyBox toyboxFind = em.find(ToyBox.class, 1);
+ Toy toy1Find = em.find(Toy.class, 1);
+ Toy toy2Find = em.find(Toy.class, 2);
+ assertNotNull("Assert em.find() for ToyBox(id=1) did not return null.", toyboxFind);
+ assertNotNull("Assert em.find() for Toy(id=1) did not return null.", toy1Find);
+ assertNotNull("Assert em.find() for Toy(id=2) did not return null.", toy2Find);
+ assertTrue("Assert em.find() returns the ToyBox returned by em.merge()", mergedToyBox == toyboxFind);
+ assertTrue("Assert tahat ToyBox(id=1).toyList is size 2", toyboxFind.getToyList().size() == 2);
+ assertTrue("Assert that ToyBox(id=1).toyList contains the managed Toy(id=1).", toyboxFind.getToyList()
+ .contains(toy1Find));
+ assertTrue("Assert that ToyBox(id=1).toyList contains the managed Toy(id=2).", toyboxFind.getToyList()
+ .contains(toy2Find));
+ assertTrue("Assert that Toy(id=1) references the managed ToyBox(id=1).",
+ toy1Find.getToybox() == toyboxFind);
+ assertTrue("Assert that Toy(id=2) references the managed ToyBox(id=1).",
+ toy2Find.getToybox() == toyboxFind);
+
+ em.clear();
+ assertNotNull("Assert em.find(Toy.class, 1) doesn't return null.", em.find(Toy.class, 1));
+ assertNotNull("Assert em.find(Toy.class, 2) doesn't return null.", em.find(Toy.class, 2));
+ assertNotNull("Assert em.find(ToyBox.class, 1) doesn't return null.", em.find(ToyBox.class, 1));
+ } finally {
+ if (em != null) {
+ if (em.getTransaction().isActive())
+ em.getTransaction().rollback();
+ em.close();
+ }
+ }
+ }
+}
Propchange: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/TestCascadeOneToManyMerge.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/model/Toy.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/model/Toy.java?rev=891121&view=auto
==============================================================================
--- openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/model/Toy.java (added)
+++ openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/model/Toy.java Wed Dec 16 04:17:47 2009
@@ -0,0 +1,75 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.merge.model;
+
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.ManyToOne;
+import javax.persistence.Version;
+
+@Entity
+public class Toy {
+ @Id
+ private int id;
+
+ private String toyName;
+
+ @ManyToOne(optional = false, fetch = FetchType.LAZY)
+ private ToyBox toybox;
+
+ @Version
+ private long version;
+
+ public Toy() {
+
+ }
+
+ public Toy(int id) {
+ this.id = id;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getToyName() {
+ return toyName;
+ }
+
+ public void setToyName(String toyName) {
+ this.toyName = toyName;
+ }
+
+ public ToyBox getToybox() {
+ return toybox;
+ }
+
+ public void setToybox(ToyBox toybox) {
+ this.toybox = toybox;
+ }
+
+ public long getVersion() {
+ return version;
+ }
+}
Propchange: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/model/Toy.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/model/ToyBox.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/model/ToyBox.java?rev=891121&view=auto
==============================================================================
--- openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/model/ToyBox.java (added)
+++ openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/model/ToyBox.java Wed Dec 16 04:17:47 2009
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.merge.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.Basic;
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Version;
+
+@Entity
+public class ToyBox {
+ @Id
+ private int id;
+
+ @Basic
+ private String ownerName;
+
+ @OneToMany(mappedBy = "toybox", cascade = CascadeType.ALL)
+ private List<Toy> toyList;
+
+ @Version
+ private long version;
+
+ public ToyBox() {
+ toyList = new ArrayList<Toy>();
+ }
+
+ public ToyBox(int id) {
+ this.id = id;
+ toyList = new ArrayList<Toy>();
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getOwnerName() {
+ return ownerName;
+ }
+
+ public void setOwnerName(String ownerName) {
+ this.ownerName = ownerName;
+ }
+
+ public List<Toy> getToyList() {
+ return toyList;
+ }
+
+ public void setToyList(List<Toy> toyList) {
+ this.toyList = toyList;
+ }
+
+ public long getVersion() {
+ return version;
+ }
+}
Propchange: openjpa/branches/1.3.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/merge/model/ToyBox.java
------------------------------------------------------------------------------
svn:eol-style = native