Spring+Hibernate实现动态SessionFactory切换(改进版)
发现存在一些问题:
需要配置多个HibernateTransactionManager和多个Spring切面
这样带来两个问题
1.程序效率降低,因为Spring进行多次Advice的拦截
2.如果其中一个SessionFactory连接出现问题,会导致整个系统无法工作
今天研究出一种新的方法来解决此类问题
1. 数据源及Hibernate SessionFactory配置:import org.hibernate.SessionFactory; public interface DynamicSessionFactoryInf extends SessionFactory { public SessionFactory getHibernateSessionFactory(); }
3. 定义DynamicSessionFactory实现DynamicSessionFactoryInf
public class DynamicSessionFactory implements DynamicSessionFactoryInf ,ApplicationContextAware{ private static final long serialVersionUID = 1L; private ApplicationContext applicationContext; //动态调用SessionFactory private SessionFactory getHibernateSessionFactory(String name) { return (SessionFactory) applicationContext.getBean(name); } //实现DynamicSessionFactoryInf 接口的方法 public SessionFactory getHibernateSessionFactory() { return getHibernateSessionFactory(ThreadLocalUtil.getCurrentITAsset() .getSessionFactoryName()); } //以下是实现SessionFactory接口的方法,并对当前的SessionFactory实体进行代理 public Reference getReference() throws NamingException { return getHibernateSessionFactory().getReference(); } public Session openSession() throws HibernateException { return getHibernateSessionFactory().openSession(); } public Session openSession(Interceptor interceptor) throws HibernateException { return getHibernateSessionFactory().openSession(interceptor); } public Session openSession(Connection connection) { return getHibernateSessionFactory().openSession(connection); } public Session openSession(Connection connection, Interceptor interceptor) { return getHibernateSessionFactory().openSession(connection,interceptor); } public Session getCurrentSession() throws HibernateException { return getHibernateSessionFactory().getCurrentSession(); } public StatelessSession openStatelessSession() { return getHibernateSessionFactory().openStatelessSession(); } public StatelessSession openStatelessSession(Connection connection) { return getHibernateSessionFactory().openStatelessSession(connection); } public ClassMetadata getClassMetadata(Class entityClass) { return getHibernateSessionFactory().getClassMetadata(entityClass); } public ClassMetadata getClassMetadata(String entityName) { return getHibernateSessionFactory().getClassMetadata(entityName); } public CollectionMetadata getCollectionMetadata(String roleName) { return getHibernateSessionFactory().getCollectionMetadata(roleName); } public Map getAllClassMetadata() { return getHibernateSessionFactory().getAllClassMetadata(); } public Map getAllCollectionMetadata() { return getHibernateSessionFactory().getAllCollectionMetadata(); } public Statistics getStatistics() { return getHibernateSessionFactory().getStatistics(); } public void close() throws HibernateException { getHibernateSessionFactory().close(); } public boolean isClosed() { return getHibernateSessionFactory().isClosed(); } public Cache getCache() { return getHibernateSessionFactory().getCache(); } public void evict(Class persistentClass) throws HibernateException { getHibernateSessionFactory().evict(persistentClass); } public void evict(Class persistentClass, Serializable id) throws HibernateException { getHibernateSessionFactory().evict(persistentClass, id); } public void evictEntity(String entityName) throws HibernateException { getHibernateSessionFactory().evictEntity(entityName); } public void evictEntity(String entityName, Serializable id) throws HibernateException { getHibernateSessionFactory().evictEntity(entityName, id); } public void evictCollection(String roleName) throws HibernateException { getHibernateSessionFactory().evictCollection(roleName); } public void evictCollection(String roleName, Serializable id) throws HibernateException { getHibernateSessionFactory().evictCollection(roleName, id); } public void evictQueries(String cacheRegion) throws HibernateException { getHibernateSessionFactory().evictQueries(cacheRegion); } public void evictQueries() throws HibernateException { getHibernateSessionFactory().evictQueries(); } public Set getDefinedFilterNames() { return getHibernateSessionFactory().getDefinedFilterNames(); } public FilterDefinition getFilterDefinition(String filterName) throws HibernateException { return getHibernateSessionFactory().getFilterDefinition(filterName); } public boolean containsFetchProfileDefinition(String name) { return getHibernateSessionFactory().containsFetchProfileDefinition(name); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this .applicationContext = applicationContext; } }
4. 配置动态SessionFactory
public class DynamicTransactionManager extends HibernateTransactionManager { private static final long serialVersionUID = 1047039346475978451L; //重写getDataSource方法,实现动态获取 public DataSource getDataSource() { DataSource sfds = SessionFactoryUtils.getDataSource(getSessionFactory()); return sfds; } //重写getSessionFactory方法,实现动态获取SessionFactory public SessionFactory getSessionFactory() { DynamicSessionFactoryInf dynamicSessionFactory = (DynamicSessionFactoryInf) super .getSessionFactory(); SessionFactory hibernateSessionFactory = dynamicSessionFactory .getHibernateSessionFactory(); return hibernateSessionFactory; } //重写afterPropertiesSet,跳过数据源的初始化等操作 public void afterPropertiesSet() { return ; } }
6. 配置dynamicTransactionManager
<bean id="dynamicTransactionManager" class="com.hp.it.qdpadmin.common.DynamicTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
7. 为SessionFactory配置事务切面
<tx:advice id="dynamicTxAdvice" transaction-manager="dynamicTransactionManager"> <tx:attributes> <tx:method name="get*" read-only="true" /> <tx:method name="find*" read-only="true" /> <tx:method name="*" propagation="REQUIRED" rollback-for="Exception" /> </tx:attributes> </tx:advice> <aop:config proxy-target-class="true"> <aop:pointcut id="txPointcut" expression="execution(* com.service.*.*(..))"/> <aop:advisor advice-ref="dynamicTxAdvice" pointcut-ref="txPointcut" /> </aop:config>