Spring+Hibernate实现动态SessionFactory切换
场景:
1)系统有多个数据库
2)且数据库类型也不尽相同
3)现在应用根据某些条件路由到具体的数据库
4)且在spring+hibernate框架下,支持依赖注入
已有实现,spring动态数据源,但无法实现动态SessionFactory,即不通数据库的方言不一样
目标:
在spring动态数据源的基础上,实现动态SessionFactory
1.配置多个数据源和SessionFactory,并给相应SessionFactory配置事务管理:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!-- FOR SqlServer--> <bean id="SqlServer_DataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" /> <property name="url" value="url" /> <property name="username" value="username" /> <property name="password" value="password" /> </bean> <bean id="SqlServer_SessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" p:mappingLocations="classpath:/com/entity/*.hbm.xml"> <property name="dataSource" ref="SqlServer_DataSource" /> <property name="hibernateProperties"> <props> <prop key="hibernate.query.factory_class">org.hibernate.hql.ast.ASTQueryTranslatorFactory</prop> <prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> </props> </property> </bean> <bean id="SqlServer_TransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="SqlServer_SessionFactory"/> </bean> <!-- FOR Oracle --> <bean id="Oracle _DataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="oracle.jdbc.OracleDriver" /> <property name="url" value="jdbc:oracle:thin:@localhost:1521/orcl" /> <property name="username" value="username" /> <property name="password" value="password" /> </bean> <bean id="Oracle_SessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" p:mappingLocations="classpath:/com/entity/*.hbm.xml"> <property name="dataSource" ref="Oracle_DataSource" /> <property name="hibernateProperties"> <props> <prop key="hibernate.query.factory_class">org.hibernate.hql.ast.ASTQueryTranslatorFactory</prop> <prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.format_sql">true</prop> </props> </property> </bean> <bean id="Oracle_TransactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="Oracle_SessionFactory"/> </bean> </beans>
2. 为SessionFactory配置事务切面:
<tx:advice id="SqlServer_TxAdvice" transaction-manager="SqlServer_TransactionManager"> <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> <tx:advice id="Oracle_TxAdvice" transaction-manager="Oracle_TransactionManager"> <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="SqlServer_TxAdvice" pointcut-ref="txPointcut" order="1"/> <aop:advisor advice-ref="Oracle_TxAdvice" pointcut-ref="txPointcut" order="2"/> </aop:config>
3. 配置一个动态的SessionFactory:
<bean id="sessionFactory" class="com.DynamicSessionFactory"/>
4. 定义DynamicSessionFactory实现接口SessionFactory:
public class DynamicSessionFactory implements SessionFactory ,ApplicationContextAware{ private static final long serialVersionUID = 1L; private ApplicationContext applicationContext; private SessionFactory getSessionFactory(String name) { return (SessionFactory) applicationContext.getBean(name); } //根据当前线程的SessionFactoryName获取SessionFactory private SessionFactory getSessionFactory() { return getSessionFactory(ThreadLocalUtil. .getSessionFactoryName()); } public Reference getReference() throws NamingException { return getSessionFactory().getReference(); } public Session openSession() throws HibernateException { return getSessionFactory().openSession(); } public Session openSession(Interceptor interceptor) throws HibernateException { return getSessionFactory().openSession(interceptor); } public Session openSession(Connection connection) { return getSessionFactory().openSession(connection); } public Session openSession(Connection connection, Interceptor interceptor) { return getSessionFactory().openSession(connection,interceptor); } public Session getCurrentSession() throws HibernateException { return getSessionFactory().getCurrentSession(); } public StatelessSession openStatelessSession() { return getSessionFactory().openStatelessSession(); } public StatelessSession openStatelessSession(Connection connection) { return getSessionFactory().openStatelessSession(connection); } public ClassMetadata getClassMetadata(Class entityClass) { return getSessionFactory().getClassMetadata(entityClass); } public ClassMetadata getClassMetadata(String entityName) { return getSessionFactory().getClassMetadata(entityName); } public CollectionMetadata getCollectionMetadata(String roleName) { return getSessionFactory().getCollectionMetadata(roleName); } public Map getAllClassMetadata() { return getSessionFactory().getAllClassMetadata(); } public Map getAllCollectionMetadata() { return getSessionFactory().getAllCollectionMetadata(); } public Statistics getStatistics() { return getSessionFactory().getStatistics(); } public void close() throws HibernateException { getSessionFactory().close(); } public boolean isClosed() { return getSessionFactory().isClosed(); } public Cache getCache() { return getSessionFactory().getCache(); } public void evict(Class persistentClass) throws HibernateException { getSessionFactory().evict(persistentClass); } public void evict(Class persistentClass, Serializable id) throws HibernateException { getSessionFactory().evict(persistentClass, id); } public void evictEntity(String entityName) throws HibernateException { getSessionFactory().evictEntity(entityName); } public void evictEntity(String entityName, Serializable id) throws HibernateException { getSessionFactory().evictEntity(entityName, id); } public void evictCollection(String roleName) throws HibernateException { getSessionFactory().evictCollection(roleName); } public void evictCollection(String roleName, Serializable id) throws HibernateException { getSessionFactory().evictCollection(roleName, id); } public void evictQueries(String cacheRegion) throws HibernateException { getSessionFactory().evictQueries(cacheRegion); } public void evictQueries() throws HibernateException { getSessionFactory().evictQueries(); } public Set getDefinedFilterNames() { return getSessionFactory().getDefinedFilterNames(); } public FilterDefinition getFilterDefinition(String filterName) throws HibernateException { return getSessionFactory().getFilterDefinition(filterName); } public boolean containsFetchProfileDefinition(String name) { return getSessionFactory().containsFetchProfileDefinition(name); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } }
作者:风过无痕-唐
出处:http://www.cnblogs.com/tangyanbo/
本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。 如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步! 再次感谢您耐心的读完本篇文章。欢迎加QQ讨论群
出处:http://www.cnblogs.com/tangyanbo/
本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。 如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步! 再次感谢您耐心的读完本篇文章。欢迎加QQ讨论群