Author: faywang
Date: Mon Jan  3 19:32:03 2011
New Revision: 1054717

URL: http://svn.apache.org/viewvc?rev=1054717&view=rev
Log:
OPENJPA-1911: fix merge problem for entities with derived id

Added:
    
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/
    
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchy.java
   (with props)
    
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchyRate.java
   (with props)
    
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchyRateOpenJPAKey.java
   (with props)
    
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/TestMergeComplexKey.java
   (with props)
Modified:
    
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java

Modified: 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java?rev=1054717&r1=1054716&r2=1054717&view=diff
==============================================================================
--- 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
 (original)
+++ 
openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/kernel/StateManagerImpl.java
 Mon Jan  3 19:32:03 2011
@@ -1999,9 +1999,25 @@ public class StateManagerImpl
                     case JavaTypes.ARRAY:
                     case JavaTypes.COLLECTION:
                     case JavaTypes.MAP:
-                    case JavaTypes.PC:
                     case JavaTypes.PC_UNTYPED:
                         break;
+                    case JavaTypes.PC:
+                        if (_meta.getField(field).isPrimaryKey()) {
+                            // this field is a derived identity
+                            //if (newVal != null && newVal.equals(curVal))
+                            //    return;
+                            //else {
+                                if (curVal != null && newVal != null && 
+                                    curVal instanceof PersistenceCapable && 
newVal instanceof PersistenceCapable) {
+                                    PersistenceCapable curPc = 
(PersistenceCapable) curVal;
+                                    PersistenceCapable newPc = 
(PersistenceCapable) newVal;
+                                    if 
(curPc.pcFetchObjectId().equals(newPc.pcFetchObjectId()))
+                                        return;
+                                    
+                                }
+                            //}
+                        } else     
+                            break;
                     default:
                         if (newVal != null && newVal.equals(curVal))
                             return;

Added: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchy.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchy.java?rev=1054717&view=auto
==============================================================================
--- 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchy.java
 (added)
+++ 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchy.java
 Mon Jan  3 19:32:03 2011
