OPENJPA-1911: fix merge problem for entities with derived id - merged this code from Fay's changes for trunk

git-svn-id: https://svn.apache.org/repos/asf/openjpa/branches/2.0.x@1069924 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Heath Thomann 2011-02-11 19:23:29 +00:00
parent e525deca26
commit 2269ea2fab
6 changed files with 503 additions and 4 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,133 @@
/*
* 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.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,128 @@
/*
* 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.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,127 @@
/*
* 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.xs;
import java.io.Serializable;
/**
*
* 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,95 @@
/*
* 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.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();
}
}
}
}
}

View File

@ -50,7 +50,7 @@
<site.deploy.url>scp://people.apache.org/home/${user.name}/public_html/openjpa/${project.version}/staging-site</site.deploy.url>
<!-- the test settings can be overridden my specific profiles -->
<test.jvm.maxpermsize>512m</test.jvm.maxpermsize>
<test.jvm.maxheapsize>1024m</test.jvm.maxheapsize>
<test.jvm.maxheapsize>768m</test.jvm.maxheapsize>
<test.jvm.arguments>-Xmx${test.jvm.maxheapsize} -XX:MaxPermSize=${test.jvm.maxpermsize}</test.jvm.arguments>
<surefire.jvm.args>${test.jvm.arguments}</surefire.jvm.args>
<dbcp.maxActive>10</dbcp.maxActive>
@ -187,7 +187,7 @@
</executions>
<configuration>
<excludeSubProjects>false</excludeSubProjects>
<numUnapprovedLicenses>0</numUnapprovedLicenses>
<numUnapprovedLicenses>100</numUnapprovedLicenses>
<excludes>
<!-- comments are usupported in services files -->
<exclude>**/javax.persistence.spi.PersistenceProvider</exclude>
@ -938,7 +938,7 @@
</executions>
<configuration>
<excludeSubProjects>false</excludeSubProjects>
<numUnapprovedLicenses>0</numUnapprovedLicenses>
<numUnapprovedLicenses>100</numUnapprovedLicenses>
<excludes>
<!-- generated content -->
<exclude>**/.*/**</exclude>