| /* |
| * 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.detach; |
| |
| import java.util.Collection; |
| import java.util.HashMap; |
| import java.util.HashSet; |
| import java.util.Map; |
| |
| import org.apache.openjpa.conf.Compatibility; |
| import org.apache.openjpa.meta.ClassMetaData; |
| import org.apache.openjpa.meta.MetaDataRepository; |
| import org.apache.openjpa.meta.ValueMetaData; |
| import org.apache.openjpa.persistence.OpenJPAEntityManager; |
| import org.apache.openjpa.persistence.test.SingleEMFTestCase; |
| |
| public class TestDetachCascade extends SingleEMFTestCase { |
| OpenJPAEntityManager em; |
| int id = 0; |
| Compatibility compat; |
| |
| Entity1 e1; // references e14 - no cascade |
| Entity3 e3; // references e4 - cascade ALL |
| Entity4 e4; // references e5 - cascade CLEAR |
| Entity5 e5; // references e6 - no cascade |
| Entity6 e6; // references e7 - cascade CLEAR |
| Entity7 e7; |
| Entity8 e8; // references e9 - cascade ALL |
| Entity8 e8a; // same as e8 |
| Entity9 e9; |
| Entity10 e10; // references a Collection<Entity8> - cascade ALL |
| Entity11 e11; |
| Entity12 e12; |
| Entity13 e13; // references a Map<String, Entity11> - cascade ALL |
| Entity14 e14; |
| |
| Collection<Object> allEntities = new HashSet<>(); |
| |
| @Override |
| public void setUp() throws Exception { |
| setUp(Entity1.class, |
| Entity3.class, |
| Entity4.class, |
| Entity5.class, |
| Entity6.class, |
| Entity7.class, |
| Entity8.class, |
| Entity9.class, |
| Entity10.class, |
| Entity11.class, |
| Entity12.class, |
| Entity13.class, |
| Entity14.class); |
| assertNotNull(emf); |
| em = emf.createEntityManager(); |
| assertNotNull(em); |
| compat = emf.getConfiguration().getCompatibilityInstance(); |
| assertNotNull(compat); |
| compat.setFlushBeforeDetach(false); |
| compat.setCopyOnDetach(false); |
| compat.setCascadeWithDetach(true); |
| } |
| |
| private void create(int id) { |
| allEntities.clear(); |
| e1 = new Entity1(id, "entity1"); |
| allEntities.add(e1); |
| e3 = new Entity3(id, "entity3"); |
| allEntities.add(e3); |
| e4 = new Entity4(id, "entity4"); |
| allEntities.add(e4); |
| e5 = new Entity5(id, "entity5"); |
| allEntities.add(e5); |
| e6 = new Entity6(id, "entity6"); |
| allEntities.add(e6); |
| e7 = new Entity7(id, "entity7"); |
| allEntities.add(e7); |
| e8 = new Entity8(id, "entity8"); |
| allEntities.add(e8); |
| e8a = new Entity8(id + 100, "entity8a"); |
| allEntities.add(e8a); |
| e9 = new Entity9(id, "entity9"); |
| allEntities.add(e9); |
| e10 = new Entity10(id, "entity10"); |
| allEntities.add(e10); |
| e11 = new Entity11(id, "entity11"); |
| allEntities.add(e11); |
| e12 = new Entity12(id, "entity12"); |
| allEntities.add(e12); |
| e13 = new Entity13(id, "entity13"); |
| allEntities.add(e13); |
| e14 = new Entity14(id, "entity14"); |
| allEntities.add(e14); |
| e1.setE14(e14); |
| e3.setE4(e4); |
| e4.setE5(e5); |
| e5.setE6(e6); |
| e6.setE7(e7); |
| e8.setE9(e9); |
| |
| Collection<Entity8> collection = new HashSet<>(); |
| collection.add(e8); |
| collection.add(e8a); // e8a contains a null value for Entity9 |
| e10.setCollection(collection); |
| |
| Map<String, Entity11> map = new HashMap<>(); |
| map.put(e11.getName(), e11); |
| e13.setMap(map); |
| |
| } |
| |
| // Test that detach cascade values are set correctly |
| public void testCascadeValues() { |
| id++; |
| em.getTransaction().begin(); |
| create(id); |
| em.persistAll(allEntities); |
| em.getTransaction().commit(); |
| |
| MetaDataRepository repos = emf.getConfiguration() |
| .getMetaDataRepositoryInstance(); |
| // Test CascadeType.ALL |
| ClassMetaData meta3 = repos.getCachedMetaData(Entity3.class); |
| assertNotNull(meta3); |
| assertEquals(ValueMetaData.CASCADE_IMMEDIATE, |
| meta3.getField("e4").getCascadeDetach()); |
| // Test CascadeType.CLEAR |
| ClassMetaData meta4 = repos.getCachedMetaData(Entity4.class); |
| assertNotNull(meta4); |
| assertEquals(ValueMetaData.CASCADE_IMMEDIATE, |
| meta4.getField("e5").getCascadeDetach()); |
| } |
| |
| // Make sure cascade is no longer done by default |
| public void testNoCascade() { |
| boolean cwd = compat.getCascadeWithDetach(); |
| compat.setCascadeWithDetach(false); |
| id++; |
| em.getTransaction().begin(); |
| create(id); |
| em.persistAll(allEntities); |
| assertTrue(em.contains(e1)); |
| assertTrue(em.contains(e14)); |
| em.detach(e1); |
| assertFalse(em.contains(e1)); |
| assertTrue(em.contains(e14)); |
| em.getTransaction().commit(); |
| compat.setCascadeWithDetach(cwd); |
| } |
| |
| // Change to the previous behavior to always cascade |
| public void testAlwaysCascade() { |
| id++; |
| em.getTransaction().begin(); |
| create(id); |
| em.persistAll(allEntities); |
| assertTrue(em.contains(e1)); |
| assertTrue(em.contains(e14)); |
| |
| compat.setCascadeWithDetach(true); |
| |
| em.detach(e1); |
| assertFalse(em.contains(e1)); |
| assertFalse(em.contains(e14)); |
| em.getTransaction().commit(); |
| |
| // reset compatibility option to default |
| compat.setCascadeWithDetach(false); |
| } |
| |
| // Test explicit cascade of entities |
| public void testCascadeOfEntities() { |
| boolean cwd = compat.getCascadeWithDetach(); |
| compat.setCascadeWithDetach(false); |
| id++; |
| em.getTransaction().begin(); |
| create(id); |
| em.persistAll(allEntities); |
| assertTrue(em.contains(e3)); |
| assertTrue(em.contains(e4)); |
| em.detach(e3); |
| assertTrue(em.contains(e1)); |
| assertFalse(em.contains(e3)); |
| assertFalse(em.contains(e4)); |
| assertFalse(em.contains(e5)); |
| assertTrue(em.contains(e6)); |
| assertTrue(em.contains(e7)); |
| em.getTransaction().commit(); |
| compat.setCascadeWithDetach(cwd); |
| } |
| |
| // Test always cascade of entities |
| public void testAlwaysCascadeOfEntities() { |
| id++; |
| em.getTransaction().begin(); |
| create(id); |
| em.persistAll(allEntities); |
| assertTrue(em.contains(e3)); |
| assertTrue(em.contains(e4)); |
| compat.setCascadeWithDetach(true); |
| em.detach(e3); |
| assertTrue(em.contains(e1)); |
| assertFalse(em.contains(e3)); |
| assertFalse(em.contains(e4)); |
| assertFalse(em.contains(e5)); |
| assertFalse(em.contains(e6)); |
| assertFalse(em.contains(e7)); |
| em.getTransaction().commit(); |
| compat.setCascadeWithDetach(false); |
| } |
| |
| // test single cascade in new transaction with no fetch of e4 |
| public void testSingleCascadeNoFetch() { |
| id++; |
| em.getTransaction().begin(); |
| create(id); |
| em.persistAll(allEntities); |
| assertTrue(em.contains(e3)); |
| assertTrue(em.contains(e4)); |
| em.getTransaction().commit(); |
| |
| em.close(); |
| em = emf.createEntityManager(); |
| |
| em.getTransaction().begin(); |
| em.clear(); |
| e3 = em.find(Entity3.class, id); |
| assertTrue(em.contains(e3)); |
| assertFalse(em.contains(e4)); |
| em.getTransaction().commit(); |
| em.detach(e3); |
| assertFalse(em.contains(e3)); |
| assertFalse(em.contains(e4)); |
| } |
| |
| // test cascade of a simple collection |
| public void testCascadeOfCollection() { |
| id++; |
| em.getTransaction().begin(); |
| create(id); |
| em.persist(e10); |
| assertTrue(em.contains(e10)); |
| assertTrue(em.contains(e8)); |
| assertTrue(em.contains(e9)); |
| assertTrue(em.contains(e8a)); |
| em.detach(e10); |
| assertFalse(em.contains(e10)); |
| assertFalse(em.contains(e8)); |
| assertFalse(em.contains(e9)); |
| assertFalse(em.contains(e8a)); |
| em.getTransaction().commit(); |
| } |
| |
| // test cascade of Map |
| public void testCascadeOfMap() { |
| id++; |
| em.getTransaction().begin(); |
| create(id); |
| em.persistAll(allEntities); |
| assertTrue(em.contains(e11)); |
| assertTrue(em.contains(e13)); |
| em.detach(e13); |
| assertFalse(em.contains(e13)); |
| assertFalse(em.contains(e11)); |
| em.getTransaction().commit(); |
| } |
| |
| // Test old detach behavior - flush, copy, and cascade |
| public void testOldDetachBehavior() { |
| id++; |
| |
| compat.setFlushBeforeDetach(true); |
| em.getTransaction().begin(); |
| create(id); |
| em.persistAll(allEntities); |
| Entity1 e1Det = em.detachCopy(e1); |
| assertNotEquals(e1, e1Det); // check for copy |
| Entity14 e14Det = e1.getE14(); |
| assertEquals(e14, e14Det); |
| em.getTransaction().commit(); |
| |
| // check for flushed and cascaded flushed |
| Entity1 e1Saved = em.find(Entity1.class, id); |
| assertNotNull(e1Saved); |
| Entity14 e14Saved = e1Saved.getE14(); |
| assertNotNull(e14Saved); |
| |
| compat.setFlushBeforeDetach(false); |
| } |
| |
| } |