| /* |
| * 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.sql.Date; |
| import java.util.HashSet; |
| import java.util.List; |
| import java.util.Set; |
| |
| import jakarta.persistence.EntityManager; |
| import jakarta.persistence.Query; |
| import jakarta.persistence.TransactionRequiredException; |
| |
| import org.eclipse.persistence.testing.framework.wdf.Bugzilla; |
| import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment; |
| import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Cubicle; |
| import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Department; |
| import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Employee; |
| import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Project; |
| import org.eclipse.persistence.testing.models.wdf.jpa1.employee.Review; |
| import org.eclipse.persistence.testing.models.wdf.jpa1.node.Node; |
| import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base; |
| import org.junit.Test; |
| |
| public class TestFlush extends JPA1Base { |
| |
| /* |
| * For any entity Y referenced by a relationship from X, where the relationship to Y has not been annotated with the cascade |
| * element value cascade=PERSIST or cascade=ALL: <p> If Y is new or removed, an IllegalStateException will be thrown by the |
| * flush operation (and the transaction rolled back) or the transaction commit will fail. |
| */ |
| @Test |
| public void testRelationshipToNew() { |
| JPAEnvironment env = getEnvironment(); |
| EntityManager em = env.getEntityManager(); |
| try { |
| // case 1: direct relationship Employee -> Cubicle (new) - 1:1 |
| Department dep = new Department(1, "dep"); |
| Employee emp1 = new Employee(2, "first", "last", dep); |
| Cubicle cub1 = new Cubicle(Integer.valueOf(3), Integer.valueOf(3), "color", emp1); |
| emp1.setCubicle(cub1); |
| env.beginTransaction(em); |
| em.persist(dep); |
| em.persist(emp1); |
| boolean flushFailed = false; |
| try { |
| em.flush(); |
| } catch (IllegalStateException e) { |
| // $JL-EXC$ this is expected behavior |
| flushFailed = true; |
| verify(env.isTransactionMarkedForRollback(em), |
| "IllegalStateException during flush did not mark transaction for rollback"); |
| env.rollbackTransactionAndClear(em); |
| } |
| try { |
| if (env.isTransactionActive(em)) { |
| env.commitTransactionAndClear(em); |
| } |
| } catch (RuntimeException e) { |
| if (!checkForIllegalStateException(e)) { |
| throw e; |
| } |
| flushFailed = true; |
| } |
| verify(!env.isTransactionActive(em), "Transaction still active"); |
| verify(flushFailed, "flush succeeded although there is a relation to an unmanaged entity"); |
| // case 2: direct relationship Employee -> Project (new) - n:m |
| dep = new Department(4, "dep"); |
| emp1 = new Employee(5, "first", "last", dep); |
| Project proj = new Project("project"); |
| Set<Project> emp1Projects = new HashSet<Project>(); |
| emp1Projects.add(proj); |
| emp1.setProjects(emp1Projects); |
| Set<Employee> projEmployees = new HashSet<Employee>(); |
| projEmployees.add(emp1); |
| proj.setEmployees(projEmployees); |
| env.beginTransaction(em); |
| em.persist(dep); |
| em.persist(emp1); |
| flushFailed = false; |
| try { |
| em.flush(); |
| } catch (IllegalStateException e) { |
| // $JL-EXC$ this is expected behavior |
| flushFailed = true; |
| verify(env.isTransactionMarkedForRollback(em), |
| "IllegalStateException during flush did not mark transaction for rollback"); |
| env.rollbackTransactionAndClear(em); |
| } |
| try { |
| if (env.isTransactionActive(em)) { |
| env.commitTransactionAndClear(em); |
| } |
| } catch (RuntimeException e) { |
| if (!checkForIllegalStateException(e)) { |
| throw e; |
| } |
| flushFailed = true; |
| } |
| verify(!env.isTransactionActive(em), "Transaction still active"); |
| verify(flushFailed, "flush succeeded although there is a relation to an unmanaged entity"); |
| // case 3: indirect relationship Employee -> Project -> Employee (new) |
| dep = new Department(7, "dep"); |
| emp1 = new Employee(8, "first1", "last1", dep); |
| Employee emp2 = new Employee(9, "first2", "last2", dep); |
| proj = new Project("project"); |
| emp1Projects = new HashSet<Project>(); |
| emp1Projects.add(proj); |
| emp1.setProjects(emp1Projects); |
| Set<Project> emp2Projects = new HashSet<Project>(); |
| emp2Projects.add(proj); |
| emp2.setProjects(emp2Projects); |
| projEmployees = new HashSet<Employee>(); |
| projEmployees.add(emp1); |
| projEmployees.add(emp2); |
| proj.setEmployees(projEmployees); |
| env.beginTransaction(em); |
| em.persist(dep); |
| em.persist(emp1); |
| em.persist(proj); |
| flushFailed = false; |
| try { |
| em.flush(); |
| } catch (IllegalStateException e) { |
| // $JL-EXC$ this is expected behavior |
| flushFailed = true; |
| verify(env.isTransactionMarkedForRollback(em), |
| "IllegalStateException during flush did not mark transaction for rollback"); |
| env.rollbackTransactionAndClear(em); |
| } |
| try { |
| if (env.isTransactionActive(em)) { |
| env.commitTransactionAndClear(em); |
| } |
| } catch (RuntimeException e) { |
| if (!checkForIllegalStateException(e)) { |
| throw e; |
| } |
| flushFailed = true; |
| } |
| verify(!env.isTransactionActive(em), "Transaction still active"); |
| verify(flushFailed, "flush succeeded although there is a relation to an unmanaged entity"); |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| /* |
| * For any entity Y referenced by a relationship from X, where the relationship to Y has not been annotated with the cascade |
| * element value cascade=PERSIST or cascade=ALL: <p> If Y is new or removed, an IllegalStateException will be thrown by the |
| * flush operation (and the transaction rolled back) or the transaction commit will fail. |
| */ |
| @SuppressWarnings("unchecked") |
| @Test |
| @Bugzilla(bugid=311760) |
| public void testRelationshipToRemoved() { |
| JPAEnvironment env = getEnvironment(); |
| EntityManager em = env.getEntityManager(); |
| try { |
| // case 1: direct relationship Employee -> Cubicle (FOR_DELETE) - 1:1 |
| Department dep = new Department(101, "dep"); |
| Employee emp1 = new Employee(102, "first", "last", dep); |
| Cubicle cub1 = new Cubicle(Integer.valueOf(103), Integer.valueOf(103), "color", emp1); |
| emp1.setCubicle(cub1); |
| env.beginTransaction(em); |
| em.persist(dep); |
| em.persist(emp1); |
| em.persist(cub1); |
| env.commitTransactionAndClear(em); |
| |
| env.beginTransaction(em); |
| emp1 = em.find(Employee.class, Integer.valueOf(emp1.getId())); |
| cub1 = em.find(Cubicle.class, cub1.getId()); |
| cub1.setEmployee(null); // added as suggested by Tom |
| em.remove(cub1); |
| boolean flushOrCommmitFailed = false; |
| try { |
| em.flush(); |
| } catch (IllegalStateException e) { |
| // $JL-EXC$ this is expected behavior |
| flushOrCommmitFailed = true; |
| verify(env.isTransactionMarkedForRollback(em), |
| "IllegalStateException during flush did not mark transaction for rollback"); |
| env.rollbackTransactionAndClear(em); |
| } |
| try { |
| if (env.isTransactionActive(em)) { |
| env.commitTransactionAndClear(em); |
| } |
| } catch (RuntimeException e) { |
| if (!checkForIllegalStateException(e)) { |
| throw e; |
| } |
| flushOrCommmitFailed = true; |
| } |
| verify(!env.isTransactionActive(em), "Transaction still active"); |
| verify(flushOrCommmitFailed, "flush succeeded although there is a relation to a removed entity"); |
| em.clear(); |
| // case 2: direct relationship Employee -> Project (FOR_DELETE) - n:m |
| dep = new Department(104, "dep"); |
| emp1 = new Employee(105, "first", "last", dep); |
| Project proj = new Project("project"); |
| Set<Project> emp1Projects = new HashSet<Project>(); |
| emp1Projects.add(proj); |
| emp1.setProjects(emp1Projects); |
| Set<Employee> projEmployees = new HashSet<Employee>(); |
| projEmployees.add(emp1); |
| proj.setEmployees(projEmployees); |
| env.beginTransaction(em); |
| em.persist(proj); |
| em.persist(dep); |
| em.persist(emp1); |
| env.commitTransactionAndClear(em); |
| env.beginTransaction(em); |
| emp1 = em.find(Employee.class, Integer.valueOf(emp1.getId())); |
| proj = em.find(Project.class, proj.getId()); |
| emp1.getProjects().size(); |
| em.remove(proj); |
| flushOrCommmitFailed = false; |
| try { |
| em.flush(); |
| } catch (IllegalStateException e) { |
| // $JL-EXC$ this is expected behavior |
| flushOrCommmitFailed = true; |
| verify(env.isTransactionMarkedForRollback(em), |
| "IllegalStateException during flush did not mark transaction for rollback"); |
| env.rollbackTransactionAndClear(em); |
| } |
| try { |
| if (env.isTransactionActive(em)) { |
| env.commitTransactionAndClear(em); |
| } |
| } catch (RuntimeException e) { |
| if (!checkForIllegalStateException(e)) { |
| throw e; |
| } |
| flushOrCommmitFailed = true; |
| } |
| verify(!env.isTransactionActive(em), "Transaction still active"); |
| verify(flushOrCommmitFailed, "flush succeeded although there is a relation to an unmanaged entity"); |
| em.clear(); |
| // case 3: indirect relationship Employee -> Project -> Employee (FOR_DELETE) |
| dep = new Department(107, "dep"); |
| emp1 = new Employee(108, "first1", "last1", dep); |
| Employee emp2 = new Employee(109, "first2", "last2", dep); |
| proj = new Project("project"); |
| emp1Projects = new HashSet<Project>(); |
| emp1Projects.add(proj); |
| emp1.setProjects(emp1Projects); |
| Set<Project> emp2Projects = new HashSet<Project>(); |
| emp2Projects.add(proj); |
| emp2.setProjects(emp2Projects); |
| projEmployees = new HashSet<Employee>(); |
| projEmployees.add(emp1); |
| projEmployees.add(emp2); |
| proj.setEmployees(projEmployees); |
| env.beginTransaction(em); |
| em.persist(proj); |
| em.persist(dep); |
| em.persist(emp1); |
| em.persist(emp2); |
| env.commitTransactionAndClear(em); |
| env.beginTransaction(em); |
| emp1 = em.find(Employee.class, Integer.valueOf(emp1.getId())); |
| emp2 = em.find(Employee.class, Integer.valueOf(emp2.getId())); |
| proj = em.find(Project.class, proj.getId()); |
| emp1.getProjects().size(); |
| proj.getEmployees().size(); |
| em.remove(emp2); |
| flushOrCommmitFailed = false; |
| try { |
| em.flush(); |
| } catch (IllegalStateException e) { |
| // $JL-EXC$ this is expected behavior |
| flushOrCommmitFailed = true; |
| verify(env.isTransactionMarkedForRollback(em), |
| "IllegalStateException during flush did not mark transaction for rollback"); |
| env.rollbackTransactionAndClear(em); |
| } |
| try { |
| if (env.isTransactionActive(em)) { |
| env.commitTransactionAndClear(em); |
| } |
| } catch (RuntimeException e) { |
| if (!checkForIllegalStateException(e)) { |
| throw e; |
| } |
| flushOrCommmitFailed = true; |
| } |
| verify(!env.isTransactionActive(em), "Transaction still active"); |
| verify(flushOrCommmitFailed, "flush succeeded although there is a relation to an unmanaged entity"); |
| em.clear(); |
| // case 1b: direct relationship Employee -> Cubicle (DELETE_EXECUTED) - 1:1 |
| dep = new Department(111, "dep"); |
| emp1 = new Employee(112, "first", "last", dep); |
| cub1 = new Cubicle(Integer.valueOf(113), Integer.valueOf(112), "color", emp1); |
| env.beginTransaction(em); |
| em.persist(dep); |
| em.persist(emp1); |
| em.persist(cub1); |
| env.commitTransactionAndClear(em); |
| env.beginTransaction(em); |
| emp1 = em.find(Employee.class, Integer.valueOf(emp1.getId())); |
| cub1 = em.find(Cubicle.class, cub1.getId()); |
| em.remove(cub1); |
| em.flush(); |
| emp1.setCubicle(cub1); |
| flushOrCommmitFailed = false; |
| try { |
| em.flush(); |
| } catch (IllegalStateException e) { |
| // $JL-EXC$ this is expected behavior |
| flushOrCommmitFailed = true; |
| verify(env.isTransactionMarkedForRollback(em), |
| "IllegalStateException during flush did not mark transaction for rollback"); |
| env.rollbackTransactionAndClear(em); |
| } |
| try { |
| if (env.isTransactionActive(em)) { |
| env.commitTransactionAndClear(em); |
| } |
| } catch (RuntimeException e) { |
| if (!checkForIllegalStateException(e)) { |
| throw e; |
| } |
| flushOrCommmitFailed = true; |
| } |
| verify(!env.isTransactionActive(em), "Transaction still active"); |
| verify(flushOrCommmitFailed, "flush succeeded although there is a relation to an unmanaged entity"); |
| em.clear(); |
| // case 2b: direct relationship Employee -> Project (DELETE_EXECUTED) - n:m |
| dep = new Department(114, "dep"); |
| emp1 = new Employee(115, "first", "last", dep); |
| proj = new Project("project"); |
| env.beginTransaction(em); |
| em.persist(dep); |
| em.persist(emp1); |
| em.persist(proj); |
| env.commitTransactionAndClear(em); |
| env.beginTransaction(em); |
| emp1 = em.find(Employee.class, Integer.valueOf(emp1.getId())); |
| proj = em.find(Project.class, proj.getId()); |
| em.remove(proj); |
| em.flush(); |
| emp1Projects = new HashSet<Project>(); |
| emp1Projects.add(proj); |
| emp1.setProjects(emp1Projects); |
| projEmployees = new HashSet<Employee>(); |
| projEmployees.add(emp1); |
| proj.setEmployees(projEmployees); |
| flushOrCommmitFailed = false; |
| try { |
| em.flush(); |
| } catch (IllegalStateException e) { |
| // $JL-EXC$ this is expected behavior |
| flushOrCommmitFailed = true; |
| verify(env.isTransactionMarkedForRollback(em), |
| "IllegalStateException during flush did not mark transaction for rollback"); |
| env.rollbackTransactionAndClear(em); |
| } |
| try { |
| if (env.isTransactionActive(em)) { |
| env.commitTransactionAndClear(em); |
| } |
| } catch (RuntimeException e) { |
| if (!checkForIllegalStateException(e)) { |
| throw e; |
| } |
| flushOrCommmitFailed = true; |
| } |
| verify(!env.isTransactionActive(em), "Transaction still active"); |
| verify(flushOrCommmitFailed, "flush succeeded although there is a relation to an unmanaged entity"); |
| em.clear(); |
| // case 3b: indirect relationship Employee -> Project -> Employee (DELETE_EXECUTED) |
| dep = new Department(117, "dep"); |
| emp1 = new Employee(118, "first1", "last1", dep); |
| emp2 = new Employee(119, "first2", "last2", dep); |
| proj = new Project("project"); |
| emp1Projects = new HashSet<Project>(); |
| emp1Projects.add(proj); |
| emp1.setProjects(emp1Projects); |
| projEmployees = new HashSet<Employee>(); |
| projEmployees.add(emp1); |
| proj.setEmployees(projEmployees); |
| env.beginTransaction(em); |
| em.persist(proj); |
| em.persist(dep); |
| em.persist(emp1); |
| em.persist(emp2); |
| env.commitTransactionAndClear(em); |
| env.beginTransaction(em); |
| emp1 = em.find(Employee.class, Integer.valueOf(emp1.getId())); |
| emp2 = em.find(Employee.class, Integer.valueOf(emp2.getId())); |
| proj = em.find(Project.class, proj.getId()); |
| emp1.getProjects().size(); |
| projEmployees = proj.getEmployees(); |
| projEmployees.size(); |
| em.remove(emp2); |
| em.flush(); |
| emp2Projects = new HashSet<Project>(); |
| emp2Projects.add(proj); |
| emp2.setProjects(emp2Projects); |
| projEmployees.add(emp2); |
| flushOrCommmitFailed = false; |
| try { |
| em.flush(); |
| } catch (IllegalStateException e) { |
| // $JL-EXC$ this is expected behavior |
| flushOrCommmitFailed = true; |
| verify(env.isTransactionMarkedForRollback(em), |
| "IllegalStateException during flush did not mark transaction for rollback"); |
| env.rollbackTransactionAndClear(em); |
| } |
| try { |
| if (env.isTransactionActive(em)) { |
| env.commitTransactionAndClear(em); |
| } |
| } catch (RuntimeException e) { |
| if (!checkForIllegalStateException(e)) { |
| throw e; |
| } |
| flushOrCommmitFailed = true; |
| } |
| verify(!env.isTransactionActive(em), "Transaction still active"); |
| verify(flushOrCommmitFailed, "flush succeeded although there is a relation to an unmanaged entity"); |
| em.clear(); |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| /** |
| * This test checks a special case that can occur with lazily loaded relationships: |
| * <ul> |
| * <li>Read Project proj1 and remove it.</li> |
| * <li>Read Employee emp1 with relationship to proj1 (lazy loading).</li> |
| * <li>Assign the set of emp1's projects to a new employee emp2 (forces implicit loading on flush).</li> |
| * <li>Flush -> IllegalStateException expected because of relation emp2 -> proj1 (removed).</li> |
| * </ul> |
| */ |
| @Test |
| @Bugzilla(bugid=311760) |
| public void testRelationshipToRemovedLazy() { |
| JPAEnvironment env = getEnvironment(); |
| EntityManager em = env.getEntityManager(); |
| try { |
| // case 1: explicit flush |
| Department dep = new Department(201, "dep"); |
| Employee emp1 = new Employee(202, "first", "last", dep); |
| Project proj = new Project("project"); |
| Set<Project> emp1Projects = new HashSet<Project>(); |
| emp1Projects.add(proj); |
| emp1.setProjects(emp1Projects); |
| Set<Employee> projEmployees = new HashSet<Employee>(); |
| projEmployees.add(emp1); |
| proj.setEmployees(projEmployees); |
| env.beginTransaction(em); |
| em.persist(proj); |
| em.persist(dep); |
| em.persist(emp1); |
| env.commitTransactionAndClear(em); |
| |
| env.beginTransaction(em); |
| dep = em.find(Department.class, Integer.valueOf(dep.getId())); |
| proj = em.find(Project.class, proj.getId()); |
| em.remove(proj); |
| emp1 = em.find(Employee.class, Integer.valueOf(emp1.getId())); |
| // copy all projects from emp1 to emp2 with out actually touching them |
| Employee emp2 = new Employee(203, "aaa", "bbb", dep); |
| proj.addEmployee(emp2); // added as suggested by Tom |
| emp2.setProjects(emp1.getProjects()); |
| em.persist(emp2); |
| boolean flushFailed = false; |
| try { |
| em.flush(); |
| } catch (IllegalStateException e) { |
| // $JL-EXC$ this is expected behavior |
| flushFailed = true; |
| verify(env.isTransactionMarkedForRollback(em), |
| "IllegalStateException during flush did not mark transaction for rollback"); |
| env.rollbackTransactionAndClear(em); |
| } |
| try { |
| if (env.isTransactionActive(em)) { |
| env.commitTransactionAndClear(em); |
| } |
| } catch (RuntimeException e) { |
| if (!checkForIllegalStateException(e)) { |
| throw e; |
| } |
| flushFailed = true; |
| } |
| verify(!env.isTransactionActive(em), "Transaction still active"); |
| verify(flushFailed, "flush succeeded although there is a relation to a removed entity"); |
| em.clear(); |
| // case 2: implicit flush during commit |
| dep = new Department(204, "dep"); |
| emp1 = new Employee(205, "first", "last", dep); |
| proj = new Project("project"); |
| emp1Projects = new HashSet<Project>(); |
| emp1Projects.add(proj); |
| emp1.setProjects(emp1Projects); |
| projEmployees = new HashSet<Employee>(); |
| projEmployees.add(emp1); |
| proj.setEmployees(projEmployees); |
| env.beginTransaction(em); |
| em.persist(proj); |
| em.persist(dep); |
| em.persist(emp1); |
| env.commitTransactionAndClear(em); |
| env.beginTransaction(em); |
| dep = em.find(Department.class, Integer.valueOf(dep.getId())); |
| proj = em.find(Project.class, proj.getId()); |
| em.remove(proj); |
| emp1 = em.find(Employee.class, Integer.valueOf(emp1.getId())); |
| // copy all projects from emp1 to emp2 with out actually touching them |
| emp2 = new Employee(206, "aaa", "bbb", dep); |
| emp2.setProjects(emp1.getProjects()); |
| em.persist(emp2); |
| flushFailed = false; |
| try { |
| env.commitTransactionAndClear(em); |
| } catch (RuntimeException e) { |
| if (!checkForIllegalStateException(e)) { |
| throw e; |
| } |
| flushFailed = true; |
| } |
| verify(!env.isTransactionActive(em), "Transaction still active"); |
| verify(flushFailed, "flush succeeded although there is a relation to a removed entity"); |
| em.clear(); |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| /** |
| * Force an exception during flush and check whether the current transaction is rolled back. |
| */ |
| @Test |
| public void testWithException() { |
| JPAEnvironment env = getEnvironment(); |
| EntityManager em = env.getEntityManager(); |
| try { |
| Node node = new Node(301, true); // PostPersist method will throw a Node.MyRuntimeException |
| env.beginTransaction(em); |
| em.persist(node); |
| boolean flushFailed = false; |
| try { |
| em.flush(); |
| } catch (Node.MyRuntimeException e) { |
| // $JL-EXC$ this is expected behavior |
| flushFailed = true; |
| verify(env.isTransactionMarkedForRollback(em), |
| "IllegalStateException during flush did not mark transaction for rollback"); |
| } |
| verify(flushFailed, "callback method did not throw exception as expected"); |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| @Test |
| public void testRestoreFieldAfterFlush() { |
| JPAEnvironment env = getEnvironment(); |
| EntityManager em = env.getEntityManager(); |
| try { |
| final String initial = "initial"; |
| final int id = 301; |
| Department department = new Department(id, initial); |
| env.beginTransaction(em); |
| em.persist(department); |
| department.setName("changed"); |
| em.flush(); |
| // undo the change between flush and commit (on a new entity) |
| department.setName(initial); |
| env.commitTransactionAndClear(em); |
| env.beginTransaction(em); |
| department = em.find(Department.class, Integer.valueOf(id)); |
| verify(initial.equals(department.getName()), "wrong name: " + department.getName()); |
| department.setName("changed"); |
| em.flush(); |
| // lets try the same with a managed field |
| department.setName(initial); |
| env.commitTransactionAndClear(em); |
| department = em.find(Department.class, Integer.valueOf(id)); |
| verify(initial.equals(department.getName()), "wrong name: " + department.getName()); |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| @Test |
| public void testRestoreRelationAfterFlush() { |
| JPAEnvironment env = getEnvironment(); |
| EntityManager em = env.getEntityManager(); |
| try { |
| final int id = 302; |
| Employee frank = new Employee(id, "Frank", "Schuster", null); |
| env.beginTransaction(em); |
| Review r1 = new Review(101, Date.valueOf("2006-10-19"), "Performance"); |
| frank.addReview(r1); |
| Review r2 = new Review(102, Date.valueOf("2006-10-19"), "Passion"); |
| frank.addReview(r2); |
| Review r3 = new Review(103, Date.valueOf("2006-10-19"), "Six-Sigma"); |
| frank.addReview(r3); |
| em.persist(frank); |
| em.persist(r1); |
| em.persist(r2); |
| em.persist(r3); |
| env.commitTransactionAndClear(em); |
| env.beginTransaction(em); |
| frank = em.find(Employee.class, Integer.valueOf(id)); |
| Set<Review> reviewsFound = frank.getReviews(); |
| int foundSize = reviewsFound.size(); |
| // lets remove a department the same with a managed field |
| Set<Review> set = new HashSet<Review>(); |
| set.add(r1); |
| set.add(r2); |
| frank.setReviews(set); |
| em.flush(); |
| // undo the change |
| frank.setReviews(reviewsFound); |
| env.commitTransactionAndClear(em); |
| env.beginTransaction(em); |
| frank = em.find(Employee.class, Integer.valueOf(id)); |
| verify(frank.getReviews().size() == foundSize, "wrong number of reviews: " + frank.getReviews().size()); |
| env.rollbackTransactionAndClear(em); |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| @Test |
| public void testNoTransaction() { |
| final JPAEnvironment env = getEnvironment(); |
| final EntityManager em = env.getEntityManager(); |
| try { |
| em.flush(); |
| flop("exception not thrown as expected"); |
| } catch (TransactionRequiredException e) { |
| // $JL-EXC$ expected behavior |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| @SuppressWarnings("unchecked") |
| @Test |
| public void testTransactionMarkedForRollback() { |
| final JPAEnvironment env = getEnvironment(); |
| final EntityManager em = env.getEntityManager(); |
| Department dep = new Department(401, "dep401"); |
| try { |
| env.beginTransaction(em); |
| em.persist(dep); |
| env.markTransactionForRollback(em); |
| em.flush(); |
| // verify that entity is inserted |
| Query query = em.createQuery("select d from Department d where d.id = ?1"); |
| query.setParameter(1, Integer.valueOf(dep.getId())); |
| List<Department> result = query.getResultList(); |
| verify(result.size() == 1, "query returned " + result.size() + " entities"); |
| env.rollbackTransaction(em); |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| @Test |
| @Bugzilla(bugid=309681) |
| public void testChangedEntityIgnoredByFlush() { |
| final JPAEnvironment env = getEnvironment(); |
| final EntityManager em = env.getEntityManager(); |
| Employee emp = new Employee(911, "Robi", "Tobi", null); |
| try { |
| env.beginTransaction(em); |
| em.persist(emp); |
| env.commitTransactionAndClear(em); |
| |
| env.beginTransaction(em); |
| Employee found = em.find(Employee.class, 911); |
| found.clearPostUpdate(); |
| found.setLastName("lesbar"); |
| em.createQuery("select i from Island i").getResultList(); |
| verify(!found.postUpdateWasCalled(), "post update was called"); |
| env.rollbackTransactionAndClear(em); |
| |
| } finally { |
| closeEntityManager(em); |
| } |
| } |
| |
| } |