mirror of https://github.com/apache/openjpa.git
OPENJPA-692: Add Test cases for Bi-directional mapping with JoinTable
git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@684443 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
6dbe8a9e57
commit
e7c3df714b
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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.jdbc.mapping.bidi;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
/**
|
||||
* Demonstrate usage of a JoinTable for a bi-directional one-to-many mapping.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
@Entity
|
||||
@Table(name="J_ADDRESS")
|
||||
public class Address {
|
||||
@Id
|
||||
private String phone;
|
||||
|
||||
private String city;
|
||||
private int zip;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(table="J_PERSON_ADDRESSES", referencedColumnName="SSN")
|
||||
private Person person;
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
public String getCity() {
|
||||
return city;
|
||||
}
|
||||
|
||||
public void setCity(String city) {
|
||||
this.city = city;
|
||||
}
|
||||
|
||||
public int getZip() {
|
||||
return zip;
|
||||
}
|
||||
|
||||
public void setZip(int zip) {
|
||||
this.zip = zip;
|
||||
}
|
||||
|
||||
public Person getPerson() {
|
||||
return person;
|
||||
}
|
||||
|
||||
public void setPerson(Person person) {
|
||||
this.person = person;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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.jdbc.mapping.bidi;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
|
||||
import org.apache.openjpa.jdbc.meta.strats.RelationCollectionTableFieldStrategy;
|
||||
import org.apache.openjpa.persistence.jdbc.Strategy;
|
||||
|
||||
/**
|
||||
* Demonstrate usage of a JoinTable for a bi-directional one-to-many mapping.
|
||||
*
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
@Entity
|
||||
@Table(name="J_PERSON")
|
||||
public class Person {
|
||||
@Id
|
||||
private long ssn;
|
||||
|
||||
private String name;
|
||||
|
||||
@OneToMany(cascade=CascadeType.ALL)
|
||||
@JoinTable(name="J_PERSON_ADDRESSES",
|
||||
joinColumns = @JoinColumn(name="PERSON_SSN", referencedColumnName="SSN"),
|
||||
inverseJoinColumns = @JoinColumn(name="ADDRESS_PHONE", referencedColumnName="PHONE"))
|
||||
private Set<Address> addresses = new HashSet<Address>();
|
||||
|
||||
public long getSsn() {
|
||||
return ssn;
|
||||
}
|
||||
|
||||
public Set<Address> getAddresses() {
|
||||
return addresses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep bi-directional relation consistent.
|
||||
*/
|
||||
public void addAddress(Address address) {
|
||||
if (addresses == null)
|
||||
addresses = new HashSet<Address>();
|
||||
addresses.add(address);
|
||||
address.setPerson(this);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void setSsn(long ssn) {
|
||||
this.ssn = ssn;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
/*
|
||||
* 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.jdbc.mapping.bidi;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
|
||||
import org.apache.openjpa.persistence.OpenJPAPersistence;
|
||||
import org.apache.openjpa.persistence.test.SQLListenerTestCase;
|
||||
|
||||
/**
|
||||
* Tests basic persistence operations on bi-directional mapping that uses a
|
||||
* JoinTable.
|
||||
*
|
||||
* Originally reported as an error which shows that
|
||||
* a) rows in join table get repeated insert as bi-directional mapping is
|
||||
* essentially modeled as two uni-directional mapping
|
||||
* b) update/delete fails with OptimisticExecption because of repeated operation
|
||||
* on the join table row
|
||||
*
|
||||
* Further details available at
|
||||
* <A HREF="https://issues.apache.org/jira/browse/OPENJPA-692">OPENJPA-692</A>
|
||||
* and
|
||||
* <A HREF="http://n2.nabble.com/bidirectional-one-to-many-relationship-with-join-table-tc678479.html">Nabble posts</A>
|
||||
*
|
||||
* @author Pinaki Poddar
|
||||
*
|
||||
*/
|
||||
public class TestBiDirectionalJoinTable extends SQLListenerTestCase {
|
||||
private static long SSN = 123456789;
|
||||
private static String[] PHONES = {"+1-23-456", "+2-34-567", "+3-45-678"};
|
||||
private static int ADDRESS_COUNT = PHONES.length;
|
||||
private static String[] CITIS = {"Berlin", "Paris", "Rome"};
|
||||
private static int[] ZIPS = {123456, 234567, 345678};
|
||||
|
||||
public void setUp() {
|
||||
super.setUp(CLEAR_TABLES, Person.class, Address.class);
|
||||
createData(SSN);
|
||||
sql.clear();
|
||||
}
|
||||
|
||||
public void testPersist() {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
Person person = em.find(Person.class, SSN);
|
||||
assertNotNull(person);
|
||||
|
||||
assertEquals(ADDRESS_COUNT, person.getAddresses().size());
|
||||
}
|
||||
|
||||
public void testQuery() {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
String jpql = "select distinct a.city from Person as p, in(p.addresses) a";
|
||||
Query query = em.createQuery(jpql);
|
||||
assertEquals(ADDRESS_COUNT, query.getResultList().size());
|
||||
}
|
||||
|
||||
public void testUpdate() {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
Person person = em.find(Person.class, SSN);
|
||||
Address newAddress = new Address();
|
||||
newAddress.setPhone("+4-56-789");
|
||||
newAddress.setCity("San Francisco");
|
||||
person.addAddress(newAddress);
|
||||
person.setName("Frank");
|
||||
em.merge(person);
|
||||
em.getTransaction().commit();
|
||||
|
||||
em = emf.createEntityManager();
|
||||
Person updated = em.find(Person.class, SSN);
|
||||
assertEquals("Frank", updated.getName());
|
||||
assertEquals(ADDRESS_COUNT+1, updated.getAddresses().size());
|
||||
}
|
||||
|
||||
public void testRemove() {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
Person person = em.find(Person.class, SSN);
|
||||
em.remove(person);
|
||||
em.getTransaction().commit();
|
||||
|
||||
assertEquals(0, count(Person.class));
|
||||
assertEquals(0, count(Address.class));
|
||||
assertSQL("DELETE FROM .*J_PERSON_ADDRESSES .*");
|
||||
}
|
||||
|
||||
public void testSingleDelete() {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
String jpql = "delete from Person p where p.ssn=:ssn";
|
||||
em.createQuery(jpql).setParameter("ssn", SSN).executeUpdate();
|
||||
em.getTransaction().commit();
|
||||
|
||||
assertEquals(0, count(Person.class));
|
||||
assertEquals(0, count(Address.class));
|
||||
assertSQL("DELETE FROM .*J_PERSON_ADDRESSES .*");
|
||||
}
|
||||
|
||||
public void testBulkDelete() {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
String jpql = "delete from Person p";
|
||||
em.createQuery(jpql).executeUpdate();
|
||||
em.getTransaction().commit();
|
||||
|
||||
assertEquals(0, count(Person.class));
|
||||
assertEquals(0, count(Address.class));
|
||||
assertSQL("DELETE FROM .*J_PERSON_ADDRESSES .*");
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Person with given SSN and fixed number of addresses.
|
||||
*
|
||||
* @param ssn
|
||||
*/
|
||||
void createData(long ssn) {
|
||||
EntityManager em = emf.createEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
||||
sql.clear();
|
||||
Person person = new Person();
|
||||
person.setSsn(SSN);
|
||||
person.setName("Pinaki");
|
||||
for (int i=0; i<PHONES.length; i++) {
|
||||
Address address = new Address();
|
||||
address.setPhone(PHONES[i]);
|
||||
address.setCity(CITIS[i]);
|
||||
address.setZip(ZIPS[i]);
|
||||
person.addAddress(address);
|
||||
}
|
||||
em.persist(person);
|
||||
em.getTransaction().commit();
|
||||
assertEquals(1+2*ADDRESS_COUNT, sql.size());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void tearDown() {
|
||||
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue