package net.rrm.ehour.persistence.hibernate; import com.google.common.collect.Lists; import net.rrm.ehour.appconfig.EhourHomeUtil; import net.rrm.ehour.persistence.database.Database; import net.rrm.ehour.persistence.database.DatabaseConfig; import org.apache.derby.jdbc.EmbeddedConnectionPoolDataSource; import org.apache.log4j.Logger; import org.hibernate.SessionFactory; import org.hibernate.cache.ehcache.EhCacheRegionFactory; import org.hibernate.cfg.AvailableSettings; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; import org.springframework.orm.hibernate4.HibernateTransactionManager; import org.springframework.orm.hibernate4.LocalSessionFactoryBean; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; import java.io.IOException; import java.sql.SQLException; import java.util.List; import java.util.Properties; @Configuration @EnableTransactionManagement public class HibernateConfiguration { protected static final PathMatchingResourcePatternResolver RESOLVER = new PathMatchingResourcePatternResolver(); private static final Logger LOGGER = Logger.getLogger(HibernateConfiguration.class); private boolean isInTestMode() { return Boolean.parseBoolean(System.getProperty("EHOUR_TEST", "false")); } @Bean(name = "sessionFactory") @Autowired public SessionFactory getSessionFactory(DatabaseConfig databaseConfig) throws Exception { String databaseName = databaseConfig.databaseType.name().toLowerCase(); Properties configProperties = EhourHomeUtil.loadDatabaseProperties(databaseName); LOGGER.info("Using database type: " + databaseName); LocalSessionFactoryBean sessionFactoryBean = new LocalSessionFactoryBean(); if (databaseConfig.databaseType == Database.DERBY) { EmbeddedConnectionPoolDataSource dataSource = createDerbyDataSource(); sessionFactoryBean.setDataSource(dataSource); } List<Resource> mappingResources = getMappingResources(configProperties); sessionFactoryBean.setMappingLocations(mappingResources.toArray(new Resource[mappingResources.size()])); sessionFactoryBean.setPackagesToScan(getPackagesToScan()); Properties hibernateProperties = getHibernateProperties(configProperties, databaseConfig); sessionFactoryBean.setHibernateProperties(hibernateProperties); beforeFinalizingSessionFactoryBean(sessionFactoryBean); sessionFactoryBean.afterPropertiesSet(); return sessionFactoryBean.getObject(); } private EmbeddedConnectionPoolDataSource createDerbyDataSource() throws SQLException { if (isInTestMode()) { EmbeddedConnectionPoolDataSource dataSource = new EmbeddedConnectionPoolDataSource(); dataSource.setDatabaseName("memory:ehourDb"); return dataSource; } else { EmbeddedConnectionPoolDataSource dataSource = new EmbeddedConnectionPoolDataSource(); dataSource.setDatabaseName("ehourDb"); return dataSource; } } private Properties getHibernateProperties(Properties configProperties, DatabaseConfig databaseConfig) { Properties hibernateProperties = new Properties(); hibernateProperties.setProperty(AvailableSettings.DIALECT, (String) configProperties.get("hibernate.dialect")); hibernateProperties.setProperty(AvailableSettings.SHOW_SQL, "false"); hibernateProperties.setProperty("net.sf.ehcache.configurationResourceName", "hibernate-ehcache.xml"); hibernateProperties.put(AvailableSettings.CACHE_REGION_FACTORY, EhCacheRegionFactory.class.getName()); hibernateProperties.setProperty(AvailableSettings.USE_SECOND_LEVEL_CACHE, "true"); hibernateProperties.setProperty(AvailableSettings.USE_QUERY_CACHE, "true"); addConnectionProvider(hibernateProperties, databaseConfig); if (databaseConfig.databaseType != Database.DERBY) { hibernateProperties.setProperty(AvailableSettings.URL, databaseConfig.url); hibernateProperties.setProperty(AvailableSettings.DRIVER, databaseConfig.driver); hibernateProperties.setProperty(AvailableSettings.USER, databaseConfig.username); hibernateProperties.setProperty(AvailableSettings.PASS, databaseConfig.password); } hibernateProperties.setProperty(AvailableSettings.AUTOCOMMIT, "false"); hibernateProperties.setProperty("dataSource.cachePrepStmts", "true"); hibernateProperties.setProperty("dataSource.prepStmtCacheSize", "250"); hibernateProperties.setProperty("dataSource.prepStmtCacheSqlLimit", "2048"); hibernateProperties.setProperty("dataSource.useServerPrepStmts", "true"); String validateSchema = (String) configProperties.get(AvailableSettings.HBM2DDL_AUTO); if (!"false".equalsIgnoreCase(validateSchema)) { hibernateProperties.setProperty(AvailableSettings.HBM2DDL_AUTO, validateSchema); } return hibernateProperties; } protected void addConnectionProvider(Properties hibernateProperties, DatabaseConfig databaseConfig) { if (databaseConfig.databaseType != Database.DERBY) { hibernateProperties.setProperty(AvailableSettings.CONNECTION_PROVIDER, HikariConnectionProvider.class.getCanonicalName()); } } protected void beforeFinalizingSessionFactoryBean(LocalSessionFactoryBean bean) { } protected String[] getPackagesToScan() { return new String[]{"net.rrm.ehour.domain"}; } protected List<Resource> getMappingResources(Properties configProperties) throws IOException { Resource[] queryResources = RESOLVER.getResources("classpath:query/common/*.hbm.xml"); ClassPathResource dbQueryResource = new ClassPathResource("query/" + configProperties.getProperty("reportquery.filename")); return Lists.asList(dbQueryResource, queryResources); } @Bean @Autowired public PlatformTransactionManager txManager(DatabaseConfig databaseConfig) { try { return new HibernateTransactionManager(getSessionFactory(databaseConfig)); } catch (Exception e) { throw new RuntimeException("Screwed", e); } } @Bean public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { return new PersistenceExceptionTranslationPostProcessor(); } }