OPENJPA-1911: fix merge problem for entities with derived id

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@1054717 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Fay Wang 2011-01-03 19:32:03 +00:00
parent aae0ccfc3a
commit c39cd993fa
5 changed files with 425 additions and 1 deletions

View File

@ -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;

View File

@ -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() + "]";
}
}

View File

@ -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;
}
}

View File

@ -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;
}
}
}

View File

@ -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();
}
}
}
}
}