`
fangang
  • 浏览: 876435 次
  • 性别: Icon_minigender_1
  • 来自: 北京
博客专栏
311c4c32-b171-3767-b974-d26acf661fb2
谈谈用例模型的那些事儿
浏览量:38616
767c50c5-189c-3525-a93f-5884d146ee78
一次迭代式开发的研究
浏览量:68792
03a3e133-6080-3bc8-a960-9d915ed9eabc
我们应当怎样做需求分析
浏览量:409820
753f3c56-c831-3add-ba41-b3b70d6d913f
重构,是这样干的
浏览量:91338
社区版块
存档分类
最新评论

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

阅读更多

在我们的项目中遇到这样一个问题:我们的项目需要连接多个数据库,而且不同的客户在每次访问中根据需要会去访问不同的数据库。我们以往在springhibernate框架中总是配置一个数据源,因而sessionFactorydataSource属性总是指向这个数据源并且恒定不变,所有DAO在使用sessionFactory的时候都是通过这个数据源访问数据库。但是现在,由于项目的需要,我们的DAO在访问sessionFactory的时候都不得不在多个数据源中不断切换,问题就出现了:如何让sessionFactory在执行数据持久化的时候,根据客户的需求能够动态切换不同的数据源?我们能不能在spring的框架下通过少量修改得到解决?是否有什么设计模式可以利用呢? 

 

问题的分析

我首先想到在springapplicationContext中配置所有的dataSource。这些dataSource可能是各种不同类型的,比如不同的数据库:OracleSQL ServerMySQL等,也可能是不同的数据源:比如apache 提供的org.apache.commons.dbcp.BasicDataSourcespring提供的org.springframework.jndi.JndiObjectFactoryBean等。然后sessionFactory根据客户的每次请求,将dataSource属性设置成不同的数据源,以到达切换数据源的目的。

 

但是,我很快发现一个问题:当多用户同时并发访问数据库的时候会出现资源争用的问题。这都是“单例模式”惹的祸。众所周知,我们在使用spring框架的时候,在beanFactory中注册的bean基本上都是采用单例模式,即spring在启动的时候,这些bean就装载到内存中,并且每个bean在整个项目中只存在一个对象。正因为只存在一个对象,对象的所有属性,更准确说是实例变量,表现得就如同是个静态变量(实际上“静态”与“单例”往往是非常相似的两个东西,我们常常用“静态”来实现“单例”)。拿我们的问题来说,sessionFactory在整个项目中只有一个对象,它的实例变量dataSource也就只有一个,就如同一个静态变量一般。如果不同的用户都不断地去修改dataSource的值,必然会出现多用户争用一个变量的问题,对系统产生隐患。

 

通过以上的分析,解决多数据源访问问题的关键,就集中在sessionFactory在执行数据持久化的时候,能够通过某段代码去根据客户的需要动态切换数据源,并解决资源争用的问题。

 

问题的解决

  • 采用Decorator设计模式

要解决这个问题,我的思路锁定在了这个dataSource上了。如果sessionFactory指向的dataSource可以根据客户的需求去连接客户所需要的真正的数据源,即提供动态切换数据源的功能,那么问题就解决了。那么我们怎么做呢?去修改那些我们要使用的dataSource源码吗?这显然不是一个好的方案,我们希望我们的修改与原dataSource代码是分离的。根据以上的分析,使用GoF设计模式中的Decorator模式(装饰者模式)应当是我们可以选择的最佳方案。

 

什么是“Decorator模式”?简单点儿说就是当我们需要修改原有的功能,但我们又不愿直接去修改原有的代码时,设计一个Decorator套在原有代码外面。当我们使用Decorator的时候与原类完全一样,当Decorator的某些功能却已经修改为了我们需要修改的功能。Decorator模式的结构如图。

 

 

我们本来需要修改图中所有具体的Component类的一些功能,但却并不是去直接修改它们的代码,而是在它们的外面增加一个DecoratorDecorator与具体的Component类都是继承的AbstractComponent,因此它长得和具体的Component类一样,也就是说我们在使用Decorator的时候就如同在使用ConcreteComponentA或者ConcreteComponentB一样,甚至那些使用ConcreteComponentA或者ConcreteComponentB的客户程序都不知道它们用的类已经改为了Decorator,但是Decorator已经对具体的Component类的部分方法进行了修改,执行这些方法的结果已经不同了。

 

  • 设计MultiDataSource

现在回到我们的问题,我们需要对dataSource的功能进行变更,但又不希望修改dataSource中的任何代码。我这里指的dataSource是所有实现javax.sql.DataSource接口的类,我们常用的包括apache 提供的org.apache.commons.dbcp.BasicDataSourcespring提供的org.springframework.jndi.JndiObjectFactoryBean等,这些类我们不可能修改它们本身,更不可能对它们一个个地修改以实现动态分配数据源的功能,同时,我们又希望使用dataSourcesessionFactory根本就感觉不到这样的变化。Decorator模式就正是解决这个问题的设计模式。

 

首先写一个Decorator类,我取名叫MultiDataSource,通过它来动态切换数据源。同时在配置文件中将sessionFactory的dataSource属性由原来的某个具体的dataSource改为MultiDataSource。如图:

 

 

对比原Decorator模式,AbstractComponent是一个抽象类,但在这里我们可以将这个抽象类用接口来代替,即DataSource接口,而ConcreteComponent就是那些DataSource的实现类,如BasicDataSourceJndiObjectFactoryBean等。MultiDataSource封装了具体的dataSource,并实现了数据源动态切换:

 

 

java 代码
  1. public class MultiDataSource implements DataSource {   
  2.     private DataSource dataSource = null;   
  3. public MultiDataSource(DataSource dataSource){   
  4.         this.dataSource = dataSource;   
  5.     }   
  6.     /* (non-Javadoc)  
  7.      * @see javax.sql.DataSource#getConnection()  
  8.      */  
  9.     public Connection getConnection() throws SQLException {   
  10.         return getDataSource().getConnection();   
  11.     }   
  12.     //其它DataSource接口应当实现的方法   
  13.   
  14.     public DataSource getDataSource(){   
  15.         return this.dataSource;   
  16.         }   
  17.     }   
  18.     public void setDataSource(DataSource dataSource) {   
  19.         this.dataSource = dataSource;   
  20.     }   
  21. }   

 

客户在发出请求的时候,将dataSourceName放到request中,然后把request中的数据源名通过调用new MultiDataSource(dataSource)时可以告诉MultiDataSource客户需要的数据源,就可以实现动态切换数据源了。但细心的朋友会发现这在单例的情况下就是问题的,因为MultiDataSource在系统中只有一个对象,它的实例变量dataSource也只有一个,就如同一个静态变量一般。正因为如此,单例模式让许多设计模式都不得不需要更改,这将在我的《“单例”更改了我们的设计模式》中详细讨论。那么,我们在单例模式下如何设计呢?

 

  • 单例模式下的MultiDataSource

在单例模式下,由于我们在每次调用MultiDataSource的方法的时候,dataSource都可能是不同的,所以我们不能将dataSource放在实例变量dataSource中,最简单的方式就是在方法getDataSource()中增加参数,告诉MultiDataSource我到底调用的是哪个dataSource

 

java 代码
  1. public DataSource getDataSource(String dataSourceName){   
  2.         log.debug("dataSourceName:"+dataSourceName);   
  3.         try{   
  4.             if(dataSourceName==null||dataSourceName.equals("")){   
  5.                 return this.dataSource;   
  6.             }   
  7.             return (DataSource)this.applicationContext.getBean(dataSourceName);   
  8.         }catch(NoSuchBeanDefinitionException ex){   
  9.             throw new DaoException("There is not the dataSource 
  10.         }   
  11.     }   

 

值得一提的是,我需要的数据源已经都在spring的配置文件中注册,dataSourceName就是其对应的id

 

xml 代码
  1. <bean id="dataSource1"  
  2.     class="org.apache.commons.dbcp.BasicDataSource">  
  3.     <property name="driverClassName">  
  4.         <value>oracle.jdbc.driver.OracleDrivervalue>  
  5.     property> 
  6.     ......   
  7. bean>  
  8. <bean id="dataSource2"  
  9.     class="org.apache.commons.dbcp.BasicDataSource">  
  10.     <property name="driverClassName">  
  11.         <value>oracle.jdbc.driver.OracleDrivervalue> 
  12.     property>   
  13.     ......   
  14. bean>   

为了得到springApplicationContextMultiDataSource类必须实现接口org.springframework.context.ApplicationContextAware,并且实现方法:

java 代码
  1. private ApplicationContext applicationContext = null;   
  2. public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {   
  3.         this.applicationContext = applicationContext;   
  4.     }   

 

如此这样,我就可以通过this.applicationContext.getBean(dataSourceName)得到dataSource了。

 

  • 通过线程传递dataSourceName

查看以上设计,MultiDataSource依然无法运行,因为用户在发出请求时,他需要连接什么数据库,其数据源名是放在request中的,要将request中的数据源名传给MultiDataSource,需要经过BUSDAO,也就是说为了把数据源名传给MultiDataSourceBUSDAO的所有方法都要增加dataSourceName的参数,这是我们不愿看到的。写一个类,通过线程的方式跳过BUSDAO直接传递给MultiDataSource是一个不错的设计:

 

java 代码
  1. public class SpObserver {   
  2.     private static ThreadLocal local = new ThreadLocal();   
  3.     public static void putSp(String sp) {   
  4.         local.set(sp);   
  5.     }   
  6.     public static String getSp() {   
  7.         return (String)local.get();   
  8.     }   
  9. }   

 

做一个filter,每次客户发出请求的时候就调用SpObserver.petSp(dataSourceName),将request中的dataSourceName传递给SpObserver对象。最后修改MultiDataSource的方法getDataSource()

 

java 代码
  1. public DataSource getDataSource(){   
  2.         String sp = SpObserver.getSp();   
  3.         return getDataSource(sp);   
  4.     }   

 

完整的MultiDataSource代码在附件中。

 

  • 动态添加数据源

通过以上方案,我们解决了动态分配数据源的问题,但你可能提出疑问:方案中的数据源都是配置在springApplicationContext中,如果我在程序运行过程中动态添加数据源怎么办?这确实是一个问题,而且在我们的项目中也确实遇到。springApplicationContext是在项目启动的时候加载的。加载以后,我们如何动态地加载新的beanApplicationContext中呢?我想到如果用spring自己的方法解决这个问题就好了。所幸的是,在查看spring的源代码后,我找到了这样的代码,编写了DynamicLoadBean类,只要调用loadBean()方法,就可以将某个或某几个配置文件中的bean加载到ApplicationContext中(见附件)。不通过配置文件直接加载对象,在spring的源码中也有,感兴趣的朋友可以自己研究。

 

 

  • spring中配置

在完成了所有这些设计以后,我最后再唠叨一句。我们应当在spring中做如下配置:

 

xml 代码
  1. <bean id="dynamicLoadBean" class="com.htxx.service.dao.DynamicLoadBean">bean>  
  2. <bean id="dataSource" class="com.htxx.service.dao.MultiDataSource">  
  3.         <property name="dataSource">  
  4.             <ref bean="dataSource1" />  
  5.         property>  
  6.     bean>  
  7.     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
  8.         <property name="dataSource">  
  9.             <ref bean="dataSource" />  
  10.         property>  
  11.         ......   
  12.     bean>  

 

其中dataSource属性实际上更准确地说应当是defaultDataSource,即spring启动时以及在客户没有指定数据源时应当指定的默认数据源。

 

该方案的优势

 

以上方案与其它方案相比,它有哪些优势呢?

 

首先,这个方案完全是在spring的框架下解决的,数据源依然配置在spring的配置文件中,sessionFactory依然去配置它的dataSource属性,它甚至都不知道dataSource的改变。唯一不同的是在真正的dataSourcesessionFactory之间增加了一个MultiDataSource

 

其次,实现简单,易于维护。这个方案虽然我说了这么多东西,其实都是分析,真正需要我们写的代码就只有MultiDataSourceSpObserver两个类。MultiDataSource类真正要写的只有getDataSource()getDataSource(sp)两个方法,而SpObserver类更简单了。实现越简单,出错的可能就越小,维护性就越高。

 

最后,这个方案可以使单数据源与多数据源兼容。这个方案完全不影响BUSDAO的编写。如果我们的项目在开始之初是单数据源的情况下开发,随着项目的进行,需要变更为多数据源,则只需要修改spring配置,并少量修改MVC层以便在请求中写入需要的数据源名,变更就完成了。如果我们的项目希望改回单数据源,则只需要简单修改配置文件。这样,为我们的项目将增加更多的弹性。

 

特别说明:实例中的DynamicLoadBean在web环境下运行会出错,需要将类中AbstractApplicationContext改为org.springframework.context.ConfigurableApplicationContext。

 

相关博客:再析在spring框架中解决多数据源的问题

 

  • example.rar (32.1 KB)
  • 描述: 源码及示例
  • 下载次数: 9942
分享到:
评论
45 楼 米饭21 2007-06-08  
看不到图
44 楼 二十一 2007-06-08  
我想知道,lz的这种方案能够保证open session in view的正常使用么?因为osiv模式是在
openSessionInViewFilter时就经确定了使用的数据源,而且以后的数据库操作都会保证使用同一数据连接,所以LZ的这种方法似乎对osiv模式没多大意义
43 楼 fangang 2007-05-29  
我虽然没有亲自测试,但我认为jdbcTemplate是可以的,因为jdbcTemplate接受的是dataSource。只要jdbcTemplate接受dataSource就可以使用MultiDataSource,因为这就是MultiDataSource的优势,你可以再试试。
42 楼 xirilianren2844 2007-05-29  
fangang 写道
xirilianren2844 写道
  我们现在也正好遇到了多数据源的项目,看了这篇文章,真可谓一场及时雨呀,我想高人fanggang在看到自己的劳动帮助了别人,内心应是无比欣慰和愉快的,在此仅向fanggang致以谢意!并祝工作顺利,全家快乐!
  用您的方法后,我现在已经能实现了多数据库查询,而且也保证了事务,一切都很正常,但是有一点现在让我很着急,而且让我束手无策.因为我们在对数据库的操作时也用到了JdbcTemplate,目前在您的文章介绍中去只用了HibernateTemplate对数据库进行操作,我昨天试着把MultidataSource注入到jdbcTemplate里面,并把jdbcTemplate注入到我使用的dao里面,此时我在使用他的时候就出现了问题,它抛出这个异常:java.lang.NoSuchFieldError: EMPTY_ITERATOR,我到api上查了一下,他解释的大意思是我在试图改变一个对象时引发了此异常.请fanggang同志给以点化,当思感恩不尽!我的Msn是:xirilianren2844@hotmail.com.

非常抱歉一直在出差中,今天才看到你的信息,是的,我的方案能带给你帮助我感到非常高兴。关于你的问题,我初步判断是你在进行数据源切换的时候,目的数据库的表中没有你所操作的字段,不知是不是这个原因,你查一查。我的MSN是:fan_gang2004@hotmail.com,不过我在出差中,近期可能不会在线上。
有那个字段,我是在还没有切换数据库的时候,就进行了相应的数据库查询,然后就报那个异常了.是不是jdbcTemplate不能用动态数据源的方式去得到数据库的连接?
41 楼 fangang 2007-05-29  
xirilianren2844 写道
  我们现在也正好遇到了多数据源的项目,看了这篇文章,真可谓一场及时雨呀,我想高人fanggang在看到自己的劳动帮助了别人,内心应是无比欣慰和愉快的,在此仅向fanggang致以谢意!并祝工作顺利,全家快乐!
  用您的方法后,我现在已经能实现了多数据库查询,而且也保证了事务,一切都很正常,但是有一点现在让我很着急,而且让我束手无策.因为我们在对数据库的操作时也用到了JdbcTemplate,目前在您的文章介绍中去只用了HibernateTemplate对数据库进行操作,我昨天试着把MultidataSource注入到jdbcTemplate里面,并把jdbcTemplate注入到我使用的dao里面,此时我在使用他的时候就出现了问题,它抛出这个异常:java.lang.NoSuchFieldError: EMPTY_ITERATOR,我到api上查了一下,他解释的大意思是我在试图改变一个对象时引发了此异常.请fanggang同志给以点化,当思感恩不尽!我的Msn是:xirilianren2844@hotmail.com.

非常抱歉一直在出差中,今天才看到你的信息,是的,我的方案能带给你帮助我感到非常高兴。关于你的问题,我初步判断是你在进行数据源切换的时候,目的数据库的表中没有你所操作的字段,不知是不是这个原因,你查一查。我的MSN是:fan_gang2004@hotmail.com,不过我在出差中,近期可能不会在线上。
40 楼 xirilianren2844 2007-05-24  
  我们现在也正好遇到了多数据源的项目,看了这篇文章,真可谓一场及时雨呀,我想高人fanggang在看到自己的劳动帮助了别人,内心应是无比欣慰和愉快的,在此仅向fanggang致以谢意!并祝工作顺利,全家快乐!
  用您的方法后,我现在已经能实现了多数据库查询,而且也保证了事务,一切都很正常,但是有一点现在让我很着急,而且让我束手无策.因为我们在对数据库的操作时也用到了JdbcTemplate,目前在您的文章介绍中去只用了HibernateTemplate对数据库进行操作,我昨天试着把MultidataSource注入到jdbcTemplate里面,并把jdbcTemplate注入到我使用的dao里面,此时我在使用他的时候就出现了问题,它抛出这个异常:java.lang.NoSuchFieldError: EMPTY_ITERATOR,我到api上查了一下,他解释的大意思是我在试图改变一个对象时引发了此异常.请fanggang同志给以点化,当思感恩不尽!我的Msn是:xirilianren2844@hotmail.com.
                                  
 
39 楼 fangang 2007-05-22  
呵呵,stephen朋友似乎没有仔细读这篇文章,我提出的方案倡导的就是不修改任何hibernate和spring框架本身,对客户透明地解决该问题。
38 楼 atianchen 2007-05-17  
呵呵,不过照我的方法做的话,虽然改了很多类,但是可以解决跨库操作的事务问题,而不采用jtaTransactionMananger以及配置JNDI,这个事务我已做测试,确实是可以的。详细操作我会写文叙述
37 楼 stephen 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 的地方也能够得到很大的简化,并不复杂。

36 楼 fangang 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模式是我这个方案的核心,而具体如何实现当然应当根据各个项目自己的需求进行设计。
35 楼 fangang 2007-05-15  
理解atianchen ,我们每个项目的具体情况都不一样,也许我的项目可以不用多个sessionFactory,但你的项目用多个却更合适。
同是重庆人,相互学习。
34 楼 atianchen 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事务处理机制上扩展实现多库事务控制就轻松多了
33 楼 jasspier 2007-05-15  
引用
fangang 写道

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

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

我替你总结吧,你的方案仅适合用户事先(比如登陆时)选定某个数据库的情况.而对于跨数据库的事务没有什么办法.这是Spring声明式的事务特性所决定的.
你的方案还有一个大问题,就是当遇到后台驻守程序访问数据库时,由于没有事先指定数据库而无法正常运行.
32 楼 fangang 2007-05-15  
jasspier 写道
你的方法里,如果要对客户端程序透明,那么无论你用JtaTransactionManager还是HibernateTransactionManager,整个操作只取一次dataSource,因此你连跨数据库都很难做到.别说什么保证事务了.
你最好先搞清楚你所提供的程序所适用的范围,定义好应用边界,再做讨论,否则你对spring的坚信是盲目的.

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

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


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

你的方法里,如果要对客户端程序透明,那么无论你用JtaTransactionManager还是HibernateTransactionManager,整个操作只取一次dataSource,因此你连跨数据库都很难做到.别说什么保证事务了.
你最好先搞清楚你所提供的程序所适用的范围,定义好应用边界,再做讨论,否则你对spring的坚信是盲目的.
30 楼 spiritfrog 2007-05-15  
fangang 写道
jasspier 写道
你这种做法,一次只能使用一只数据源,如果同时要对两个数据源做操作,你如何保证事务?

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

就是说也不必一定要用JtaTransactionManager咯?HibernateTransactionManager也可以?
29 楼 抛出异常的爱 2007-05-15  
当然可以。。。
spring是个锤子
28 楼 fangang 2007-05-15  
atianchen的解决方案也是一个不错的思路,可以看到,我们的方案都有一个共通的地方,就是运用线程直接从request中获得信息。但是,atianchen使用了多个sessionFactory,可实际上这多个sessionFactory在差别上只有dataSource,但却要装载多份值对象集,这恐怕在装载时间和资源耗费上都是一种不必要的浪费。atianchen可以再优化一下你的方案。
27 楼 fangang 2007-05-15  
这真的是一个很有意思的问题,在我的项目中没有遇到,可以搭建一个环境实际测试一下,不过我坚信spring是可以解决的。
26 楼 fangang 2007-05-15  
spring通过org.springframework.transaction.jta.JtaTransactionManager可以运用Jta进行跨数据库的事务管理

相关推荐

    spring+hibernate解决多数据源问题3.pdf

    在多数据源的配置中,需要有一种机制来实现数据源的动态切换。这通常涉及到根据业务逻辑条件选择不同的数据源来执行数据库操作。在应用程序运行过程中,可以根据需要动态地切换数据源,这可能涉及到会话工厂中数据库...

    spring框架多数据源切换问题的解决

    首先,这个方案完全是在spring的框架下解决的,数据源依然配置在spring的配置文件中,sessionFactory依然去配置它的dataSource属性,它甚至都不知道dataSource的改变。 其次,实现简单,易于维护。这个方案虽然我说...

    Springcloud 多数库 多数据源整合,查询动态切换数据库

    2. **动态切换数据源**:在Spring框架中,我们可以利用AOP(面向切面编程)和ThreadLocal来实现数据源的动态切换。创建一个自定义的数据源切换注解,比如`@SwitchDataSource`,并在需要切换数据源的方法上使用。通过...

    SSM(Spring+SpringMVC+MyBatis)多数据源配置框架

    在多数据源配置中,Spring能够帮助管理不同的数据源,通过配置bean来切换和控制数据源的使用。 **SpringMVC** 是Spring框架的一部分,专为Web开发设计。它简化了模型-视图-控制器(Model-View-Controller,MVC)的...

    spring boot 2多数据源,里面有hibernate和mybatis的多数据源代码

    在多数据源的场景下,Hibernate提供了灵活的数据源配置,可以在同一个应用中管理多个数据库连接。这通常通过定义不同的SessionFactory配置和DataSource实例来实现。 **MyBatis** 则是一个轻量级的ORM框架,它比...

    spring整合mybatis多数据源

    5. **事务管理**:在多数据源环境下,事务管理也需要特别注意。Spring的PlatformTransactionManager应配置为DataSourceTransactionManager,并且需要确保它知道如何处理多个数据源。在事务开始时,事务管理器会根据...

    spring3+springmvc+jpa+hibernate多数据源

    在多数据源场景下,Hibernate可以配置为连接不同的数据库,使得应用可以根据业务需求灵活切换数据源。 **多数据源** 是指在一个应用中管理多个独立的数据库连接。在本项目中,数据源被配置为Hibernate和Datastore,...

    java spring 多数据源

    在Java Spring框架中,多数据源的实现是一个重要的特性,特别是在大型企业级应用中,它允许应用程序连接到多个数据库,从而实现数据隔离、负载均衡或读写分离等高级功能。本教程将深入探讨如何在Spring中配置和管理...

    spring多数据源

    Spring多数据源允许我们在一个应用中同时管理多个数据库连接,通过切换不同的数据源来满足不同业务的需求。实现这一功能的关键在于Spring的DataSourceTransactionManager和AbstractRoutingDataSource。 1. **...

    Spring动态切换多数据源Demo

    在Spring框架中,多数据源的支持使得应用可以同时连接并操作多个不同的数据库,这在分布式系统、微服务架构或者需要处理多种数据类型的场景下非常有用。"Spring动态切换多数据源Demo"是一个示例项目,它展示了如何在...

    Spring+Hibernate多数据源

    在多数据源环境中,每个数据源需要一个单独的SessionFactory。我们可以为每个数据源创建一个SessionFactory配置,并指定相应的DataSource,实体扫描路径,以及其他的Hibernate配置参数。 在"压缩包子文件的文件名称...

    基于Spring多数据源实例

    本文将深入探讨如何在一个基于Spring框架的应用中实现多数据源的动态切换,以"基于SSI+Oracle架构的多数据源动态切换实例"为例进行详细讲解。 首先,我们需要理解什么是多数据源。多数据源是指在一个应用中同时连接...

    mybatis spring 多数据源

    标签中的"源码"可能指的是理解MyBatis和Spring框架内部如何处理多数据源的关键代码,这有助于我们更深入地定制和优化解决方案。"工具"可能是指像Druid、HikariCP这样的数据库连接池,它们在多数据源配置中起着至关...

    mybatis+spring实现动态切换数据源

    在本项目中,我们将探讨如何利用MyBatis与Spring框架实现动态切换数据源的功能。首先,我们需要理解MyBatis和Spring的基本概念以及它们如何协同工作。 MyBatis是一个优秀的持久层框架,它简化了Java与数据库之间的...

    Spring+SpringMVC+Mybatis动态链接多数据源

    在多数据源场景下,Mybatis可以通过SqlSessionFactoryBuilder创建多个SqlSessionFactory实例,每个实例对应一个数据源,从而实现数据源的隔离。 实现多数据源通常有以下步骤: 1. **配置数据源**:首先,你需要...

    spring 动态多数据源配置代码

    - 注意事务管理的配置,确保在多数据源环境下事务的一致性。 8. **应用场景**: - 分布式系统中,不同的服务可能需要连接不同的数据库。 - 高并发场景下,可以通过数据源分片来分散压力。 - 读写分离,主库负责...

    springAop多数据源

    - 在多数据源和AOP的测试中,我们需要模拟不同的数据源环境,确保在各种情况下,代码都能正确地选择并使用正确的数据源。 - 可以使用Spring的@Test注解和@MockBean来创建测试环境,模拟数据源切换,并验证AOP是否...

Global site tag (gtag.js) - Google Analytics