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:
Pinaki Poddar 2008-08-10 10:12:37 +00:00
parent 6dbe8a9e57
commit e7c3df714b
3 changed files with 326 additions and 0 deletions

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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() {
}
}