论坛首页 Java企业应用论坛

如何在spring框架中解决多数据源的问题

浏览 109936 次
精华帖 (8) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-05-15  
fangang 写道
jasspier 写道
你这种做法,一次只能使用一只数据源,如果同时要对两个数据源做操作,你如何保证事务?

运用spring的事物处理机制是没有问题的

就是说也不必一定要用JtaTransactionManager咯?HibernateTransactionManager也可以?
0 请登录后投票
   发表时间:2007-05-15  
引用
fangang 写道

运用spring的事物处理机制是没有问题的.
在我的项目中没有遇到,可以搭建一个环境实际测试一下,不过我坚信spring是可以解决的。


你到底试没试过?你说可以就可以?坚信有什么实际价值吗?

你的方法里,如果要对客户端程序透明,那么无论你用JtaTransactionManager还是HibernateTransactionManager,整个操作只取一次dataSource,因此你连跨数据库都很难做到.别说什么保证事务了.
你最好先搞清楚你所提供的程序所适用的范围,定义好应用边界,再做讨论,否则你对spring的坚信是盲目的.
0 请登录后投票
   发表时间:2007-05-15  
jasspier 写道
你的方法里,如果要对客户端程序透明,那么无论你用JtaTransactionManager还是HibernateTransactionManager,整个操作只取一次dataSource,因此你连跨数据库都很难做到.别说什么保证事务了.
你最好先搞清楚你所提供的程序所适用的范围,定义好应用边界,再做讨论,否则你对spring的坚信是盲目的.

在我们的项目中虽然需要连接多个数据库,但是每次操作仅仅对一个数据库中进行,因此不存在跨数据库事务管理的问题。
但是,在我的应用中没有跨数据库事务管理的需求,不等于我的方案不能解决这个问题。我现在正在准备搭建这样一个软件环境,通过实际的测试解决这个问题。我们做技术的,任何不经过实际地测试而张口胡说都是不严谨的,是吧?
0 请登录后投票
   发表时间:2007-05-15  
引用
fangang 写道

任何不经过实际地测试而张口胡说都是不严谨的,是吧?

你没有经过测试,怎么以已度人的认为我也不没有呢?
引用的正是我想对你说的.连环境都还没有,就信誓旦旦的"坚信"起来.

我替你总结吧,你的方案仅适合用户事先(比如登陆时)选定某个数据库的情况.而对于跨数据库的事务没有什么办法.这是Spring声明式的事务特性所决定的.
你的方案还有一个大问题,就是当遇到后台驻守程序访问数据库时,由于没有事先指定数据库而无法正常运行.
0 请登录后投票
   发表时间:2007-05-15  
fangang 写道
atianchen的解决方案也是一个不错的思路,可以看到,我们的方案都有一个共通的地方,就是运用线程直接从request中获得信息。但是,atianchen使用了多个sessionFactory,可实际上这多个sessionFactory在差别上只有dataSource,但却要装载多份值对象集,这恐怕在装载时间和资源耗费上都是一种不必要的浪费。atianchen可以再优化一下你的方案。


最开始我也想过只有一个sessionFactory的实现方式,但是因为系统中经常涉及跨库操作,单一的sessionFactory无论是在调用还是在事务处理上都不方便实现,所以才改成同时并存多个SessionFactory,这样更好进行扩展
spring在处理Hibernate事务方面,TransactionSynchronizationManager的资源注册以及SessionHolder等一系列处理都是以SessionFactory做为Key和源头的,如果要用一个SessionFactory然后多datasource的方式,势必要修改spring对Hibernate的事务支持,事实上,做这样的修改是非常痛苦的过程,我曾经尝试这样做,结果就一个SessionFactoryUtils.java的修改就引起一系列连锁反应,改不甚改,只有放弃
既然sessionFactory是spring事务处理的源头,那么多sessionFactory共存,然后在spring事务处理机制上扩展实现多库事务控制就轻松多了
0 请登录后投票
   发表时间:2007-05-15  
理解atianchen ,我们每个项目的具体情况都不一样,也许我的项目可以不用多个sessionFactory,但你的项目用多个却更合适。
同是重庆人,相互学习。
0 请登录后投票
   发表时间:2007-05-16  
