mirror of https://github.com/apache/openjpa.git
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:
parent
e525deca26
commit
2269ea2fab
|
@ -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;
|
||||
|
|
|
@ -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() + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
6
pom.xml
6
pom.xml
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue