Package ch.inftec.ju.db

Source Code of ch.inftec.ju.db.MultiplePersistenceUnitsTest$EntityManagerTest

package ch.inftec.ju.db;

import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import junit.framework.Assert;

import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.TransactionSynchronizationManager;

import ch.inftec.ju.testing.db.data.entity.Team;
import ch.inftec.ju.testing.db.data.repo.TeamRepo;
import ch.inftec.ju.testing.db.data.repo.TestingEntityRepo;
import ch.inftec.ju.util.JuCollectionUtils;

/**
* Test class to see how multiple persistenceUnits and dataSources (including
* the corresponding transactions) are handled.
* <p>
* Note: Even though one can have multiple PersistenceUnits defined, one need to explicitly
* define which one to inject EVERY TIME a PersistenceContext is used.
* @author Martin
*
*/
public class MultiplePersistenceUnitsTest {
  public static class EntityManagerTest {
    @PersistenceContext(unitName="TeamPlayer PU")
    private EntityManager entityManager;
   
    @Autowired
    private JuDbUtils juDbUtils;
   
    @Autowired
    private TeamRepo teamRepo;
   
    @Autowired
    private ConnectionInfoContextHolder contextHolder;
   
    private boolean tableForSecondUnitCreated = false;
   
    @Transactional // Must be transactional to unwrap session
    public void createDb() {
      this.juDbUtils.createDefaultTables();
    }
   
    public int teamCount() {
      return (int) this.teamRepo.count();
    }
   
    public String teamName(Long id) {
      return this.teamRepo.findOne(id).getName();
    }
   
    public boolean exists(Long id) {
      return this.teamRepo.exists(id);
    }
   
    public boolean exists(String name) {
      return this.teamRepo.getByName(name) != null;
    }
   
    public Long insertTeam(String name, boolean throwException) {
      Long id = this.doInsertTeam(name);
     
      if (throwException) {
        throw new RuntimeException("No Rollback");
      }
     
      return id;
    }
   
    @Transactional
    public Long insertTeamTx(String name, boolean throwException) {
      Long id = this.doInsertTeam(name);
     
      if (throwException) {
        throw new RuntimeException("Rollback");
      }
     
      return id;
    }
   
    @Transactional(propagation=Propagation.REQUIRES_NEW)
    public Long insertTeamNewTx(String name, boolean throwException) {
      Long id = this.doInsertTeam(name);
     
      if (throwException) {
        throw new RuntimeException("Rollback");
      }
     
      return id;
    }
   
    @Transactional
    public void tryToSwitchConnectionInfoBetweenTx(ConnectionInfo connectionInfo) {
      this.insertTeam("switchTest1", false);
      this.contextHolder.setConnectionInfo(connectionInfo);
      this.insertTeam("switchTest2", false);
    }
   
    @Transactional
    public void tryToSwitchConnectionInfoBeforeTx(ConnectionInfo connectionInfo) {
      this.contextHolder.setConnectionInfo(connectionInfo);
      this.insertTeam("switchTest3", false);
    }
   
    @Transactional
    public Long tryToSwitchConnectionInfoForNewTransactionTx(ConnectionInfo connectionInfo) {
      this.contextHolder.setConnectionInfo(connectionInfo);
      return this.insertTeamNewTx("switchTestNewTx", false);
    }
   
    public boolean transactionStatusTest() {
      return TransactionSynchronizationManager.isActualTransactionActive();
//      // Should throw an Exception if we have not transaction
//      TransactionInterceptor.currentTransactionStatus();
    }
   
    @Transactional
    public boolean transactionStatusTestTx() {
      return TransactionSynchronizationManager.isActualTransactionActive();
//      TransactionStatus status = TransactionInterceptor.currentTransactionStatus();
    }
   
    private Long doInsertTeam(String name) {
      Team t = new Team();
      t.setName(name);
     
      // See http://stackoverflow.com/questions/8625150/why-to-use-returned-instance-after-save-on-spring-data-jpa-repository
      t = this.teamRepo.save(t);
      return t.getId();
    }
  }
 
  public static class EntityManagerTestingEntityTest {
    @PersistenceContext(unitName="TestingEntity PU")
    private EntityManager entityManager;
   
    @Autowired
    private TestingEntityRepo testingEntityRepo;
   
    @Autowired
    private InheritingEntityManagerTest inheritingEmTest;
   
    public int testingEntityCount() {
      return (int) this.testingEntityRepo.count();
    }
   
    public int inheritedTestingEntityCount() {
      return this.inheritingEmTest.testingEntityCount();
    }
  }
 
  public static class InheritingEntityManagerTest {
    @PersistenceContext(unitName="TestingEntity PU") // PersistenceContext is not "inherited"...
    private EntityManager entityManager;
   
    public int testingEntityCount() {
      return (int) this.entityManager.createQuery("select t from TestingEntity t").getResultList().size();
    }
  }
 
  /**
   * JdbcTemplate tests, using raw SQL
   * @author Martin
   *
   */
  public static class JdbcTemplateTest {
    @PersistenceContext(unitName="TeamPlayer PU")
    private EntityManager entityManager;
   
    @Autowired
    private ConnectionInfoContextHolder contextHolder;
   
    @Autowired
    private JdbcTemplate jdbcTemplate;
   
//    @Autowired
//    private JuDbUtils juDbUtils;
   
    public int teamCount() {
      return jdbcTemplate.queryForInt("select count(*) from Team");
    }
   
    public String teamName(Long id) {
      return jdbcTemplate.queryForObject("select name from Team where id=?", String.class, id);
    }
   
    public void insertTeam(Long id, String name, boolean throwException) {
      this.doInsertTeam(id, name);
     
      if (throwException) {
        throw new RuntimeException("No Rollback");
      }
    }
   
    @Transactional
    public void insertTeamTx(Long id, String name, boolean throwException) {
      this.doInsertTeam(id, name);
     
      if (throwException) {
        throw new RuntimeException("Rollback");
      }
    }
   
    private void doInsertTeam(Long id, String name) {
      this.jdbcTemplate.update("insert into Team (id, name, ranking, version) values (?, ?, 0, 0)", id, name);
    }
  }
 
