package com.vladmihalcea.hibernate.type.util; import com.vladmihalcea.hibernate.type.util.providers.DataSourceProvider; import com.vladmihalcea.hibernate.type.util.providers.HSQLDBDataSourceProvider; import com.vladmihalcea.hibernate.type.util.transaction.*; import org.hibernate.Interceptor; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import org.hibernate.ejb.EntityManagerFactoryImpl; import org.hibernate.ejb.HibernatePersistence; import org.hibernate.engine.transaction.spi.LocalStatus; import org.hibernate.integrator.spi.Integrator; import org.hibernate.jdbc.Work; import org.hibernate.service.BootstrapServiceRegistryBuilder; import org.hibernate.type.Type; import org.junit.After; import org.junit.Before; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.spi.PersistenceUnitInfo; import javax.sql.DataSource; import java.io.Closeable; import java.io.IOException; import java.sql.Connection; import java.sql.SQLException; import java.util.*; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicReference; public abstract class AbstractTest { static { Thread.currentThread().setName("Alice"); } protected final ExecutorService executorService = Executors.newSingleThreadExecutor(new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread bob = new Thread(r); bob.setName("Bob"); return bob; } }); protected final Logger LOGGER = LoggerFactory.getLogger(getClass()); private EntityManagerFactory emf; private SessionFactory sf; private List<Closeable> closeables = new ArrayList<Closeable>(); @Before public void init() { if(nativeHibernateSessionFactoryBootstrap()) { sf = newSessionFactory(); } else { emf = newEntityManagerFactory(); } afterInit(); } protected void afterInit() { } @After public void destroy() { if (nativeHibernateSessionFactoryBootstrap()) { sf.close(); } else { emf.close(); } for (Closeable closeable : closeables) { try { closeable.close(); } catch (IOException e) { LOGGER.error("Failure", e); } } closeables.clear(); } public EntityManagerFactory entityManagerFactory() { return nativeHibernateSessionFactoryBootstrap() ? null : emf; } public SessionFactory sessionFactory() { return nativeHibernateSessionFactoryBootstrap() ? sf : ((EntityManagerFactoryImpl) entityManagerFactory()).getSessionFactory(); } protected boolean nativeHibernateSessionFactoryBootstrap() { return false; } protected abstract Class<?>[] entities(); protected List<String> entityClassNames() { List<String> classNames = new ArrayList<String>(); for (Class entityClass : entities()) { classNames.add(entityClass.getName()); } return classNames; } protected String[] packages() { return null; } protected String[] resources() { return null; } protected Interceptor interceptor() { return null; } private SessionFactory newSessionFactory() { Properties properties = properties(); Configuration configuration = new Configuration().addProperties(properties); for (Class<?> entityClass : entities()) { configuration.addAnnotatedClass(entityClass); } String[] packages = packages(); if (packages != null) { for (String scannedPackage : packages) { configuration.addPackage(scannedPackage); } } String[] resources = resources(); if (resources != null) { for (String resource : resources) { configuration.addResource(resource); } } Interceptor interceptor = interceptor(); if (interceptor != null) { configuration.setInterceptor(interceptor); } configuration.setProperties(properties); return configuration.buildSessionFactory( new BootstrapServiceRegistryBuilder() .build() ); } protected EntityManagerFactory newEntityManagerFactory() { PersistenceUnitInfo persistenceUnitInfo = persistenceUnitInfo(getClass().getSimpleName()); Map<String, Object> configuration = new HashMap<String, Object>(); HibernatePersistence hibernatePersistence = new HibernatePersistence(); return hibernatePersistence.createContainerEntityManagerFactory(persistenceUnitInfo, configuration); } protected PersistenceUnitInfoImpl persistenceUnitInfo(String name) { PersistenceUnitInfoImpl persistenceUnitInfo = new PersistenceUnitInfoImpl( name, entityClassNames(), properties() ); String[] resources = resources(); if (resources != null) { persistenceUnitInfo.getMappingFileNames().addAll(Arrays.asList(resources)); } return persistenceUnitInfo; } protected Properties properties() { Properties properties = new Properties(); properties.put("hibernate.dialect", dataSourceProvider().hibernateDialect()); //log settings properties.put("hibernate.hbm2ddl.auto", "create-drop"); //data source settings DataSource dataSource = newDataSource(); if (dataSource != null) { properties.put("hibernate.connection.datasource", dataSource); } additionalProperties(properties); return properties; } protected void additionalProperties(Properties properties) { } protected DataSourceProxyType dataSourceProxyType() { return DataSourceProxyType.DATA_SOURCE_PROXY; } protected DataSource newDataSource() { DataSource dataSource = proxyDataSource() ? dataSourceProxyType().dataSource(dataSourceProvider().dataSource()) : dataSourceProvider().dataSource(); return dataSource; } protected boolean proxyDataSource() { return true; } protected DataSourceProvider dataSourceProvider() { return new HSQLDBDataSourceProvider(); } protected <T> T doInHibernate(HibernateTransactionFunction<T> callable) { T result = null; Session session = null; Transaction txn = null; try { session = sessionFactory().openSession(); callable.beforeTransactionCompletion(); txn = session.beginTransaction(); result = callable.apply(session); if (txn.getLocalStatus() == LocalStatus.ACTIVE) { txn.commit(); } else { try { txn.rollback(); } catch (Exception e) { LOGGER.error("Rollback failure", e); } } } catch (Throwable t) { if (txn != null && txn.getLocalStatus() == LocalStatus.ACTIVE) { try { txn.rollback(); } catch (Exception e) { LOGGER.error("Rollback failure", e); } } throw new RuntimeException(t); } finally { callable.afterTransactionCompletion(); if (session != null) { session.close(); } } return result; } protected void doInHibernate(HibernateTransactionConsumer callable) { Session session = null; Transaction txn = null; try { session = sessionFactory().openSession(); callable.beforeTransactionCompletion(); txn = session.beginTransaction(); callable.accept(session); if (txn.getLocalStatus() == LocalStatus.ACTIVE) { txn.commit(); } else { try { txn.rollback(); } catch (Exception e) { LOGGER.error("Rollback failure", e); } } } catch (Throwable t) { if (txn != null && txn.getLocalStatus() == LocalStatus.ACTIVE) { try { txn.rollback(); } catch (Exception e) { LOGGER.error("Rollback failure", e); } } throw new RuntimeException(t); } finally { callable.afterTransactionCompletion(); if (session != null) { session.close(); } } } protected <T> T doInJPA(JPATransactionFunction<T> function) { T result = null; EntityManager entityManager = null; EntityTransaction txn = null; try { entityManager = entityManagerFactory().createEntityManager(); function.beforeTransactionCompletion(); txn = entityManager.getTransaction(); txn.begin(); result = function.apply(entityManager); if (!txn.getRollbackOnly()) { txn.commit(); } else { try { txn.rollback(); } catch (Exception e) { LOGGER.error("Rollback failure", e); } } } catch (Throwable t) { if (txn != null) { try { txn.rollback(); } catch (Exception e) { LOGGER.error("Rollback failure", e); } } throw new RuntimeException(t); } finally { function.afterTransactionCompletion(); if (entityManager != null) { entityManager.close(); } } return result; } protected void doInJPA(JPATransactionVoidFunction function) { EntityManager entityManager = null; EntityTransaction txn = null; try { entityManager = entityManagerFactory().createEntityManager(); function.beforeTransactionCompletion(); txn = entityManager.getTransaction(); txn.begin(); function.accept(entityManager); if (!txn.getRollbackOnly()) { txn.commit(); } else { try { txn.rollback(); } catch (Exception e) { LOGGER.error("Rollback failure", e); } } } catch (Throwable t) { if (txn != null) { try { txn.rollback(); } catch (Exception e) { LOGGER.error("Rollback failure", e); } } throw new RuntimeException(t); } finally { function.afterTransactionCompletion(); if (entityManager != null) { entityManager.close(); } } } protected <T> T doInJDBC(final ConnectionCallable<T> callable) { final AtomicReference<T> result = new AtomicReference<T>(); Session session = null; Transaction txn = null; try { session = sessionFactory().openSession(); txn = session.beginTransaction(); session.doWork(new Work() { @Override public void execute(Connection connection) throws SQLException { result.set(callable.execute(connection)); } }); if (txn.getLocalStatus() == LocalStatus.ACTIVE) { txn.commit(); } else { try { txn.rollback(); } catch (Exception e) { LOGGER.error("Rollback failure", e); } } } catch (Throwable t) { if (txn != null && txn.getLocalStatus() == LocalStatus.ACTIVE) { try { txn.rollback(); } catch (Exception e) { LOGGER.error("Rollback failure", e); } } throw new RuntimeException(t); } finally { if (session != null) { session.close(); } } return result.get(); } protected void doInJDBC(final ConnectionVoidCallable callable) { Session session = null; Transaction txn = null; try { session = sessionFactory().openSession(); txn = session.beginTransaction(); session.doWork(new Work() { @Override public void execute(Connection connection) throws SQLException { callable.execute(connection); } }); if (txn.getLocalStatus() == LocalStatus.ACTIVE) { txn.commit(); } else { try { txn.rollback(); } catch (Exception e) { LOGGER.error("Rollback failure", e); } } } catch (Throwable t) { if (txn != null && txn.getLocalStatus() == LocalStatus.ACTIVE) { try { txn.rollback(); } catch (Exception e) { LOGGER.error("Rollback failure", e); } } throw new RuntimeException(t); } finally { if (session != null) { session.close(); } } } }