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