  @Test
  public void multiplePersistenceUnits() {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:/ch/inftec/ju/db/MultiplePersistenceUnitsTest-context.xml");
    ConnectionInfoContextHolder contextHolder = context.getBean(ConnectionInfoContextHolder.class);
   
    EntityManagerTest entityManagerTest = context.getBean(EntityManagerTest.class);
    entityManagerTest.createDb();
   
    // JDBC tests
   
    JdbcTemplateTest jdbcTemplateTest = context.getBean(JdbcTemplateTest.class);
   
    // Access Team DB (without transaction)
    Assert.assertEquals(0, jdbcTemplateTest.teamCount());
    jdbcTemplateTest.insertTeam(-1L, "Team-1", false);
    Assert.assertEquals(1, jdbcTemplateTest.teamCount());
   
    // Access Team DB (with transaction, with and without rollback)
    try {
      jdbcTemplateTest.insertTeamTx(-2L, "Team-2-rb", true);
    } catch (RuntimeException ex) {
      Assert.assertEquals("Rollback", ex.getMessage());     
    }
    Assert.assertEquals(1, jdbcTemplateTest.teamCount());
    jdbcTemplateTest.insertTeamTx(-2L, "Team-2", false);
    Assert.assertEquals("Team-2", jdbcTemplateTest.teamName(-2L));
   
    // Try access with exception and no transaction
    try {
      jdbcTemplateTest.insertTeam(-3L, "Team-3-noRb", true);
    } catch (RuntimeException ex) {
      Assert.assertEquals("No Rollback", ex.getMessage());
    }
    Assert.assertEquals("Team-3-noRb", jdbcTemplateTest.teamName(-3L));
   
    // EntityManager tests
    Assert.assertEquals("Team-1", entityManagerTest.teamName(-1L));
    Assert.assertEquals(3, entityManagerTest.teamCount());
   
    // Access Team DB (with transaction, with and without rollback)
    try {
      entityManagerTest.insertTeamTx("Team-2-rb", true);
    } catch (RuntimeException ex) {
      Assert.assertEquals("Rollback", ex.getMessage());     
    }
    Assert.assertEquals(3, entityManagerTest.teamCount());
    Long et2 = entityManagerTest.insertTeamTx("Team-2", false);
    Assert.assertEquals("Team-2", jdbcTemplateTest.teamName(et2));
    Assert.assertEquals(4, jdbcTemplateTest.teamCount());
   
    // Try access with exception and no transaction
    try {
      entityManagerTest.insertTeam("Team-3-noRb", true);
    } catch (RuntimeException ex) {
      Assert.assertEquals("No Rollback", ex.getMessage());
    }
    Assert.assertEquals(5, jdbcTemplateTest.teamCount());
   
    // Test different PersistenceUnit
    EntityManagerTestingEntityTest emTeTest = context.getBean(EntityManagerTestingEntityTest.class);
    Assert.assertEquals(0, emTeTest.testingEntityCount());
   
    // Test EntityManager inheritance
    Assert.assertEquals(0, emTeTest.inheritedTestingEntityCount());
   
    // Test DataSource switching
    List<ConnectionInfo> availableConnections = JuCollectionUtils.asList(contextHolder.getAvailableConnectionInfos());
    ConnectionInfo ci1 = availableConnections.get(0);
    ConnectionInfo ci2 = availableConnections.get(1);
   
    Assert.assertEquals("TeamPlayer DB1", ci1.getName());
    Assert.assertEquals("TeamPlayer DB2", ci2.getName());
   
    // Insert Entity in DB1
    contextHolder.setConnectionInfo(ci1);
    Long etDb1a = entityManagerTest.insertTeam("DB1 a", false);
    Assert.assertEquals("DB1 a", entityManagerTest.teamName(etDb1a));
   
    // Switch to DB2 and make sure it isn't there
    contextHolder.setConnectionInfo(ci2);
    entityManagerTest.createDb();
    Assert.assertFalse(entityManagerTest.exists(etDb1a));
   
    // Insert Object in DB2
    Long etDb2a = entityManagerTest.insertTeam("DB2 a", false);
    Assert.assertEquals("DB2 a", entityManagerTest.teamName(etDb2a));
   
    // Try to switch DB in a transaction after objects have been inserted...
    entityManagerTest.tryToSwitchConnectionInfoBetweenTx(ci1);
    // As we run the switch within the transaction, the Connection will not be
    // reopened, thus the switch is performed AFTER the transaction ends. All
    // objects are inserted in the ci2
    Assert.assertFalse(entityManagerTest.exists("switchTest2"));
   
    // Check if the objects have been created in ci2
    contextHolder.setConnectionInfo(ci2);
    Assert.assertTrue(entityManagerTest.exists("switchTest1"));
    Assert.assertTrue(entityManagerTest.exists("switchTest2"));

    entityManagerTest.tryToSwitchConnectionInfoBeforeTx(ci1);
    // The transaction is started when the method is accessed, so we cannot
    // change the DataSource within a transactional method...
    Assert.assertFalse(entityManagerTest.exists("switchTest3"));
    // Check if the object was created in ci2
    contextHolder.setConnectionInfo(ci2);
    Assert.assertTrue(entityManagerTest.exists("switchTest3"));
   
    // Try to switch DB for a new transaction
    Long etDb1b = entityManagerTest.tryToSwitchConnectionInfoForNewTransactionTx(ci1);
    // The new transaction will NOT use the new ConnectionInfo, but the one that
    // was set before the transaction started
    Assert.assertFalse(entityManagerTest.exists(etDb1b));
    contextHolder.setConnectionInfo(ci2);
    Assert.assertEquals("switchTestNewTx", entityManagerTest.teamName(etDb1b));
   
    // Check transaction status
    Assert.assertFalse(entityManagerTest.transactionStatusTest());
    Assert.assertTrue(entityManagerTest.transactionStatusTestTx());
   
    // Try to switch DB in a transaction BEFORE an object has been inserted
    context.close();
  }
 
}
TOP

Related Classes of ch.inftec.ju.db.MultiplePersistenceUnitsTest$EntityManagerTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.