前面写了一篇关于动态切换Hibernate SessionFactory的文章

发现存在一些问题:
需要配置多个HibernateTransactionManager和多个Spring 切面
这样带来两个问题
1. 程序效率降低,因为Spring进行多次Advice的拦截
2. 如果其中一个SessionFactory连接出现问题,会导致整个系统无法工作
今天研究出一种新的方法来解决此类问题
1. 数据源及Hibernate 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> <!-- 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> </beans>

2. 定义扩展接口DynamicSessionFactoryInf继承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

<bean id="sessionFactory" class="com.hp.it.qdpadmin.common.DynamicSessionFactory"/>

5. 定义DynamicTransactionManager继承HibernateTransactionManager

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>

Spring+Hibernate实现动态SessionFactory切换(改进版)的更多相关文章

  1. Spring+Hibernate实现动态SessionFactory切换

    场景: 1)系统有多个数据库 2)且数据库类型也不尽相同 3)现在应用根据某些条件路由到具体的数据库 4)且在spring+hibernate框架下,支持依赖注入 已有实现,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. MySql实现分页查询的SQL,mysql实现分页查询的sql语句 (转)

    http://blog.csdn.net/sxdtzhaoxinguo/article/details/51481430 摘要:MySQL数据库实现分页查询的SQL语句写法! 一:分页需求: 客户端通 ...

  2. MySQL学习笔记(五)并发时经典常见的死锁原因及解决方法

    MySQL都有什么锁? MySQL有三种锁的级别:页级.表级.行级. 表级锁:开销小,加锁快:不会出现死锁:锁定粒度大,发生锁冲突的概率最高,并发度最低. 行级锁:开销大,加锁慢:会出现死锁:锁定粒度 ...

  3. 第一节:从面向对象思想(oo)开发、接口、抽象类以及二者比较

    一. 面向对象思想 1. 面向过程(OP)和面向对象(OO)的区别: (1):面向过程就是排着用最简单的代码一步一步写下去,没有封装,当业务复杂的时候,改动就很麻烦了 (2):面向对象将复杂的业务分离 ...

  4. sql server 2008怎样导入mdf,ldf文件,怎样解决导入mdf,ldf文件时出现附加数据库错误的问题

    废话不多说,直入主题吧. 1:打开sql server 2008,右键数据库-->附加 2:这时出现这个界面点击添加 3:打开数据库实例的安装目录,打开DATA文件夹;(如我的实例目录地址为:D ...

  5. PYthon3:简单几步实现冒泡排序

    1.概念理解: 冒泡排序:可以简单的理解为是列表中相近的元素,两两比较,小的在前面.最多需要len()-1次排序. 2.例子:a=[11,7,4,56,35,0] 3.代码实现: 4.输出结果: 第1 ...

  6. 51nod--1183 编辑距离(动态规划)

    题目: 1183 编辑距离 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指 ...

  7. Flask开发微电影网站(七)

    1.后台管理之电影管理 1.1 定义电影表单 在app的admin目录的forms.py文件中,定义电影表单 # 电影表单 class MovieForm(FlaskForm): title = St ...

  8. Python-数据类型之列表

    列表和元祖都属于序列类型,该序列内可以包含任意数据类型,且数据存储是有序的,索引从0到1 一:列表概述 1.1  如何定义一个列表 中括号,已逗号为分割符,可以放任意的数据类型,甚至是对象. li = ...

  9. python数据类型一:字符串

    Python 字符串 字符串是 Python 中最常用的数据类型.我们可以使用引号('或")来创建字符串. 创建字符串很简单,只要为变量分配一个值即可.例如: var1 = 'Hello W ...

  10. const 成员函数

    我们知道,在成员函数中,如果没有修改成员变量,应该给成员函数加上 const 修饰符,例如 #include <iostream> using namespace std; class F ...