@@ -0,0 +1,114 @@
+package org.apache.openjpa.persistence.xs;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.OneToMany;
+import javax.persistence.Table;
+import javax.persistence.Transient;
+
+...@entity
+...@table(name = "PM_ACCOUNTING_HIERARCHY_TEST")
+public class AccountingHierarchy implements Serializable {
+
+    private static final long serialVersionUID = -1759978020595211326L;
+
+    private String code;
+    private String shortDesc;
+
+    private List<AccountingHierarchyRate> accRateList = new 
ArrayList<AccountingHierarchyRate>(0);
+
+    private Long version;
+
+    public AccountingHierarchy() {
+    }
+
+    public AccountingHierarchy(String code) {
+        this.code = code;
+    }
+
+    public AccountingHierarchy(String code, String shortDesc) {
+        this.code = code;
+        this.shortDesc = shortDesc;
+    }
+
+    public AccountingHierarchy(String code, String shortDesc, String 
hierarchyType) {
+        this.code = code;
+        this.shortDesc = shortDesc;
+    }
+
+    @Id
+    @Column(name = "code", length = 20)
+    public String getCode() {
+        return code;
+    }
+
+    @Column(name = "short_desc", nullable = false, length = 50)
+    public String getShortDesc() {
+        return shortDesc;
+    }
+
+    @OneToMany(mappedBy = "accountingHierarchy", fetch = FetchType.EAGER, 
+        targetEntity = AccountingHierarchyRate.class, cascade = 
CascadeType.ALL, orphanRemoval = true)
+    public List<AccountingHierarchyRate> getAccRateList() {
+        return accRateList;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public void setShortDesc(String shortDesc) {
+        this.shortDesc = shortDesc;
+    }
+
+    public void setAccRateList(List<AccountingHierarchyRate> accRateList) {
+        this.accRateList = accRateList;
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        result = prime * result + ((getCode() == null) ? 0 : 
getCode().hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (!(obj instanceof AccountingHierarchy))
+            return false;
+        AccountingHierarchy other = (AccountingHierarchy) obj;
+        if (getCode() == null) {
+            if (other.getCode() != null)
+                return false;
+        } else if (!getCode().equals(other.getCode()))
+            return false;
+        return true;
+    }
+
+    @Transient
+    public Long getVersion() {
+        return version;
+    }
+
+    public void setVersion(Long version) {
+        this.version = version;
+    }
+
+    @Override
+    public String toString() {
+        return "AccountingHierarchy [getCode()=" + getCode() + ", 
getShortDesc()=" + getShortDesc() + "]";
+    }
+
+}

Propchange: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchyRate.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchyRate.java?rev=1054717&view=auto
==============================================================================
--- 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchyRate.java
 (added)
+++ 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchyRate.java
 Mon Jan  3 19:32:03 2011
@@ -0,0 +1,109 @@
+package org.apache.openjpa.persistence.xs;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+import javax.persistence.Column;
+import javax.persistence.Entity;
+import javax.persistence.FetchType;
+import javax.persistence.Id;
+import javax.persistence.IdClass;
+import javax.persistence.JoinColumn;
+import javax.persistence.ManyToOne;
+import javax.persistence.Table;
+
+...@entity
+...@table(name = "PM_ACCOUNTING_HIERARCHY_RATE_TEST")
+...@idclass(AccountingHierarchyRateOpenJPAKey.class)
+public class AccountingHierarchyRate implements Serializable {
+
+       private static final long serialVersionUID = 538926265319989492L;
+
+       private String id;
+       private AccountingHierarchy accountingHierarchy;
+
+       private BigDecimal currentRate;
+       private BigDecimal budgetRate;
+
+       public AccountingHierarchyRate() {
+       }
+
+       public AccountingHierarchyRate(String id, AccountingHierarchy 
accountingHierarchy, 
+               BigDecimal currentRate, BigDecimal budgetRate) {
+               this.id = id;
+               this.accountingHierarchy = accountingHierarchy;
+               this.currentRate = currentRate;
+               this.budgetRate = budgetRate;
+       }
+
+       @Id
+       @Column(name = "id", length = 20, nullable = false)
+       public String getId() {
+               return id;
+       }
+
+       @Id
+       @ManyToOne(targetEntity = AccountingHierarchy.class, fetch = 
FetchType.LAZY)
+       @JoinColumn(name = "acc_hier", nullable = false)
+       public AccountingHierarchy getAccountingHierarchy() {
+               return accountingHierarchy;
+       }
+
+       @Column(name = "current_rate", nullable = true, precision = 12, scale = 
4)
+       public BigDecimal getCurrentRate() {
+               return currentRate;
+       }
+
+       @Column(name = "budget_rate", nullable = true, precision = 12, scale = 
4)
+       public BigDecimal getBudgetRate() {
+               return budgetRate;
+       }
+
+       public void setId(String id) {
+               this.id = id;
+       }
+
+       public void setAccountingHierarchy(AccountingHierarchy 
accountingHierarchy) {
+               this.accountingHierarchy = accountingHierarchy;
+       }
+
+       public void setCurrentRate(BigDecimal currentRate) {
+               this.currentRate = currentRate;
+       }
+
+       public void setBudgetRate(BigDecimal budgetRate) {
+               this.budgetRate = budgetRate;
+       }
+
+       @Override
+       public int hashCode() {
+               final int prime = 31;
+               int result = 1;
+               result = prime * result + ((getId() == null) ? 0 : 
getId().hashCode());
+               result = prime * result + ((getAccountingHierarchy() == null) ? 
0 : 
+                   getAccountingHierarchy().hashCode());
+               return result;
+       }
+
+       @Override
+       public boolean equals(Object obj) {
+               if (this == obj)
+                       return true;
+               if (obj == null)
+                       return false;
+               if (!(obj instanceof AccountingHierarchyRate))
+                       return false;
+               AccountingHierarchyRate other = (AccountingHierarchyRate) obj;
+               if (getId() == null) {
+                       if (other.getId() != null)
+                               return false;
+               } else if (!getId().equals(other.getId()))
+                       return false;
+               if (getAccountingHierarchy() == null) {
+                       if (other.getAccountingHierarchy() != null)
+                               return false;
+               } else if 
(!getAccountingHierarchy().equals(other.getAccountingHierarchy()))
+                       return false;
+               return true;
+       }
+}

Propchange: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchyRate.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchyRateOpenJPAKey.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchyRateOpenJPAKey.java?rev=1054717&view=auto
==============================================================================
--- 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchyRateOpenJPAKey.java
 (added)
+++ 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchyRateOpenJPAKey.java
 Mon Jan  3 19:32:03 2011
@@ -0,0 +1,109 @@
+package org.apache.openjpa.persistence.xs;
+
+import java.io.Serializable;
+
+/**
+ * Application identity class for: 
lk.informatics.infotrack.model.entity.AccountingHierarchyRate
+ *
+ * Auto-generated by:
+ * org.apache.openjpa.enhance.ApplicationIdTool
+ */
+public class AccountingHierarchyRateOpenJPAKey implements Serializable {
+       /**
+        * 
+        */
+       private static final long serialVersionUID = -2345673847908844341L;
+
+       static {
+               // register persistent class in JVM
+               try { 
Class.forName("org.apache.openjpa.persistence.xs.AccountingHierarchyRate"); }
+               catch(Exception e) {}
+       }
+
+       public String accountingHierarchy;
+       public String id;
+
+       public AccountingHierarchyRateOpenJPAKey() {
+       }
+
+       public AccountingHierarchyRateOpenJPAKey(String str) {
+               fromString(str);
+       }
+
+       public String getAccountingHierarchy() {
+               return accountingHierarchy;
+       }
+
+       public void setAccountingHierarchy(String accountingHierarchy) {
+               this.accountingHierarchy = accountingHierarchy;
+       }
+
+       public String getId() {
+               return id;
+       }
+
+       public void setId(String id) {
+               this.id = id;
+       }
+
+       public String toString() {
+               return accountingHierarchy
+                       + "::" + id;
+       }
+
+       public int hashCode() {
+               int rs = 17;
+               rs = rs * 37 + ((accountingHierarchy == null) ? 0 : 
accountingHierarchy.hashCode());
+               rs = rs * 37 + ((id == null) ? 0 : id.hashCode());
+               return rs;
+       }
+
+       public boolean equals(Object obj) {
+               if(this == obj)
+                       return true;
+               if(obj == null || obj.getClass() != getClass())
+                       return false;
+
+               AccountingHierarchyRateOpenJPAKey other = 
(AccountingHierarchyRateOpenJPAKey) obj;
+               return ((accountingHierarchy == null && 
other.accountingHierarchy == null)
+                       || (accountingHierarchy != null && 
accountingHierarchy.equals(other.accountingHierarchy)))
+                       && ((id == null && other.id == null)
+                       || (id != null && id.equals(other.id)));
+       }
+
+       private void fromString(String str) {
+               Tokenizer toke = new Tokenizer(str);
+               str = toke.nextToken();
+               if("null".equals(str))
+                       accountingHierarchy = null;
+               else
+                       accountingHierarchy = str;
+               str = toke.nextToken();
+               if("null".equals(str))
+                       id = null;
+               else
+                       id = str;
+       }
+
+       protected static class Tokenizer {
+               private final String str;
+               private int last;
+
+               public Tokenizer (String str) {
+                       this.str = str;
+               }
+
+               public String nextToken () {
+                       int next = str.indexOf("::", last);
+                       String part;
+                       if(next == -1) {
+                               part = str.substring(last);
+                               last = str.length();
+                       } else {
+                               part = str.substring(last, next);
+                               last = next + 2;
+                       }
+                       return part;
+               }
+       }
+}

Propchange: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/AccountingHierarchyRateOpenJPAKey.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/TestMergeComplexKey.java
URL: 
http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/TestMergeComplexKey.java?rev=1054717&view=auto
==============================================================================
--- 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/TestMergeComplexKey.java
 (added)
+++ 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/TestMergeComplexKey.java
 Mon Jan  3 19:32:03 2011
@@ -0,0 +1,76 @@
+package org.apache.openjpa.persistence.xs;
+
+import java.math.BigDecimal;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+public class TestMergeComplexKey extends SingleEMFTestCase {
+    Object[] props = new Object[] { AccountingHierarchy.class, 
AccountingHierarchyRate.class, CLEAR_TABLES };
+
+    @Override
+    public void setUp() throws Exception {
+        setUp(props);
+    }
+
+    public void test() throws Exception {
+        createDate();
+        EntityManager em = emf.createEntityManager();
+        AccountingHierarchy accountingHierarchy = (AccountingHierarchy) 
em.find(AccountingHierarchy.class, "TESTING");
+        accountingHierarchy.setShortDesc("NAME:" + System.currentTimeMillis());
+        accountingHierarchy = roundtrip(accountingHierarchy);
+        em.close();
+
+        em = emf.createEntityManager();
+        em.getTransaction().begin();
+        try {
+            em.merge(accountingHierarchy);
+        } catch (RuntimeException e) {
+            em.getTransaction().setRollbackOnly();
+            throw e;
+        } finally {
+            if (em.getTransaction().getRollbackOnly()) {
+                em.getTransaction().rollback();
+            } else {
+                em.getTransaction().commit();
+            }
+        }
+
+    }
+
+    void createDate() {
+        EntityManager em = emf.createEntityManager();
+        System.out.println(em.createQuery("select o from AccountingHierarchy 
o").getResultList().size());
+
+        String code = "TESTING";
+        AccountingHierarchy accountingHierarchy = 
em.find(AccountingHierarchy.class, code);
+        if (accountingHierarchy == null) {
+            accountingHierarchy = new AccountingHierarchy();
+            accountingHierarchy.setCode(code);
+            accountingHierarchy.setShortDesc("TESTING");
+
+            AccountingHierarchyRate accountingHierarchyRate =
+                new AccountingHierarchyRate("1", accountingHierarchy, 
BigDecimal.ONE, BigDecimal.TEN);
+
+            accountingHierarchy.getAccRateList().add(accountingHierarchyRate);
+
+            EntityTransaction tx = em.getTransaction();
+            tx.begin();
+            try {
+                em.persist(accountingHierarchy);
+            } catch (RuntimeException e) {
+                tx.setRollbackOnly();
+                throw e;
+            } finally {
+                if (tx.getRollbackOnly()) {
+                    tx.rollback();
+                } else {
+                    tx.commit();
+                }
+            }
+        }
+
+    }
+}

Propchange: 
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/xs/TestMergeComplexKey.java
------------------------------------------------------------------------------
    svn:eol-style = native


Reply via email to