仔细思考我前面提到的方案,由于使用一个sessionFactory和多个dataSource,它实际上并不是适用于所有的多数据源的应用,而是适用于那些多数据库但数据结构一致的应用。因为他只有一个sessionFactory,这个sessionFactory中的值对象应当存在于其所有数据源对应的数据库中。如果多数据源对应的数据库结构不一致怎么办呢?就是使用多个sessionFactory,将Decorator放到sessionFactory前(结构如图)。

然而,我的方案与其它的方案差别在哪里呢?很多朋友在提成他们的方案的时候提到建立一个工厂。诚然,不论是多个dataSource还是多个sessionFactory,建立一个工厂都是一个最佳的方案,但是我们应当注意到一个细节,在我们的系统中已经存在了一个工厂,那就是spring的beanFactory。既然系统中已经存在一个工厂,我们唯一需要做的事情就是编写如何获取工厂中产品的代码,就是如何获得我们需要的dataSource或sessionFactory的业务逻辑,这就是我设计的Decorator所执行的功能。当然,Decorator的分配机制朋友们可以根据自己的业务需要进行改写。
实现同样一个业务功能,如果实现越简单,实现的代码越少,维护代码的成本就越低,执行效率和可移植性就越高。结合我们现在的问题,如果我们写自己的工厂,我们当然需要编写维护工厂的代码,何不利用一个已有的工厂呢?用beanFactory,所有的工厂维护都是spring完成,我们只需要决定我们怎样得到我们需要的dataSource或sessionFactory。同时,我利用了Decorator模式对客户程序透明的特点,在客户程序毫不知情的情况下解决了多数据源动态切换的问题。总之,利用beanFactory和运用Decorator模式是我这个方案的核心,而具体如何实现当然应当根据各个项目自己的需求进行设计。
0 请登录后投票
   发表时间:2007-05-17  
atianchen 写道

当一个请求进来时候,我写了一个Filter会根据request请求信息设置当前的sessionFactory

然后就是重写,需要重写spring关于Hibernate3支持的四个类
HibernateAccessor,HibernateDaoSupport,HibernateTemplate,HibernateTransactionManager
其实主要是修改HibernateAccessor和HibernateTransactionManager的sessionFactory获取方式,由于HibernateDaoSupport->HibernateTemplate->HibernateAccessor,所以重写HibernateAccessor就要重写HibernateDaoSupport和HibernateTemplate


这种方式需要修改 spring,改很多的 spring 类。有一种类似,但是不需修改 spring:
spring 多数据源解决方案

多数据源问题可以打个比喻:假设有个工厂原来可以生产汽车,现在也想这个工厂可以生产火车。
在这个时候,有两个解决办法:
第一种是改造这个工厂的生产设备,使得一个工厂就可以同时生产汽车和火车。
第二种是新建一个工厂,这个工厂专门生产火车。原来的工厂保持不变。

LZ 和 atianchen 用的是第一种方法。还是用一个 BeanFactory ,然后里面声明多个的 DataSource 。用这种方法就需要修改 spring 相关的类。

spring 多数据源解决方案
这里用的就是第二种方法,直接使用多个 BeanFactory ,每个 BeanFactory 使用的 DataSource 不同。使用这种方法,不需修改 spring 的类,而是需要修改上层调用 BeanFactory 的地方。

两种方法的差异在于:
第一种方法使用隐式的参数传递(ThreadLocal,或者SessionContext),希望对上层调用者隐藏多数据源的事实;把多数据源的功能封装在了 BeanFactory 内部。
第二种方法是直接曝露接口给上层调用者,由调用者决定怎么使用。
如果从灵活性角度来说,第二种会更好。因为调用者可以直接通过 Registry.getBeanFacrtory(xxx).getBean(yyy) 来获得相应的 bean 。对于上面有人提到一次请求中需要用到两个 DataSource 的问题,也可以解决。

由于有 servlet 的 filter 机制,或者 webwork 的 interceptor 机制,所以修改上层调用 BeanFactory 的地方也能够得到很大的简化,并不复杂。

0 请登录后投票
   发表时间:2007-05-17  
呵呵,不过照我的方法做的话,虽然改了很多类,但是可以解决跨库操作的事务问题,而不采用jtaTransactionMananger以及配置JNDI,这个事务我已做测试,确实是可以的。详细操作我会写文叙述
0 请登录后投票
   发表时间:2007-05-22  
呵呵,stephen朋友似乎没有仔细读这篇文章,我提出的方案倡导的就是不修改任何hibernate和spring框架本身,对客户透明地解决该问题。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics