You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by fa...@apache.org on 2008/11/14 00:17:24 UTC

svn commit: r713858 - in /openjpa/branches/1.2.x: openjpa-kernel/src/main/java/org/apache/openjpa/kernel/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/ openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persis...

Author: fancy
Date: Thu Nov 13 15:17:23 2008
New Revision: 713858

URL: http://svn.apache.org/viewvc?rev=713858&view=rev
Log:
OPENJPA-755 OpenJPA thows EntityExistsException trying persist a preexisting, detached entity
Apply fix to 1.2.x branch

Added:
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/TestDetachedEntityCascadePersist.java
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMCustomer.java
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMCustomerInventory.java
    openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMItem.java
Modified:
    openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java

Modified: openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java?rev=713858&r1=713857&r2=713858&view=diff
==============================================================================
--- openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java (original)
+++ openjpa/branches/1.2.x/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/SingleFieldManager.java Thu Nov 13 15:17:23 2008
@@ -744,6 +744,7 @@
             return;
 
         OpenJPAStateManager sm;
+
         if (vmd.getCascadePersist() == ValueMetaData.CASCADE_NONE) {
             if (!_broker.isDetachedNew() && _broker.isDetached(obj))
                 return; // allow but ignore
@@ -754,6 +755,10 @@
                     _loc.get("cant-cascade-persist", vmd))
                     .setFailedObject(obj);
         } else {
+            if (vmd.getCascadePersist() == ValueMetaData.CASCADE_IMMEDIATE) {
+                if (!_broker.isDetachedNew() && _broker.isDetached(obj))
+                    return; // allow but ignore
+            }        	
             sm = _broker.getStateManager(obj);
             if (sm == null || !sm.isProvisional()) { 
                 sm = _broker.persist(obj, null, true, call);

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/TestDetachedEntityCascadePersist.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/TestDetachedEntityCascadePersist.java?rev=713858&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/TestDetachedEntityCascadePersist.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/TestDetachedEntityCascadePersist.java Thu Nov 13 15:17:23 2008
@@ -0,0 +1,74 @@
+/*
+ * 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.detachment;
+
+import javax.persistence.EntityManager;
+
+import org.apache.openjpa.persistence.detachment.model.DMCustomer;
+import org.apache.openjpa.persistence.detachment.model.DMCustomerInventory;
+import org.apache.openjpa.persistence.detachment.model.DMItem;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+public class TestDetachedEntityCascadePersist extends SingleEMFTestCase {
+
+    public void setUp() {		
+        setUp(
+            CLEAR_TABLES,
+            DMCustomer.class,
+            DMItem.class,
+            DMCustomerInventory.class
+        );
+    }
+
+    public void testDetachedEntityCascadePersist() {
+        // Persist an item for finding later 
+        EntityManager em = emf.createEntityManager();
+        DMItem item = new DMItem(); 
+        item.setName("openjpa");
+        item.setPrice(0.0);
+        em.getTransaction().begin();        
+        em.persist(item);
+        // Persist a customer for finding later
+        DMCustomer customer = new DMCustomer();
+        customer.setFirstName("Open");
+        customer.setLastName("JPA");
+        em.persist(customer);
+        em.getTransaction().commit();
+        em.close();
+
+        em = emf.createEntityManager();
+        DMItem itemDetached = em.find(DMItem.class, item.getId());
+        em.close();        
+        em = emf.createEntityManager();
+        DMCustomer customer2 = em.find(DMCustomer.class, customer.getId());       
+        DMCustomerInventory customerInventory = new DMCustomerInventory();
+        customerInventory.setCustomer(customer2);
+        customerInventory.setItem(itemDetached);
+        customerInventory.setQuantity(20);
+        customer2.getCustomerInventories().add(customerInventory);
+        em.getTransaction().begin();
+        em.merge(customer2);        
+        // At this point, itemDetached is still detached.
+        // The following commit causes a persist on CustomerInventory,
+        // which leads to a cascade-persist on the detached item.
+        // This cascade-persist on a detached item should be ignored, 
+        // instead of a EntityExistsException being thrown
+        em.getTransaction().commit();
+    }
+}

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMCustomer.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMCustomer.java?rev=713858&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMCustomer.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMCustomer.java Thu Nov 13 15:17:23 2008
@@ -0,0 +1,77 @@
+/*
+ * 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.detachment.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+
+@Entity 
+public class DMCustomer {
+
+    private static long idCounter = System.currentTimeMillis();	
+    @Id private long id = idCounter++;    
+    private String firstName;    
+    private String lastName;    
+
+    @OneToMany(mappedBy="customer", 
+            fetch=FetchType.EAGER,
+            cascade=CascadeType.ALL)
+            private List<DMCustomerInventory> customerInventories = new ArrayList<DMCustomerInventory>();
+
+    public DMCustomer() {
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public String getFirstName() {
+        return firstName;
+    }
+
+    public void setFirstName(String firstName) {
+        this.firstName = firstName;
+    }
+
+    public String getLastName() {
+        return lastName;
+    }
+
+    public void setLastName(String lastName) {
+        this.lastName = lastName;
+    }
+
+    public List<DMCustomerInventory> getCustomerInventories() {
+        return customerInventories;
+    }
+
+    public void setCustomerInventories(List<DMCustomerInventory> customerInventories) {
+        this.customerInventories = customerInventories;
+    }
+}

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMCustomerInventory.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMCustomerInventory.java?rev=713858&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMCustomerInventory.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMCustomerInventory.java Thu Nov 13 15:17:23 2008
@@ -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.detachment.model;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+
+@Entity
+public class DMCustomerInventory  {
+    private static long idCounter = System.currentTimeMillis();
+    @Id private long id = idCounter++;
+
+    @ManyToOne(cascade=CascadeType.ALL)
+    @JoinColumn(name = "CI_ITEMID")
+    private DMItem  item;    
+    private int quantity;
+
+    @ManyToOne(cascade=CascadeType.MERGE)
+    @JoinColumn(name="CI_CUSTOMERID")
+    private DMCustomer customer;
+
+    public DMCustomerInventory() {
+    }
+
+    public long getId() {
+        return id;
+    }
+
+    public void setId(long id) {
+        this.id = id;
+    }
+
+    public DMItem getItem() {
+        return item;
+    }
+
+    public void setItem(DMItem item) {
+        this.item = item;
+    }
+
+    public int getQuantity() {
+        return quantity;
+    }
+
+    public void setQuantity(int quantity) {
+        this.quantity = quantity;
+    }
+
+    public DMCustomer getCustomer() {
+        return customer;
+    }
+
+    public void setCustomer(DMCustomer customer) {
+        this.customer = customer;
+    }    
+}

Added: openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMItem.java
URL: http://svn.apache.org/viewvc/openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMItem.java?rev=713858&view=auto
==============================================================================
--- openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMItem.java (added)
+++ openjpa/branches/1.2.x/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/detachment/model/DMItem.java Thu Nov 13 15:17:23 2008
@@ -0,0 +1,51 @@
+/*
+ * 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.detachment.model;
+
+import javax.persistence.Entity;
+import javax.persistence.Id;
+
+@Entity
+public class DMItem {
+    private static long idCounter = System.currentTimeMillis();	
+    @Id private long id = idCounter++;
+
+    private String name;
+    private double price;
+
+
+    public long getId() {
+        return id;
+    }
+    public void setId(long id) {
+        this.id = id;
+    }
+    public String getName() {
+        return name;
+    }
+    public void setName(String name) {
+        this.name = name;
+    }
+    public double getPrice() {
+        return price;
+    }
+    public void setPrice(double price) {
+        this.price = price;
+    }
+}