/******************************************************************************* * 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 v1.0 and Eclipse Distribution License v. 1.0 * which accompanies this distribution. * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html * and the Eclipse Distribution License is available at * http://www.eclipse.org/org/documents/edl-v10.php. * * Contributors: * SAP - initial API and implementation ******************************************************************************/ package org.eclipse.persistence.testing.tests.wdf.jpa1.relation; import java.sql.Connection; import java.sql.Date; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import javax.persistence.EntityManager; import javax.sql.DataSource; import org.eclipse.persistence.testing.framework.wdf.JPAEnvironment; 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.Review; import org.eclipse.persistence.testing.tests.wdf.jpa1.JPA1Base; import org.junit.Before; import org.junit.Test; @SuppressWarnings("unchecked") public class TestUnidirectionalOneToMany extends JPA1Base { private static final int EMP_ID_VALUE = 4; private static final Integer EMP_ID = new Integer(EMP_ID_VALUE); private static final Set<Pair> SEED_SET = new HashSet<Pair>(); static { SEED_SET.add(new Pair(EMP_ID_VALUE, 1)); SEED_SET.add(new Pair(EMP_ID_VALUE, 2)); SEED_SET.add(new Pair(EMP_ID_VALUE, 3)); } @Before public void seedDataModel() throws SQLException { clearAllTables(); // clear all tables; JPAEnvironment env = getEnvironment(); EntityManager em = env.getEntityManager(); try { env.beginTransaction(em); Department dep = new Department(17, "R&D"); Employee emp = new Employee(EMP_ID_VALUE, "Hans", "Wurst", dep); Review r1 = new Review(1, Date.valueOf("2005-10-07"), "bla"); Review r2 = new Review(2, Date.valueOf("2005-10-08"), "ble"); Review r3 = new Review(3, Date.valueOf("2005-10-09"), "bli"); emp.addReview(r1); emp.addReview(r2); emp.addReview(r3); em.persist(dep); em.persist(emp); em.persist(r1); em.persist(r2); em.persist(r3); env.commitTransactionAndClear(em); } finally { closeEntityManager(em); } } @Test public void testUnchanged() throws SQLException { JPAEnvironment env = getEnvironment(); EntityManager em = env.getEntityManager(); try { // 1. do nothing env.beginTransaction(em); Employee emp = em.find(Employee.class, EMP_ID); // do nothing emp.clearPostUpdate(); env.commitTransactionAndClear(em); verify(!emp.postUpdateWasCalled(), "postUpdate was called"); checkJoinTable(SEED_SET); // 2. touch the reviews env.beginTransaction(em); emp = em.find(Employee.class, EMP_ID); emp.getReviews().size(); emp.clearPostUpdate(); env.commitTransactionAndClear(em); verify(!emp.postUpdateWasCalled(), "postUpdate was called"); checkJoinTable(SEED_SET); // 3. trivial update env.beginTransaction(em); emp = em.find(Employee.class, EMP_ID); Set<Review> reviews = emp.getReviews(); emp.setReviews(new HashSet<Review>(reviews)); emp.clearPostUpdate(); env.commitTransactionAndClear(em); verify(!emp.postUpdateWasCalled(), "postUpdate was called"); checkJoinTable(SEED_SET); } finally { closeEntityManager(em); } } private void checkJoinTable(Set<Pair> expected) throws SQLException { DataSource ds = getEnvironment().getDataSource(); Connection conn = ds.getConnection(); try { PreparedStatement pstmt = conn.prepareStatement("SELECT EMP_ID, REVIEW_ID FROM TMP_EMP_REVIEW"); try { ResultSet rs = pstmt.executeQuery(); try { Set<Pair> actual = new HashSet<Pair>(); while (rs.next()) { actual.add(new Pair(rs.getInt("EMP_ID"), rs.getInt("REVIEW_ID"))); } verify(expected.size() == actual.size(), "actual set has wrong size " + actual.size() + " expected: " + expected.size()); verify(expected.containsAll(actual), "actual set contains some elements missing in the expecetd set"); verify(actual.containsAll(expected), "expected set contains some elements missing in the actual set"); } finally { rs.close(); } } finally { pstmt.close(); } } finally { conn.close(); } } @Test public void testDeleteEmployee() throws SQLException { JPAEnvironment env = getEnvironment(); EntityManager em = env.getEntityManager(); try { env.beginTransaction(em); Employee emp = em.find(Employee.class, EMP_ID); verify(emp != null, "employee not found"); em.remove(emp); env.commitTransactionAndClear(em); checkJoinTable(new HashSet<Pair>()); } finally { closeEntityManager(em); } } @Test public void testDeleteReview() throws SQLException { JPAEnvironment env = getEnvironment(); EntityManager em = env.getEntityManager(); try { env.beginTransaction(em); Employee emp = em.find(Employee.class, EMP_ID); verify(emp != null, "employee not found"); Set reviews = emp.getReviews(); verify(reviews != null, "reviews are null"); verify(reviews.size() == 3, "not exactly 3 reviews but " + reviews.size()); Iterator iter = reviews.iterator(); Review review = (Review) iter.next(); int removedId = review.getId(); // there are no managed relationships -> we have to remove the reviews on both sides em.remove(review); iter.remove(); emp.clearPostUpdate(); env.commitTransactionAndClear(em); verify(emp.postUpdateWasCalled(), "post update was not called"); Set<Pair> expected = new HashSet<Pair>(SEED_SET); expected.remove(new Pair(EMP_ID_VALUE, removedId)); checkJoinTable(expected); env.beginTransaction(em); emp = em.find(Employee.class, EMP_ID); reviews = emp.getReviews(); verify(reviews.size() == 2, "not exactly 2 reviews but " + reviews.size()); Object object = em.find(Review.class, new Integer(removedId)); verify(object == null, "review found"); env.rollbackTransactionAndClear(em); } finally { closeEntityManager(em); } } @Test public void testAdd() throws SQLException { JPAEnvironment env = getEnvironment(); EntityManager em = env.getEntityManager(); try { env.beginTransaction(em); Employee emp = em.find(Employee.class, EMP_ID); verify(emp != null, "employee not found"); Set<Review> reviews = emp.getReviews(); Review r4 = new Review(4, Date.valueOf("2005-10-10"), "blo"); em.persist(r4); reviews.add(r4); emp.clearPostUpdate(); env.commitTransactionAndClear(em); verify(emp.postUpdateWasCalled(), "post update was not called"); Set<Pair> expected = new HashSet<Pair>(SEED_SET); expected.add(new Pair(EMP_ID_VALUE, 4)); checkJoinTable(expected); env.beginTransaction(em); emp = em.find(Employee.class, EMP_ID); reviews = emp.getReviews(); verify(reviews.size() == 4, "not exactly 4 reviews but " + reviews.size()); env.rollbackTransactionAndClear(em); } finally { closeEntityManager(em); } } @Test public void testExchange() throws SQLException { JPAEnvironment env = getEnvironment(); EntityManager em = env.getEntityManager(); try { env.beginTransaction(em); Employee emp = em.find(Employee.class, EMP_ID); verify(emp != null, "employee not found"); Set<Review> reviews = emp.getReviews(); Iterator iter = reviews.iterator(); Review review = (Review) iter.next(); int removedId = review.getId(); // there are no managed relationships -> we have to remove the reviews on both sides em.remove(review); iter.remove(); Review r4 = new Review(4, Date.valueOf("2005-10-10"), "blo"); em.persist(r4); reviews.add(r4); emp.clearPostUpdate(); env.commitTransactionAndClear(em); verify(emp.postUpdateWasCalled(), "post update was not called"); Set<Pair> expected = new HashSet<Pair>(SEED_SET); expected.remove(new Pair(EMP_ID_VALUE, removedId)); expected.add(new Pair(EMP_ID_VALUE, 4)); checkJoinTable(expected); env.beginTransaction(em); emp = em.find(Employee.class, EMP_ID); reviews = emp.getReviews(); verify(reviews.size() == 3, "not exactly 3 reviews but " + reviews.size()); env.rollbackTransactionAndClear(em); } finally { closeEntityManager(em); } } @Test public void testMoveAllReviews() throws SQLException { JPAEnvironment env = getEnvironment(); EntityManager em = env.getEntityManager(); try { final int newId = 15; env.beginTransaction(em); Employee emp = em.find(Employee.class, EMP_ID); verify(emp != null, "employee not found"); Set<Review> reviews = emp.getReviews(); Employee newEmp = new Employee(newId, "Paulchen", "M\u00fcller", null); newEmp.setReviews(reviews); emp.setReviews(null); em.persist(newEmp); emp.clearPostUpdate(); env.commitTransactionAndClear(em); verify(emp.postUpdateWasCalled(), "post update was not called"); Set<Pair> expected = new HashSet<Pair>(); expected.add(new Pair(newId, 1)); expected.add(new Pair(newId, 2)); expected.add(new Pair(newId, 3)); checkJoinTable(expected); env.beginTransaction(em); emp = em.find(Employee.class, Integer.valueOf(newId)); reviews = emp.getReviews(); verify(reviews.size() == 3, "not exactly 3 reviews but " + reviews.size()); env.rollbackTransactionAndClear(em); } finally { closeEntityManager(em); } } private static class Pair { /* * (non-Javadoc) * * @see java.lang.Object#equals(java.lang.Object) */ @Override public boolean equals(Object obj) { if (obj instanceof Pair) { Pair other = (Pair) obj; return other.empId == empId && other.reviewId == reviewId; } return false; } /* * (non-Javadoc) * * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return empId + 17 * reviewId; } /** * @return Returns the empId. */ @SuppressWarnings("unused") public int getEmpId() { return empId; } /** * @return Returns the reviewId. */ @SuppressWarnings("unused") public int getReviewId() { return reviewId; } final int empId; final int reviewId; Pair(int e, int r) { empId = e; reviewId = r; } } }