OPENJPA-870: orm support for OrphanRemoval

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@740781 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Fay Wang 2009-02-04 16:31:54 +00:00
parent d61b3b26a9
commit 4d5a6c5e56
12 changed files with 430 additions and 38 deletions

View File

@ -1,3 +1,21 @@
/*
* 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.embed;
import javax.persistence.*;

View File

@ -0,0 +1,84 @@
/*
* 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.embed;
import java.util.HashSet;
import java.util.Set;
public class CustomerXml {
protected int id;
protected String name;
protected Set<OrderXml> orders = new HashSet<OrderXml>();
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<OrderXml> getOrders() {
return orders;
}
public void setOrders(Set<OrderXml> orders) {
this.orders = orders;
}
public void addOrder(OrderXml order) {
orders.add(order);
}
public boolean equals(Object obj) {
CustomerXml c0 = (CustomerXml) obj;
if (c0 == null) return false;
if (c0.getId() != id) return false;
if (!c0.getName().equals(name)) return false;
Set<OrderXml> orders0 = c0.getOrders();
if (orders0.size() != orders.size())
return false;
for (OrderXml o : orders) {
if (!contains(orders0, o))
return false;
}
return true;
}
private boolean contains(Set<OrderXml> orders0, OrderXml o) {
int id = o.getId();
for (OrderXml o0 : orders0) {
if (o0.getId() == id)
return true;
}
return false;
}
}

View File

@ -1,7 +1,24 @@
/*
* 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.embed;
import javax.persistence.*;
import java.util.*;
@Embeddable
public class JobInfo {

View File

@ -1,3 +1,21 @@
/*
* 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.embed;
import javax.persistence.*;

View File

@ -0,0 +1,61 @@
/*
* 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.embed;
public class OrderXml {
protected int id;
protected String description;
protected CustomerXml cust;
public CustomerXml getCust() {
return cust;
}
public void setCust(CustomerXml cust) {
this.cust = cust;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getDescription() {
return description;
}
public void setDescription(String desc) {
this.description = desc;
}
public boolean equals(Object obj) {
OrderXml o0 = (OrderXml) obj;
if (o0 == null) return false;
if (o0.getId() != id) return false;
if (!o0.getDescription().equals(description)) return false;
if (!o0.getCust().equals(cust)) return false;
return true;
}
}

View File

@ -1,3 +1,21 @@
/*
* 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.embed;
import javax.persistence.*;

View File

@ -1,3 +1,21 @@
/*
* 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.embed;
import javax.persistence.*;

View File

@ -1,3 +1,21 @@
/*
* 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.embed;
import javax.persistence.*;

View File

@ -44,12 +44,16 @@ public class TestEmbeddableXml extends SingleEMFTestCase {
public int newVpId = 100;
public int numItems = 2;
public int itemId = 1;
public int cId = 1;
public int oId = 1;
public int numImagesPerItem = 3;
public int numDepartments = 2;
public int numEmployeesPerDept = 2;
public int numCompany = 2;
public int numDivisionsPerCo = 2;
public int numCustomers = 1;
public int numOrdersPerCustomer = 2;
public void setUp() {
setUp(CLEAR_TABLES);
@ -625,5 +629,107 @@ public class TestEmbeddableXml extends SingleEMFTestCase {
public void assertVicePresident(VicePresidentXml vp) {
int id = vp.getId();
String name = vp.getName();
}
}
public void createOrphanRemoval() {
EntityManager em = emf.createEntityManager();
EntityTransaction tran = em.getTransaction();
for (int i = 0; i < numCustomers; i++)
createCustomer(em, cId++);
tran.begin();
em.flush();
tran.commit();
em.close();
}
public CustomerXml createCustomer(EntityManager em, int id) {
CustomerXml c = new CustomerXml();
c.setId(id);
c.setName("name" + id);
for (int i = 0; i < numOrdersPerCustomer; i++) {
OrderXml order = createOrder(em, oId++);
c.addOrder(order);
order.setCust(c);
em.persist(order);
}
em.persist(c);
return c;
}
public OrderXml createOrder(EntityManager em, int id) {
OrderXml o = new OrderXml();
o.setId(id);
em.persist(o);
return o;
}
public void testOrphanRemovalTarget() {
createOrphanRemoval();
EntityManager em = emf.createEntityManager();
int count = count(OrderXml.class);
assertEquals(numOrdersPerCustomer * numCustomers, count);
CustomerXml c = em.find(CustomerXml.class, 1);
Set<OrderXml> orders = c.getOrders();
assertEquals(numOrdersPerCustomer, orders.size());
// OrphanRemoval: remove target: the order will be deleted from db
for (OrderXml order : orders) {
orders.remove(order);
break;
}
em.getTransaction().begin();
em.persist(c);
em.flush();
em.getTransaction().commit();
em.clear();
c = em.find(CustomerXml.class, 1);
orders = c.getOrders();
assertEquals(numOrdersPerCustomer - 1, orders.size());
count = count(OrderXml.class);
assertEquals(numOrdersPerCustomer * numCustomers - 1, count);
em.close();
}
public void testOrphanRemovalTargetSetNull() {
createOrphanRemoval();
EntityManager em = emf.createEntityManager();
CustomerXml c = em.find(CustomerXml.class, 1);
System.err.println("C name = " + c.getName());
System.err.println("size before = " + c.getOrders().size());
c.setOrders(null);
em.getTransaction().begin();
em.persist(c);
em.flush();
em.getTransaction().commit();
em.clear();
int count = count(OrderXml.class);
assertEquals(numOrdersPerCustomer * (numCustomers - 1), count);
c = em.find(CustomerXml.class, 1);
Set<OrderXml> orders = c.getOrders();
if (orders != null)
assertEquals(0, orders.size());
em.close();
}
public void testOrphanRemovalSource() {
createOrphanRemoval();
EntityManager em = emf.createEntityManager();
// OrphanRemoval: remove source
CustomerXml c = em.find(CustomerXml.class, 1);
em.getTransaction().begin();
em.remove(c);
em.flush();
em.getTransaction().commit();
em.clear();
int count = count(OrderXml.class);
assertEquals(numOrdersPerCustomer * (numCustomers - 1), count);
em.close();
}
}

View File

@ -39,6 +39,7 @@
class.
</description>
<mapping-file>org/apache/openjpa/persistence/xml/orm.xml</mapping-file>
<mapping-file>org/apache/openjpa/persistence/embed/embed-orm.xml</mapping-file>
<properties>
<property name="openjpa.jdbc.SynchronizeMappings"
value="buildSchema(ForeignKeys=true)"/>
@ -107,6 +108,8 @@
<class>org.apache.openjpa.persistence.embed.EntityA_Coll_Embed_EmbedXml</class>
<class>org.apache.openjpa.persistence.embed.Embed_EmbedXml</class>
<class>org.apache.openjpa.persistence.embed.EmbedXml</class>
<class>org.apache.openjpa.persistence.embed.CustomerXml</class>
<class>org.apache.openjpa.persistence.embed.OrderXml</class>
<properties>
<property name="openjpa.jdbc.SynchronizeMappings"
value="buildSchema(ForeignKeys=true)"/>

View File

@ -123,40 +123,60 @@ version="2.0">
</one-to-many>
</attributes>
</entity>
<embeddable class="org.apache.openjpa.persistence.embed.Embed_EmbedXml"
access="FIELD">
<attributes>
<basic name="intVal1">
</basic>
<basic name="intVal2">
</basic>
<basic name="intVal3">
</basic>
<embedded name="embed">
<attribute-override name="intVal1">
<column name="embed_intVal1"/>
</attribute-override>
<attribute-override name="intVal2">
<column name="embed_intVal2"/>
</attribute-override>
<attribute-override name="intVal3">
<column name="embed_intVal3"/>
</attribute-override>
</embedded>
</attributes>
</embeddable>
<embeddable class="org.apache.openjpa.persistence.embed.EmbedXml"
access="FIELD">
<attributes>
<basic name="intVal1">
</basic>
<basic name="intVal2">
</basic>
<basic name="intVal3">
</basic>
</attributes>
</embeddable>
<entity name="CustomerXml"
class="org.apache.openjpa.persistence.embed.CustomerXml"
access="FIELD">
<table name="Customer_XML" />
<attributes>
<id name="id"></id>
<basic name="name" />
<one-to-many name="orders" mapped-by="cust"
orphan-removal="true" />
</attributes>
</entity>
<entity name="OrderXml"
class="org.apache.openjpa.persistence.embed.OrderXml"
access="FIELD">
<table name="Order_XML" />
<attributes>
<id name="id"></id>
<basic name="description" />
<many-to-one name="cust">
<join-column name="CUST_ID" nullable="false" />
</many-to-one>
</attributes>
</entity>
<embeddable
class="org.apache.openjpa.persistence.embed.Embed_EmbedXml"
access="FIELD">
<attributes>
<basic name="intVal1"></basic>
<basic name="intVal2"></basic>
<basic name="intVal3"></basic>
<embedded name="embed">
<attribute-override name="intVal1">
<column name="embed_intVal1" />
</attribute-override>
<attribute-override name="intVal2">
<column name="embed_intVal2" />
</attribute-override>
<attribute-override name="intVal3">
<column name="embed_intVal3" />
</attribute-override>
</embedded>
</attributes>
</embeddable>
<embeddable class="org.apache.openjpa.persistence.embed.EmbedXml"
access="FIELD">
<attributes>
<basic name="intVal1"></basic>
<basic name="intVal2"></basic>
<basic name="intVal3"></basic>
</attributes>
</embeddable>
</entity-mappings>

View File

@ -1392,6 +1392,9 @@ public class XMLPersistenceMetaDataParser
fmd.setSerialized(false); // override any Lob annotation
if (!fmd.isDefaultFetchGroupExplicit())
fmd.setInDefaultFetchGroup(true);
boolean orphanRemoval = Boolean.valueOf(attrs.getValue(
"orphan-removal"));
setOrphanRemoval(fmd, orphanRemoval);
}
/**
@ -1448,8 +1451,16 @@ public class XMLPersistenceMetaDataParser
fmd.getElement().setDeclaredType(classForName(val));
assertPCCollection(fmd, "OneToMany");
fmd.setSerialized(false); // override any Lob annotation
boolean orphanRemoval = Boolean.valueOf(attrs.getValue(
"orphan-removal"));
setOrphanRemoval(fmd.getElement(), orphanRemoval);
}
protected void setOrphanRemoval(ValueMetaData vmd, boolean orphanRemoval) {
if (orphanRemoval)
vmd.setCascadeDelete(ValueMetaData.CASCADE_AUTO);
}
protected void parseElementCollection(FieldMetaData fmd, Attributes attrs)
throws SAXException {
String val = attrs.getValue("target-entity");