mirror of https://github.com/apache/openjpa.git
OPENJPA-715. Committing the testcase provided by Ekin Sokmen and the patch provided by Fay Wang. Committing the change for both the 1.2.x service stream and 1.3.0 snapshot (trunk).
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@693287 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
8e6db6cb65
commit
4aa64410ad
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* 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.relations;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
|
import javax.persistence.Version;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class ChainEntityA {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private long aId;
|
||||||
|
|
||||||
|
@Version
|
||||||
|
private Integer optLock;
|
||||||
|
|
||||||
|
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||||
|
protected Set<ChainEntityB> chainEntityBSet;
|
||||||
|
|
||||||
|
public ChainEntityA () {
|
||||||
|
super ();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addChildEntityB (ChainEntityB bean) {
|
||||||
|
if (null == chainEntityBSet)
|
||||||
|
chainEntityBSet = new LinkedHashSet<ChainEntityB> ();
|
||||||
|
chainEntityBSet.add (bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<ChainEntityB> getChildren () {
|
||||||
|
if (null == chainEntityBSet)
|
||||||
|
chainEntityBSet = new LinkedHashSet<ChainEntityB> ();
|
||||||
|
return chainEntityBSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName () {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName (String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId () {
|
||||||
|
return aId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId (long id) {
|
||||||
|
this.aId = id;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* 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.relations;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.Version;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class ChainEntityB {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private long bId;
|
||||||
|
|
||||||
|
@Version
|
||||||
|
private Integer optLock;
|
||||||
|
|
||||||
|
//cascade = CascadeType.ALL,
|
||||||
|
@OneToMany(cascade=CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "chainEntityB")
|
||||||
|
protected Set<ChainEntityC> chainEntityCSet = null;
|
||||||
|
|
||||||
|
public void addChainEntityC (ChainEntityC bean) {
|
||||||
|
if (null == chainEntityCSet)
|
||||||
|
chainEntityCSet = new LinkedHashSet<ChainEntityC> ();
|
||||||
|
chainEntityCSet.add (bean);
|
||||||
|
bean.setChainEntityB (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<ChainEntityC> getChainEntityCSet () {
|
||||||
|
if (null == chainEntityCSet)
|
||||||
|
chainEntityCSet = new LinkedHashSet<ChainEntityC> ();
|
||||||
|
return chainEntityCSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName () {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName (String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId () {
|
||||||
|
return bId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId (long id) {
|
||||||
|
this.bId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* 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.relations;
|
||||||
|
|
||||||
|
import javax.persistence.Basic;
|
||||||
|
import javax.persistence.CascadeType;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
|
import javax.persistence.GeneratedValue;
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.Version;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class ChainEntityC {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@GeneratedValue
|
||||||
|
private long cId;
|
||||||
|
|
||||||
|
@Version
|
||||||
|
private Integer optLock;
|
||||||
|
|
||||||
|
@ManyToOne(fetch = FetchType.EAGER, cascade=CascadeType.ALL)
|
||||||
|
protected ChainEntityB chainEntityB;
|
||||||
|
|
||||||
|
@Basic
|
||||||
|
protected long chainEntityBId;
|
||||||
|
|
||||||
|
public void setChainEntityB (ChainEntityB b) {
|
||||||
|
this.chainEntityB = b;
|
||||||
|
// this.chainEntityBId = null == b ? 0 : b.getId ();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public String getName () {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName (String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getId () {
|
||||||
|
return cId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId (long id) {
|
||||||
|
this.cId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,117 @@
|
||||||
|
/*
|
||||||
|
* 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.relations;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
|
||||||
|
import org.apache.openjpa.persistence.test.SingleEMFTestCase;
|
||||||
|
|
||||||
|
public class TestChainEntities extends SingleEMFTestCase {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set this magical number to 3 or less to avoid the error.
|
||||||
|
*/
|
||||||
|
private static final int MAGICAL_NUMBER = 50;
|
||||||
|
|
||||||
|
long aid;
|
||||||
|
|
||||||
|
public void setUp () {
|
||||||
|
setUp (ChainEntityA.class, ChainEntityB.class, ChainEntityC.class);
|
||||||
|
// Create A
|
||||||
|
ChainEntityA a = new ChainEntityA ();
|
||||||
|
a.setName ("TEST_A");
|
||||||
|
// Persist A
|
||||||
|
EntityManager em = emf.createEntityManager ();
|
||||||
|
em.getTransaction ().begin ();
|
||||||
|
em.persist (a);
|
||||||
|
aid = a.getId ();
|
||||||
|
em.getTransaction ().commit ();
|
||||||
|
em.close ();
|
||||||
|
System.out.println ("ChainEntityA id = " + aid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testChainEntities () {
|
||||||
|
chainUpdate ();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void chainUpdate () {
|
||||||
|
// Get A
|
||||||
|
ChainEntityA a = getA ();
|
||||||
|
// Create B
|
||||||
|
ChainEntityB b = new ChainEntityB ();
|
||||||
|
b.setName ("Test_B_");
|
||||||
|
ChainEntityC c;
|
||||||
|
/*
|
||||||
|
* Create and add C to B. Increasing the number of iterations (number of
|
||||||
|
* ChainEntityC) increases the probability to get the unique key
|
||||||
|
* constraint violation error.
|
||||||
|
*/
|
||||||
|
for (int i = 1; i <= MAGICAL_NUMBER; i++) {
|
||||||
|
c = new ChainEntityC ();
|
||||||
|
c.setName ("Test_C_" + i);
|
||||||
|
b.addChainEntityC (c);
|
||||||
|
}
|
||||||
|
a.addChildEntityB (b);
|
||||||
|
// dump (a); // debug
|
||||||
|
// Merge A
|
||||||
|
EntityManager em = emf.createEntityManager ();
|
||||||
|
em.getTransaction ().begin ();
|
||||||
|
a = em.merge (a);
|
||||||
|
/*
|
||||||
|
* workaround: Uncommenting following line is a workaround. If we
|
||||||
|
* retrive Ids of ChainEntityC objects after merge but before commit we
|
||||||
|
* don't get the error.
|
||||||
|
*/
|
||||||
|
//dump (a);
|
||||||
|
em.getTransaction ().commit ();
|
||||||
|
em.close ();
|
||||||
|
// dump (getA ()); // debug
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get created ChainEntityA using aid field.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
protected ChainEntityA getA () {
|
||||||
|
EntityManager em = emf.createEntityManager ();
|
||||||
|
ChainEntityA a = em.find (ChainEntityA.class, aid);
|
||||||
|
em.close ();
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Print the object graph of given ChainEntityA to System.out
|
||||||
|
*
|
||||||
|
* @param testA
|
||||||
|
*/
|
||||||
|
protected void dump (ChainEntityA testA) {
|
||||||
|
System.out.println ("-------");
|
||||||
|
System.out.println (testA.getName () + "[" + testA.getId () + "]");
|
||||||
|
for (ChainEntityB testB : testA.getChildren ()) {
|
||||||
|
System.out.println (testB.getName () + "[" + testB.getId () + "]");
|
||||||
|
for (ChainEntityC testC : testB.getChainEntityCSet ()) {
|
||||||
|
System.out.println (testC.getName () + "[" + testC.getId ()
|
||||||
|
+ "]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println ("-------");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue