OPENJPA-1053: fix update by setting an embeddable which contains a cascade delete relation with another entity.

git-svn-id: https://svn.apache.org/repos/asf/openjpa/trunk@769879 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Fay Wang 2009-04-29 19:08:11 +00:00
parent 14ae1c34cf
commit 1677b481b2
7 changed files with 323 additions and 7 deletions

View File

@ -2658,8 +2658,11 @@ public class BrokerImpl
// ACT_CASCADE
if ((action & OpCallbacks.ACT_RUN) == 0) {
if (sm != null)
sm.cascadeDelete(call);
if (sm != null) {
if (!sm.isEmbedded() || !sm.getDereferencedEmbedDependent()) {
sm.cascadeDelete(call);
}
}
else
cascadeTransient(OpCallbacks.OP_DELETE, obj, call, "delete");
return;
@ -2669,8 +2672,11 @@ public class BrokerImpl
if (sm != null) {
if (sm.isDetached())
throw newDetachedException(obj, "delete");
if ((action & OpCallbacks.ACT_CASCADE) != 0)
sm.cascadeDelete(call);
if ((action & OpCallbacks.ACT_CASCADE) != 0) {
if (!sm.isEmbedded() || !sm.getDereferencedEmbedDependent()) {
sm.cascadeDelete(call);
}
}
sm.delete();
} else if (assertPersistenceCapable(obj).pcIsDetached() == Boolean.TRUE)
throw newDetachedException(obj, "delete");

View File

@ -302,8 +302,11 @@ class SingleFieldManager
// immediate cascade works on field value; dependent deref
// works on external value
if ((immediate || fmd.isEmbeddedPC())
&& fmd.getCascadeDelete() == ValueMetaData.CASCADE_IMMEDIATE)
&& fmd.getCascadeDelete() == ValueMetaData.CASCADE_IMMEDIATE) {
if (fmd.isEmbeddedPC())
dereferenceEmbedDependent(_sm);
delete(fmd, objval, call);
}
else if (fmd.getCascadeDelete() == ValueMetaData.CASCADE_AUTO)
dereferenceDependent(fmd.getExternalValue(objval, _broker));
return;
@ -413,7 +416,11 @@ class SingleFieldManager
if (sm != null)
sm.setDereferencedDependent(true, true);
}
void dereferenceEmbedDependent(StateManagerImpl sm) {
sm.setDereferencedEmbedDependent(true);
}
/**
* Recursively invoke the broker to gather cascade-refresh objects in
* the current field into the given set. This method is only called

View File

@ -107,6 +107,7 @@ public class StateManagerImpl
private static final int FLAG_VERSION_CHECK = 2 << 14;
private static final int FLAG_VERSION_UPDATE = 2 << 15;
private static final int FLAG_DETACHING = 2 << 16;
private static final int FLAG_EMBED_DEREF = 2 << 17;
private static final Localizer _loc = Localizer.forPackage
(StateManagerImpl.class);
@ -1300,6 +1301,18 @@ public class StateManagerImpl
_broker.addDereferencedDependent(this);
}
}
void setDereferencedEmbedDependent(boolean deref) {
if (!deref && (_flags & FLAG_EMBED_DEREF) > 0) {
_flags &= ~FLAG_EMBED_DEREF;
} else if (deref && (_flags & FLAG_EMBED_DEREF) == 0) {
_flags |= FLAG_EMBED_DEREF;
}
}
public boolean getDereferencedEmbedDependent() {
return ((_flags |= FLAG_EMBED_DEREF) == 0 ? false : true);
}
///////////
// Locking

View File

@ -0,0 +1,67 @@
/*
* 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.CascadeType;
import javax.persistence.Embeddable;
import javax.persistence.FetchType;
import javax.persistence.OneToOne;
@Embeddable
public class Embed_MappedToOneCascadeDelete {
protected String name1;
protected String name2;
protected String name3;
@OneToOne(mappedBy="entityA", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
protected EntityB2 bm;
public String getName1() {
return name1;
}
public void setName1(String name1) {
this.name1 = name1;
}
public String getName2() {
return name2;
}
public void setName2(String name2) {
this.name2 = name2;
}
public String getName3() {
return name3;
}
public void setName3(String name3) {
this.name3 = name3;
}
public void setMappedEntityB(EntityB2 bm) {
this.bm = bm;
}
public EntityB2 getMappedEntityB() {
return bm;
}
}

View File

@ -0,0 +1,77 @@
/*
* 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.io.Serializable;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Embedded;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="TB11A")
public class EntityA_Embed_MappedToOneCascadeDelete implements Serializable {
@Id
Integer id;
@Column(length=30)
String name;
@Basic(fetch=FetchType.LAZY)
int age;
@Embedded
protected Embed_MappedToOneCascadeDelete embed;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Embed_MappedToOneCascadeDelete getEmbed() {
return embed;
}
public void setEmbed(Embed_MappedToOneCascadeDelete embed) {
this.embed = embed;
}
}

View File

@ -0,0 +1,65 @@
/*
* 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.io.Serializable;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
@Entity
public class EntityB2 implements Serializable {
@Id
int id;
@Column(length=30)
String name;
@OneToOne(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
EntityA_Embed_MappedToOneCascadeDelete entityA;
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 EntityA_Embed_MappedToOneCascadeDelete getEntityA() {
return entityA;
}
public void setEntityA(EntityA_Embed_MappedToOneCascadeDelete entityA) {
this.entityA = entityA;
}
}

View File

@ -79,7 +79,9 @@ public class TestEmbeddable extends SingleEMFTestCase {
Employee3.class, EmployeeName3.class, Item1.class, Item2.class,
Item3.class, Company1.class, Company2.class, Division.class,
VicePresident.class, EntityA_Embed_MappedToOne.class,
Embed_MappedToOne.class, DROP_TABLES);
Embed_MappedToOne.class, Embed_MappedToOneCascadeDelete.class,
EntityA_Embed_MappedToOneCascadeDelete.class, EntityB2.class,
DROP_TABLES);
}
public void testEntityA_Coll_String() {
@ -160,6 +162,11 @@ public class TestEmbeddable extends SingleEMFTestCase {
findObjMapKeyClass();
}
public void testEntityA_Embed_MappedToOneCascadeDelete() {
createEntityA_Embed_MappedToOneCascadeDelete();
updateEntityA_Embed_MappedToOneCascadeDelete();
}
/*
* Create EntityA_Coll_String
*/
@ -257,6 +264,80 @@ public class TestEmbeddable extends SingleEMFTestCase {
return embed;
}
/*
* Create EntityA_Embed_MappedToOneCascadeDelete
*/
public void createEntityA_Embed_MappedToOneCascadeDelete() {
EntityManager em = emf.createEntityManager();
EntityTransaction tran = em.getTransaction();
createEntityA_Embed_MappedToOneCascadeDelete(em, ID);
tran.begin();
em.flush();
tran.commit();
em.close();
}
public void createEntityA_Embed_MappedToOneCascadeDelete(EntityManager em,
int id) {
EntityA_Embed_MappedToOneCascadeDelete a =
new EntityA_Embed_MappedToOneCascadeDelete();
a.setId(id);
a.setName("a" + id);
a.setAge(id);
Embed_MappedToOneCascadeDelete embed =
createEmbed_MappedToOneDeleteCascade(em, id, a);
a.setEmbed(embed);
em.persist(a);
}
public Embed_MappedToOneCascadeDelete createEmbed_MappedToOneDeleteCascade(
EntityManager em, int id, EntityA_Embed_MappedToOneCascadeDelete a) {
Embed_MappedToOneCascadeDelete embed = new Embed_MappedToOneCascadeDelete();
embed.setName1("name1");
embed.setName2("name2");
embed.setName3("name3");
EntityB2 b = new EntityB2();
b.setId(id);
b.setName("bm" + id);
b.setEntityA(a);
embed.setMappedEntityB(b);
em.persist(b);
return embed;
}
/*
* Update EntityA_Embed_MappedToOneCascadeDelete
*/
public void updateEntityA_Embed_MappedToOneCascadeDelete() {
EntityManager em = emf.createEntityManager();
EntityTransaction tran = em.getTransaction();
updateEntityA_Embed_MappedToOneCascadeDelete(em, ID);
tran.begin();
em.flush();
tran.commit();
em.clear();
EntityA_Embed_MappedToOneCascadeDelete a =
em.find(EntityA_Embed_MappedToOneCascadeDelete.class, ID);
assertNotNull(a);
EntityB2 b2 = em.find(EntityB2.class, ID);
assertNotNull(b2);
em.close();
}
public void updateEntityA_Embed_MappedToOneCascadeDelete(EntityManager em,
int id) {
EntityA_Embed_MappedToOneCascadeDelete a =
em.find(EntityA_Embed_MappedToOneCascadeDelete.class, id);
a.setName("newa" + id);
a.setAge(id + 1);
Embed_MappedToOneCascadeDelete embed =
createEmbed_MappedToOneDeleteCascade(em, id+1, a);
a.setEmbed(embed);
}
/*
* Create EntityA_Coll_Embed_ToOne
*/