/* * Copyright 2011-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package kr.debop4j.data.hibernate.spring; import kr.debop4j.core.tools.StringTool; import kr.debop4j.data.hibernate.forTesting.UnitOfWorkTestContextBase; import kr.debop4j.data.hibernate.interceptor.MultiInterceptor; import kr.debop4j.data.hibernate.interceptor.StatefulEntityInterceptor; import kr.debop4j.data.hibernate.interceptor.UpdateTimestampedInterceptor; import kr.debop4j.data.hibernate.repository.IHibernateDao; import kr.debop4j.data.hibernate.repository.IHibernateRepositoryFactory; import kr.debop4j.data.hibernate.repository.impl.HibernateDao; import kr.debop4j.data.hibernate.repository.impl.HibernateRepositoryFactory; import kr.debop4j.data.hibernate.tools.HibernateTool; import kr.debop4j.data.hibernate.unitofwork.IUnitOfWorkFactory; import kr.debop4j.data.hibernate.unitofwork.UnitOfWorkFactory; import kr.debop4j.data.hibernate.unitofwork.UnitOfWorks; import kr.debop4j.data.jdbc.JdbcTool; import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; import org.hibernate.ConnectionReleaseMode; import org.hibernate.Interceptor; import org.hibernate.SessionFactory; import org.hibernate.cfg.Environment; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.orm.hibernate4.HibernateTransactionManager; import org.springframework.orm.hibernate4.LocalSessionFactoryBean; import org.springframework.transaction.annotation.EnableTransactionManagement; import javax.sql.DataSource; import java.io.IOException; import java.util.Properties; /** * hibernate 의 환경설정을 spring framework의 bean 환경설정으로 구현했습니다. * * @author 배성혁 ( sunghyouk.bae@gmail.com ) * @since 13. 2. 21. */ @Slf4j @Configuration @EnableTransactionManagement @ComponentScan(basePackageClasses = { UnitOfWorks.class, HibernateTool.class }) public abstract class HibernateConfigBase { @Getter @Setter private UnitOfWorkTestContextBase testContext; /** Database 명 */ abstract public String getDatabaseName(); /** Database JDBC URL */ abstract public String getJdbcUrl(); /** 사용자 Id */ public String getUsername() { return ""; } /** 사용자 비밀번호 */ public String getPassword() { return ""; } /** 매핑된 엔티티가 있는 Pagacke 명들 */ abstract protected String[] getMappedPackageNames(); /** Hibernate 설정 값 */ protected Properties hibernateProperties() { Properties props = new Properties(); props.put(Environment.FORMAT_SQL, "true"); props.put(Environment.HBM2DDL_AUTO, "create"); // create | spawn | spawn-drop | update | validate | none props.put(Environment.SHOW_SQL, "true"); props.put(Environment.RELEASE_CONNECTIONS, ConnectionReleaseMode.ON_CLOSE); props.put(Environment.AUTOCOMMIT, "true"); props.put(Environment.STATEMENT_BATCH_SIZE, "30"); return props; } /** * Build data source. * * @param driverClass the driver class * @param url the url * @param username the username * @param password the password * @return the data source */ protected DataSource buildDataSource(String driverClass, String url, String username, String password) { return JdbcTool.getDataSource(driverClass, url, username, password); } protected DataSource buildEmbeddedDataSource() { return JdbcTool.getEmbeddedHsqlDataSource(); } /** * Provide {@link DataSource}. * * @return the data source */ @Bean(destroyMethod = "close") abstract public DataSource dataSource(); /** factoryBean 에 추가 설정을 지정할 수 있습니다. */ protected void setupSessionFactory(LocalSessionFactoryBean factoryBean) { } /** * Provide Hibernate ISessionFactory. * * @return the session factory */ @Bean public SessionFactory sessionFactory() { if (log.isInfoEnabled()) log.info("SessionFactory Bean을 생성합니다..."); LocalSessionFactoryBean factoryBean = new LocalSessionFactoryBean(); String[] packageNames = getMappedPackageNames(); if (packageNames != null) { log.info("hibernate용 entity를 scan합니다. packages=[{}]", StringTool.listToString(packageNames)); factoryBean.setPackagesToScan(packageNames); } factoryBean.setHibernateProperties(hibernateProperties()); factoryBean.setDataSource(dataSource()); factoryBean.setEntityInterceptor(hibernateInterceptor()); // Drived class에서 추가 작업을 수행할 수 있도록 합니다. setupSessionFactory(factoryBean); try { factoryBean.afterPropertiesSet(); log.info("SessionFactory Bean을 생성했습니다!!!"); return factoryBean.getObject(); } catch (IOException e) { throw new RuntimeException("SessionFactory 빌드에 실패했습니다.", e); } } /** * Hibernate transaction manager. * * @return the hibernate transaction manager */ @Bean public HibernateTransactionManager hibernateTransactionManager() { return new HibernateTransactionManager(sessionFactory()); } /** * Provide hibernate interceptor. * * @return Interceptor instance */ @Bean public Interceptor hibernateInterceptor() { MultiInterceptor interceptor = new MultiInterceptor(); interceptor.getInterceptors().add(new StatefulEntityInterceptor()); interceptor.getInterceptors().add(new UpdateTimestampedInterceptor()); return interceptor; } /** * Provide {@link IUnitOfWorkFactory} * * @return IUnitOfWorkFactory instance. */ @Bean public IUnitOfWorkFactory unitOfWorkFactory() { log.info("UnitOfWorkFactory를 생성합니다."); UnitOfWorkFactory factory = new UnitOfWorkFactory(); factory.setSessionFactory(sessionFactory()); return factory; } private static final String HIBERNATE_DAO_KEY = IHibernateDao.class.getName() + ".Current"; /** * {@link IHibernateDao}를 Transaction Context 별로 제공합니다. * * @return {@link IHibernateDao} instance. */ @Bean(name = { "hibernateDao" }) // @Scope("prototype") public IHibernateDao hibernateDao() { return new HibernateDao(true); // return Local.getOrCreate(HIBERNATE_DAO_KEY, // IHibernateDao.class, // new Function<IHibernateDao>() { // @Override // public IHibernateDao execute() { // return new HibernateDao(true); // } // }); } @Bean public IHibernateRepositoryFactory hibernateRepositoryFactory() { return new HibernateRepositoryFactory(); } }