场景:

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;
} }

Spring+Hibernate实现动态SessionFactory切换的更多相关文章

  1. Spring+Hibernate实现动态SessionFactory切换(改进版)

    前面写了一篇关于动态切换Hibernate SessionFactory的文章 发现存在一些问题: 需要配置多个HibernateTransactionManager和多个Spring 切面 这样带来 ...

  2. Spring(AbstractRoutingDataSource)实现动态数据源切换--转载

    原始出处:http://linhongyu.blog.51cto.com/6373370/1615895 一.前言 近期一项目A需实现数据同步到另一项目B数据库中,在不改变B项目的情况下,只好选择项目 ...

  3. Spring(AbstractRoutingDataSource)实现动态数据源切换

    转自: http://blog.51cto.com/linhongyu/1615895 一.前言 近期一项目A需实现数据同步到另一项目B数据库中,在不改变B项目的情况下,只好选择项目A中切换数据源,直 ...

  4. spring hibernate实现动态替换表名(分表)

    1.概述 其实最简单的办法就是使用原生sql,如 session.createSQLQuery("sql"),或者使用jdbcTemplate.但是项目中已经使用了hql的方式查询 ...

  5. dubbo服务+Spring事务+AOP动态数据源切换 出错

    1:问题描述,以及分析 项目用了spring数据源动态切换,服务用的是dubbo.在运行一段时间后程序异常,更新操作没有切换到主库上. 这个问题在先调用读操作后再调用写操作会出现. 经日志分析原因: ...

  6. spring AbstractRoutingDataSource实现动态数据源切换

    使用Spring 提供的 AbstractRoutingDataSource 实现 创建 AbstractRoutingDataSource 实现类,负责保存所有数据源与切换数据源策略:public ...

  7. Spring 实现动态数据源切换--转载 (AbstractRoutingDataSource)的使用

    [参考]Spring(AbstractRoutingDataSource)实现动态数据源切换--转载 [参考] 利用Spring的AbstractRoutingDataSource解决多数据源的问题 ...

  8. 30个类手写Spring核心原理之动态数据源切换(8)

    本文节选自<Spring 5核心原理> 阅读本文之前,请先阅读以下内容: 30个类手写Spring核心原理之自定义ORM(上)(6) 30个类手写Spring核心原理之自定义ORM(下)( ...

  9. Spring整合Hibernate 一 - 注入SessionFactory

    Spring3 整合 Hibernate4 - 注入SessionFactory 版本: spring-framework-3.2.4.RELEASE hibernate-release-4.2.5. ...

随机推荐

  1. 常用工具说明--Java的常用工具

    1.Eclipse.IntelliJ IDEA Eclipse是IDE领域的瑞士军刀,有着大量定制的接口和无数的插件.它无处不在,后面本文将推荐的其他所有工具都提供Eclipse插件. Eclipse ...

  2. Shell脚本编写5-----Shell 基本运算符

    算术运算符 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用.expr 是一款表达式计算工具,使用它能完成表达式的求值操作.例如: 两个数相加 ...

  3. oracle数据同步

    随着各行业信息化水平的不断提升,各种各样的信息管理系统都被广泛使用,各系统间数据完全独立,形成了大量的信息孤岛.出于管理及决策方面的需求,实现各平台的数据同步是一个很迫切的需求,TreeSoft数据库 ...

  4. 【java基础】从反射开始(Reflection)

    Java学习笔记 https://github.com/SnailDev/java-learning 和我一起启程... 反射(Reflection) 定义 在运行状态中, 对于任意的一个类,都能够知 ...

  5. git常用命令和场景

    总结: git init //初始化本地git环境 git clone XXX//克隆一份代码到本地仓库 git pull //把远程库的代码更新到工作台 git pull --rebase orig ...

  6. Exam E05-001 Information Storage and Management Version 3 Exam

    Emc 考试 e05-001信息存储和管理版本3考试 [总问题:171] 哪种 emc 产品提供软件定义的存储基础架构的自动监视和报告? A. viprSrmB. 斯纳普内C. 阿瓦马尔D. 快速副总 ...

  7. 在vue中子组件修改props引发的对js深拷贝和浅拷贝的思考

    不管是react还是vue,父级组件与子组件的通信都是通过props来实现的,在vue中父组件的props遵循的是单向数据流,用官方的话说就是,父级的props的更新会向下流动到子组件中,反之则不行. ...

  8. BZOJ4337: BJOI2015 树的同构(hash 树同构)

    题意 题目链接 Sol 树的同构问题,直接拿hash判一下,具体流程大概是这样的: 首先转化为有根树,预处理出第\(i\)棵树以\(j\)为根时的hash值. 那么两个树同构当且仅当把两棵树的hash ...

  9. css中单位em和rem的区别

    在css中单位长度用的最多的是px.em.rem,这三个的区别是: px是固定的像素,一旦设置了就无法因为适应页面大小而改变. em和rem相对于px更具有灵活性,他们是相对长度单位,意思是长度不是定 ...

  10. JavaSE (二)

    this关键字 当一个对象创建后,Java虚拟机(JVM)就会给这个对象分配一个引用自身的指针,这个指针的名字就是 this. 用法:对当前对象的默认引用 调用自己的的构造方法. 用在构造方法内部,区 ...