| /* |
| * Copyright (c) 2005, 2021 Oracle and/or its affiliates. All rights reserved. |
| * Copyright (c) 2005, 2015 SAP. All rights reserved. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * http://www.eclipse.org/legal/epl-2.0, |
| * or the Eclipse Distribution License v. 1.0 which is available at |
| * http://www.eclipse.org/org/documents/edl-v10.php. |
| * |
| * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause |
| */ |
| |
| // Contributors: |
| // SAP - initial API and implementation |
| |
| package org.eclipse.persistence.testing.tests.wdf.jpa1.entitymanager; |
| |
| import java.util.Set; |
| |
| import jakarta.persistence.EntityManager; |
| |
| import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment; |
| import org.eclipse.persistence.testing.framework.wdf.ToBeInvestigated; |
| import org.eclipse.persistence.testing.models.wdf.jpa1.node.CascadingNode; |
| import org.eclipse.persistence.testing.models.wdf.jpa1.node.CascadingNodeDescription; |
| import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base; |
| import org.junit.Test; |
| |
| public class TestCascadeMerge extends JPA1Base { |
| |
| @Test |
| @ToBeInvestigated |
| public void testCascadeNew() { |
| /* |
| * If X is a new entity instance, a new managed entity instance X' is created and the state of X is copied into the new |
| * managed entity instance X'. |
| * |
| * For all entities Y referenced by relationships from X having the cascade element value cascade=MERGE or cascade=ALL, |
| * Y is merged recursively as Y'. For all such Y referenced by X, X' is set to reference Y'. (Note that if X is managed |
| * then X is the same object as X'.) |
| */ |
| final JPAEnvironment env = getEnvironment(); |
| final EntityManager em = env.getEntityManager(); |
| try { |
| CascadingNode parent = new CascadingNode(1, null); |
| CascadingNodeDescription parentDescription = new CascadingNodeDescription(2, null, "new parent"); |
| parent.setDescription(parentDescription); |
| CascadingNode child = new CascadingNode(3, null); |
| CascadingNodeDescription childDescription = new CascadingNodeDescription(4, null, "new child"); |
| child.setDescription(childDescription); |
| CascadingNode grandchild = new CascadingNode(5, null); |
| CascadingNodeDescription grandchildDescription = new CascadingNodeDescription(6, null, "new grandchild"); |
| grandchild.setDescription(grandchildDescription); |
| parent.addChild(child); |
| child.addChild(grandchild); |
| env.beginTransaction(em); |
| CascadingNode mergedNode = em.merge(parent); |
| verify(mergedNode.getId() == parent.getId(), "merged entity has wrong id: expected " + parent.getId() + ", got " |
| + mergedNode.getId()); |
| verify(mergedNode != parent, "merged entity not a copy"); |
| verify(em.contains(mergedNode), "merged entity not managed"); |
| CascadingNodeDescription mergedDescription = mergedNode.getDescription(); |
| verify(mergedDescription.getId() == parentDescription.getId(), "merged entity has wrong id: expected " |
| + parentDescription.getId() + ", got " + mergedDescription.getId()); |
| verify(mergedDescription != parentDescription, "merged entity not a copy"); |
| verify(em.contains(mergedDescription), "merged entity not managed"); |
| Set<CascadingNode> mergedChildren = mergedNode.getChildren(); |
| verify(mergedChildren.size() == 1, "Wrong number of children: expected 1, got " + mergedChildren.size()); |
| for (CascadingNode temp : mergedChildren) { |
| mergedNode = temp; |
| break; |
| } |
| verify(mergedNode.getId() == child.getId(), "merged entity has wrong id: expected " + child.getId() + ", got " |
| + mergedNode.getId()); |
| verify(mergedNode != child, "merged entity not a copy"); |
| verify(em.contains(mergedNode), "merged entity not managed"); |
| mergedDescription = mergedNode.getDescription(); |
| verify(mergedDescription.getId() == childDescription.getId(), "merged entity has wrong id: expected " |
| + childDescription.getId() + ", got " + mergedDescription.getId()); |
| verify(mergedDescription != childDescription, "merged entity not a copy"); |
| verify(em.contains(mergedDescription), "merged entity not managed"); |
| mergedChildren = mergedNode.getChildren(); |
| verify(mergedChildren.size() == 1, "Wrong number of children: expected 1, got " + mergedChildren.size()); |
| for (CascadingNode temp : mergedChildren) { |
| mergedNode = temp; |
| break; |
| } |
| verify(mergedNode.getId() == grandchild.getId(), "merged entity has wrong id: expected " + grandchild.getId() |
| + ", got " + mergedNode.getId()); |
| verify(mergedNode != grandchild, "merged entity not a copy"); |
| verify(em.contains(mergedNode), "merged entity not managed"); |
| mergedDescription = mergedNode.getDescription(); |
| verify(mergedDescription.getId() == grandchildDescription.getId(), "merged entity has wrong id: expected " |
| + grandchildDescription.getId() + ", got " + mergedDescription.getId()); |
| verify(mergedDescription != grandchildDescription, "merged entity not a copy"); |
| verify(em.contains(mergedDescription), "merged entity not managed"); |
| mergedChildren = mergedNode.getChildren(); |
| verify(mergedChildren == null, "merged entity has children"); |
| env.commitTransactionAndClear(em); |
| verifyExistence(em, parent); |
| verifyExistence(em, parentDescription); |
| verifyExistence(em, child); |
| verifyExistence(em, childDescription); |
| verifyExistence(em, grandchild); |
| verifyExistence(em, grandchildDescription); |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| @Test |
| @ToBeInvestigated |
| public void testCascadeDetached() { |
| /* |
| * If X is a detached entity, the state of X is copied onto a pre-existing managed entity instance X' of the same |
| * identity or a new managed copy X' of X is created. |
| * |
| * For all entities Y referenced by relationships from X having the cascade element value cascade=MERGE or cascade=ALL, |
| * Y is merged recursively as Y'. For all such Y referenced by X, X' is set to reference Y'. (Note that if X is managed |
| * then X is the same object as X'.) |
| */ |
| final JPAEnvironment env = getEnvironment(); |
| final EntityManager em = env.getEntityManager(); |
| try { |
| // types of being detached: |
| // parent, parentDescription: not in persistence context but on db |
| // child, childDescription: different object with same pk in persistence context, state FOR_UPDATE |
| // grandchild, grandchildDescription: different object with same pk in persistence context, state FOR_INSERT |
| CascadingNode parent = new CascadingNode(101, null); |
| CascadingNodeDescription parentDescription = new CascadingNodeDescription(102, null, "new parent"); |
| parent.setDescription(parentDescription); |
| CascadingNode child = new CascadingNode(103, null); |
| CascadingNodeDescription childDescription = new CascadingNodeDescription(104, null, "new child"); |
| child.setDescription(childDescription); |
| parent.addChild(child); |
| env.beginTransaction(em); |
| em.persist(parent); |
| env.commitTransactionAndClear(em); |
| verifyExistence(em, parent); |
| verifyExistence(em, parentDescription); |
| verifyExistence(em, child); |
| verifyExistence(em, childDescription); |
| env.beginTransaction(em); |
| CascadingNode grandchild = new CascadingNode(105, null); |
| CascadingNodeDescription grandchildDescription = new CascadingNodeDescription(106, null, "new grandchild"); |
| grandchild.setDescription(grandchildDescription); |
| child.addChild(grandchild); |
| CascadingNode managedChild = em.find(CascadingNode.class, child.getId()); |
| CascadingNodeDescription managedChildDescription = em.find(CascadingNodeDescription.class, childDescription.getId()); |
| CascadingNode managedGrandchild = new CascadingNode(grandchild.getId(), null); |
| CascadingNodeDescription managedGrandchildDescription = new CascadingNodeDescription(grandchildDescription.getId(), |
| null, "new grandchild"); |
| managedGrandchild.setDescription(managedGrandchildDescription); |
| managedChild.addChild(managedGrandchild); |
| em.persist(managedGrandchild); |
| verify(!em.contains(parent), "parent is managed"); |
| verify(!em.contains(parentDescription), "parentDescription is managed"); |
| verify(!em.contains(child), "child is managed"); |
| verify(!em.contains(childDescription), "childDescription is managed"); |
| verify(!em.contains(grandchild), "grandchild is managed"); |
| verify(!em.contains(grandchildDescription), "grandchildDescription is managed"); |
| verify(em.contains(managedChild), "managedChild is not managed"); |
| verify(em.contains(managedChildDescription), "managedChildDescription is not managed"); |
| verify(em.contains(managedGrandchild), "managedGrandchild is not managed"); |
| verify(em.contains(managedGrandchildDescription), "managedGrandchildDescription is not managed"); |
| // setup complete |
| CascadingNode mergedNode = em.merge(parent); |
| verify(mergedNode.getId() == parent.getId(), "merged entity has wrong id: expected " + parent.getId() + ", got " |
| + mergedNode.getId()); |
| verify(mergedNode != parent, "merged entity not a copy"); |
| verify(em.contains(mergedNode), "merged entity not managed"); |
| CascadingNodeDescription mergedDescription = mergedNode.getDescription(); |
| verify(mergedDescription.getId() == parentDescription.getId(), "merged entity has wrong id: expected " |
| + parentDescription.getId() + ", got " + mergedDescription.getId()); |
| verify(mergedDescription != parentDescription, "merged entity not a copy"); |
| verify(em.contains(mergedDescription), "merged entity not managed"); |
| Set<CascadingNode> mergedChildren = mergedNode.getChildren(); |
| verify(mergedChildren.size() == 1, "Wrong number of children: expected 1, got " + mergedChildren.size()); |
| for (CascadingNode temp : mergedChildren) { |
| mergedNode = temp; |
| break; |
| } |
| verify(mergedNode.getId() == child.getId(), "merged entity has wrong id: expected " + child.getId() + ", got " |
| + mergedNode.getId()); |
| verify(mergedNode != child, "merged entity not a copy"); |
| verify(em.contains(mergedNode), "merged entity not managed"); |
| mergedDescription = mergedNode.getDescription(); |
| verify(mergedDescription.getId() == childDescription.getId(), "merged entity has wrong id: expected " |
| + childDescription.getId() + ", got " + mergedDescription.getId()); |
| verify(mergedDescription != childDescription, "merged entity not a copy"); |
| verify(em.contains(mergedDescription), "merged entity not managed"); |
| mergedChildren = mergedNode.getChildren(); |
| verify(mergedChildren.size() == 1, "Wrong number of children: expected 1, got " + mergedChildren.size()); |
| for (CascadingNode temp : mergedChildren) { |
| mergedNode = temp; |
| break; |
| } |
| verify(mergedNode.getId() == grandchild.getId(), "merged entity has wrong id: expected " + grandchild.getId() |
| + ", got " + mergedNode.getId()); |
| verify(mergedNode != grandchild, "merged entity not a copy"); |
| verify(em.contains(mergedNode), "merged entity not managed"); |
| mergedDescription = mergedNode.getDescription(); |
| verify(mergedDescription.getId() == grandchildDescription.getId(), "merged entity has wrong id: expected " |
| + grandchildDescription.getId() + ", got " + mergedDescription.getId()); |
| verify(mergedDescription != grandchildDescription, "merged entity not a copy"); |
| verify(em.contains(mergedDescription), "merged entity not managed"); |
| mergedChildren = mergedNode.getChildren(); |
| verify(mergedChildren == null, "merged entity has children"); |
| env.commitTransactionAndClear(em); |
| verifyExistence(em, parent); |
| verifyExistence(em, parentDescription); |
| verifyExistence(em, child); |
| verifyExistence(em, childDescription); |
| verifyExistence(em, grandchild); |
| verifyExistence(em, grandchildDescription); |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| /** |
| * Scenario: Merge a detached entity in case an entity with the same primary key but different object identiy exists in the |
| * persistence context <b>in state FOR_DELETE</b>. The specification does not state clearly how to behave in that case. We |
| * decided to throw an IllegalArgumentException. |
| */ |
| @Test |
| public void testCascadeDetachedRemoved() { |
| final JPAEnvironment env = getEnvironment(); |
| final EntityManager em = env.getEntityManager(); |
| try { |
| // child, childDescription: different object with same pk in persistence context, state FOR_DELETE |
| // others: detached (other types) |
| CascadingNode parent = new CascadingNode(201, null); |
| CascadingNodeDescription parentDescription = new CascadingNodeDescription(202, null, "new parent"); |
| parent.setDescription(parentDescription); |
| CascadingNode child = new CascadingNode(203, null); |
| CascadingNodeDescription childDescription = new CascadingNodeDescription(204, null, "new child"); |
| child.setDescription(childDescription); |
| CascadingNode grandchild = new CascadingNode(205, null); |
| CascadingNodeDescription grandchildDescription = new CascadingNodeDescription(206, null, "new grandchild"); |
| grandchild.setDescription(grandchildDescription); |
| parent.addChild(child); |
| child.addChild(grandchild); |
| env.beginTransaction(em); |
| em.persist(parent); |
| env.commitTransactionAndClear(em); |
| verifyExistence(em, parent); |
| verifyExistence(em, parentDescription); |
| verifyExistence(em, child); |
| verifyExistence(em, childDescription); |
| verifyExistence(em, grandchild); |
| verifyExistence(em, grandchildDescription); |
| env.beginTransaction(em); |
| CascadingNode managedParent = em.find(CascadingNode.class, parent.getId()); |
| CascadingNodeDescription managedParentDescription = em.find(CascadingNodeDescription.class, parentDescription.getId()); |
| CascadingNode managedChild = em.find(CascadingNode.class, child.getId()); |
| CascadingNodeDescription managedChildDescription = em.find(CascadingNodeDescription.class, childDescription.getId()); |
| CascadingNode managedGrandchild = em.find(CascadingNode.class, grandchild.getId()); |
| CascadingNodeDescription managedGrandchildDescription = em.find(CascadingNodeDescription.class, grandchildDescription.getId()); |
| managedParent.setChildren(null); |
| em.remove(managedChild); |
| em.persist(managedGrandchild); |
| verify(!em.contains(parent), "parent is managed"); |
| verify(!em.contains(parentDescription), "parentDescription is managed"); |
| verify(!em.contains(child), "child is managed"); |
| verify(!em.contains(childDescription), "childDescription is managed"); |
| verify(!em.contains(grandchild), "grandchild is managed"); |
| verify(!em.contains(grandchildDescription), "grandchildDescription is managed"); |
| verify(em.contains(managedParent), "managedParent is not managed"); |
| verify(em.contains(managedParentDescription), "managedParentDescription is not managed"); |
| verify(!em.contains(managedChild), "managedChild is not in state FOR_DELETE"); |
| verify(!em.contains(managedChildDescription), "managedChildDescription is not in state FOR_DELETE"); |
| verify(em.contains(managedGrandchild), "managedGrandchild is not managed"); |
| verify(em.contains(managedGrandchildDescription), "managedGrandchildDescription is not managed"); |
| // setup complete |
| boolean mergeFailed = false; |
| try { |
| em.merge(parent); |
| } catch (IllegalArgumentException e) { |
| // $JL-EXC$ this is expected behavior |
| mergeFailed = true; |
| } |
| verify(mergeFailed, "Merge did not throw IllegalArgumentException"); |
| verify(em.contains(managedParent), "managedParent is not managed"); |
| verify(em.contains(managedParentDescription), "managedParentDescription is not managed"); |
| verify(managedParent.getDescription() == managedParentDescription, "managedParent has wrong description"); |
| Set<CascadingNode> children = managedParent.getChildren(); |
| verify(children == null || children.size() == 0, "parent has children"); |
| verify(!em.contains(managedChild), "managedChild is not in state FOR_DELETE"); |
| verify(!em.contains(managedChildDescription), "managedChildDescription is not in state FOR_DELETE"); |
| verify(em.contains(managedGrandchild), "managedGrandchild is not managed"); |
| verify(em.contains(managedGrandchildDescription), "managedGrandchildDescription is not managed"); |
| verify(managedGrandchild.getDescription() == managedGrandchildDescription, |
| "managedGrandchild has wrong description"); |
| env.rollbackTransactionAndClear(em); |
| verifyExistence(em, parent); |
| verifyExistence(em, parentDescription); |
| verifyExistence(em, child); |
| verifyExistence(em, childDescription); |
| verifyExistence(em, grandchild); |
| verifyExistence(em, grandchildDescription); |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| @Test |
| public void testCircularCascade() { |
| final JPAEnvironment env = getEnvironment(); |
| final EntityManager em = env.getEntityManager(); |
| try { |
| CascadingNode node1 = new CascadingNode(301, null); |
| CascadingNode node2 = new CascadingNode(302, null); |
| env.beginTransaction(em); |
| em.persist(node1); |
| em.persist(node2); |
| env.commitTransactionAndClear(em); |
| verifyExistence(em, node1); |
| verifyExistence(em, node2); |
| node1.addChild(node2); |
| node2.addChild(node1); |
| env.beginTransaction(em); |
| CascadingNode mergedNode1 = em.merge(node1); |
| verify(em.contains(mergedNode1), "mergedNode1 not managed"); |
| Set<CascadingNode> childrenOfNode1 = mergedNode1.getChildren(); |
| verify(childrenOfNode1.size() == 1, "Wrong number of children: expected 1, got " + childrenOfNode1.size()); |
| CascadingNode childOfNode1 = null; |
| for (CascadingNode temp : childrenOfNode1) { |
| childOfNode1 = temp; |
| break; |
| } |
| verify(childOfNode1.getId() == node2.getId(), "childOfNode1 has wrong id: " + childOfNode1.getId()); |
| verify(em.contains(childOfNode1), "childOfNode1 not managed"); |
| Set<CascadingNode> childrenOfNode2 = childOfNode1.getChildren(); |
| verify(childrenOfNode2.size() == 1, "Wrong number of children: expected 1, got " + childrenOfNode2.size()); |
| CascadingNode childOfNode2 = null; |
| for (CascadingNode temp : childrenOfNode2) { |
| childOfNode2 = temp; |
| break; |
| } |
| verify(childOfNode2 == mergedNode1, "mergedNode1 not child of childOfNode1"); |
| env.commitTransactionAndClear(em); |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| /** |
| * Tests a scenario where two nodes with the same primary key are related to each other, one is managed, the other detached. |
| */ |
| @Test |
| public void testCircularCascadeWithSamePks() { |
| final JPAEnvironment env = getEnvironment(); |
| final EntityManager em = env.getEntityManager(); |
| try { |
| CascadingNode managedNode = new CascadingNode(401, null); |
| CascadingNode detachedNode = new CascadingNode(managedNode.getId(), null); |
| env.beginTransaction(em); |
| em.persist(managedNode); |
| env.commitTransactionAndClear(em); |
| verifyExistence(em, managedNode); |
| env.beginTransaction(em); |
| managedNode = em.find(CascadingNode.class, managedNode.getId()); |
| managedNode.addChild(detachedNode); |
| detachedNode.addChild(managedNode); |
| CascadingNode mergedNode = em.merge(detachedNode); |
| verify(em.contains(mergedNode), "mergedNode not managed"); |
| verify(mergedNode == managedNode, "mergedNode not identical to managedNode"); |
| Set<CascadingNode> children = mergedNode.getChildren(); |
| verify(children.size() == 1, "Wrong number of children: expected 1, got " + children.size()); |
| CascadingNode child = null; |
| for (CascadingNode temp : children) { |
| child = temp; |
| break; |
| } |
| verify(child == managedNode, "child is not identical to managedNode"); |
| env.commitTransactionAndClear(em); |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| @Test |
| public void testCascadeManaged() { |
| /* |
| * If X is a managed entity, it is ignored by the merge operation, however, the merge operation is cascaded to entities |
| * referenced by relationships from X if these relationships have been annotated with the cascade element value |
| * cascade=MERGE or cascade=ALL annotation. |
| * |
| * For all entities Y referenced by relationships from X having the cascade element value cascade=MERGE or cascade=ALL, |
| * Y is merged recursively as Y'. For all such Y referenced by X, X' is set to reference Y'. (Note that if X is managed |
| * then X is the same object as X'.) |
| */ |
| final JPAEnvironment env = getEnvironment(); |
| final EntityManager em = env.getEntityManager(); |
| try { |
| // states: |
| // parent, parentDescription: managed |
| // child, childDescription: new |
| CascadingNode parent = new CascadingNode(501, null); |
| CascadingNodeDescription parentDescription = new CascadingNodeDescription(502, null, "managed parent"); |
| parent.setDescription(parentDescription); |
| CascadingNode child = new CascadingNode(503, null); |
| CascadingNodeDescription childDescription = new CascadingNodeDescription(504, null, "new child"); |
| child.setDescription(childDescription); |
| env.beginTransaction(em); |
| em.persist(parent); |
| env.commitTransactionAndClear(em); |
| verifyExistence(em, parent); |
| verifyExistence(em, parentDescription); |
| verifyAbsence(em, child); |
| verifyAbsence(em, childDescription); |
| env.beginTransaction(em); |
| parent = em.find(CascadingNode.class, parent.getId()); |
| parent.addChild(child); |
| // setup complete |
| CascadingNode mergedNode = em.merge(parent); |
| verify(mergedNode == parent, "merge returned a copy of the managed entity"); |
| verify(em.contains(mergedNode), "merged entity not managed"); |
| CascadingNodeDescription mergedDescription = mergedNode.getDescription(); |
| verify(mergedDescription.getId() == parentDescription.getId(), "merged entity has wrong id: expected " |
| + parentDescription.getId() + ", got " + mergedNode.getId()); |
| verify(mergedDescription != parentDescription, "merged entity not a copy"); |
| verify(em.contains(mergedDescription), "merged entity not managed"); |
| Set<CascadingNode> mergedChildren = mergedNode.getChildren(); |
| verify(mergedChildren.size() == 1, "Wrong number of children: expected 1, got " + mergedChildren.size()); |
| for (CascadingNode temp : mergedChildren) { |
| mergedNode = temp; |
| break; |
| } |
| verify(mergedNode.getId() == child.getId(), "merged entity has wrong id: expected " + child.getId() + ", got " |
| + mergedNode.getId()); |
| verify(mergedNode != child, "merged entity not a copy"); |
| verify(em.contains(mergedNode), "merged entity not managed"); |
| mergedDescription = mergedNode.getDescription(); |
| verify(mergedDescription.getId() == childDescription.getId(), "merged entity has wrong id: expected " |
| + childDescription.getId() + ", got " + mergedNode.getId()); |
| verify(mergedDescription != childDescription, "merged entity not a copy"); |
| verify(em.contains(mergedDescription), "merged entity not managed"); |
| mergedChildren = mergedNode.getChildren(); |
| verify(mergedChildren == null || mergedChildren.size() == 0, "Node has children, expected none"); |
| env.commitTransactionAndClear(em); |
| verifyExistence(em, parent); |
| verifyExistence(em, parentDescription); |
| verifyExistence(em, child); |
| verifyExistence(em, childDescription); |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| @Test |
| public void testCascadeRemoved() { |
| /* |
| * If X is a removed entity instance, an IllegalArgumentException will be thrown by the merge operation (or the |
| * transaction commit will fail). |
| */ |
| final JPAEnvironment env = getEnvironment(); |
| final EntityManager em = env.getEntityManager(); |
| try { |
| // states: |
| // parent, parentDescription: new |
| // child, childDescription: removed |
| CascadingNode parent = new CascadingNode(601, null); |
| CascadingNodeDescription parentDescription = new CascadingNodeDescription(602, null, "new parent"); |
| parent.setDescription(parentDescription); |
| CascadingNode child = new CascadingNode(603, null); |
| CascadingNodeDescription childDescription = new CascadingNodeDescription(604, null, "removed child"); |
| child.setDescription(childDescription); |
| env.beginTransaction(em); |
| em.persist(child); |
| env.commitTransactionAndClear(em); |
| verifyAbsence(em, parent); |
| verifyAbsence(em, parentDescription); |
| verifyExistence(em, child); |
| verifyExistence(em, childDescription); |
| env.beginTransaction(em); |
| child = em.find(CascadingNode.class, child.getId()); |
| em.remove(child); |
| parent.addChild(child); |
| verify(!em.contains(parent), "parent not new"); |
| verify(!em.contains(child), "child not removed"); |
| // setup complete |
| boolean mergeFailed = false; |
| boolean immediateException = false; |
| try { |
| em.merge(parent); |
| } catch (IllegalArgumentException e) { |
| mergeFailed = true; |
| immediateException = true; |
| verify(!em.contains(parent), "parent not new"); |
| verify(!em.contains(child), "child not removed"); |
| } |
| if (!immediateException) { |
| try { |
| env.commitTransactionAndClear(em); |
| } catch (RuntimeException e) { |
| if (!checkForPersistenceException(e)) { |
| throw e; |
| } |
| mergeFailed = true; |
| } |
| } else { |
| env.rollbackTransactionAndClear(em); |
| } |
| verify(mergeFailed, "merge succeeded on a removed entity"); |
| verifyAbsence(em, parent); |
| verifyAbsence(em, parentDescription); |
| verifyExistence(em, child); |
| verifyExistence(em, childDescription); |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| private void verifyExistence(EntityManager em, Object entity) { |
| if (entity instanceof CascadingNode) { |
| CascadingNode node = (CascadingNode) entity; |
| CascadingNode found = em.find(CascadingNode.class, node.getId()); |
| verify(found != null, "cascading node with id " + node.getId() + " not found"); |
| } else if (entity instanceof CascadingNodeDescription) { |
| CascadingNodeDescription desc = (CascadingNodeDescription) entity; |
| CascadingNodeDescription found = em.find(CascadingNodeDescription.class, desc.getId()); |
| verify(found != null, "cascading node description with id " + desc.getId() + " not found"); |
| } else { |
| throw new IllegalArgumentException("not supported"); |
| } |
| } |
| |
| private void verifyAbsence(EntityManager em, Object entity) { |
| if (entity instanceof CascadingNode) { |
| CascadingNode node = (CascadingNode) entity; |
| CascadingNode found = em.find(CascadingNode.class, node.getId()); |
| verify(found == null, "cascading node with id " + node.getId() + " found"); |
| } else if (entity instanceof CascadingNodeDescription) { |
| CascadingNodeDescription desc = (CascadingNodeDescription) entity; |
| CascadingNodeDescription found = em.find(CascadingNodeDescription.class, desc.getId()); |
| verify(found == null, "cascading node description with id " + desc.getId() + " found"); |
| } else { |
| throw new IllegalArgumentException("not supported"); |
| } |
| } |
| } |