`
aijuans
  • 浏览: 1566023 次
社区版块
存档分类
最新评论

再析在spring框架中解决多数据源的问题

阅读更多

在前面我写了《如何在 spring 框架中解决多数据源的问题 》,通过设计模式中的 Decorator 模式在 spring 框架中解决多数据源的问题,得到了许多网友的关注。在与网友探讨该问题的过程中,我发现我的方案并不完善,它只解决了一部分问题。

总结多数据源的问题,其实它需要分为以下三种情况:各个数据源的数据结构不同、各个数据源的数据结构相同、各个数据源的数据结构部分相同又有部分不同。对于第二种情况,各个数据源的数据结构相同,我们使用一个 sessionFactory ,而在 sessionFactory 中通过 MultiDataSource 来动态切换数据源,应当是一个不错的方案,既解决了多个 sessionFactory 对相同的值对象重复装载对内存的浪费,又使数据源的切换对客户程序透明,简化了代码的实现和对客户程序的影响。但是,对于第一种情况,各个数据源的数据结构不同,运用这样的方案存在潜在风险。

对于各个数据源的数据结构不同的情况,使用一个 sessionFactory 而在这个 sessionFactory 中动态切换数据源,可能造成数据访问的张冠李戴。譬如,数据源 A 有表 T 而数据源 B 没有,可能造成客户程序在访问表 T 的时候却尝试去连接数据源 B ,因为客户程序访问哪个数据源是在程序运行期间由客户程序决定的,因此这样的错误是很难发现的。也许客户程序的一个不经意的错误就可能造成错误。解决这个问题的方法有两个:一是严格要求客户程序不要写错,这当然是可以做到的,但作为框架设计者,另一个解决方法是在框架中就避免出现这样的情况。因此我祭出了 MultiSessionFactory 的方案来解决各个数据源的数据结构不同的多数据源问题。

问题的分析

MultiDataSource 的方案一样, MultiSessionFactory 同样是在 spring 框架下调用 ApplicationContext getBean() 方法而不会另外创建 beanFacoty ,也同样使用 Decorator 模式来处理切换的问题。 MultiSessionFactory 的对象关系如图:

 

在该方案中, SessionFactory 就是 Hibernate org.hibernate.SessionFactory 接口, Decorator 就是 MultiSessionFactory SessionFactory1 SessionFactory2 往往是 spring org.springframework.orm.hibernate3.LocalSessionFactoryBean 。细心的朋友可能会注意,实际上 LocalSessionFactoryBean 并不是 SessionFactory 的实现,这个方案是否有问题呢?这个问题其实也一直困扰了我好久,最后我发现,我们通过 ApplicationContext getBean() 得到一个 LocalSessionFactoryBean 的时候其实并不是真正地得到了它,而是得到了一个 SessionFactory ,因为 spring LocalSessionFactoryBean 重写了 getObject() ,使其返回的是 SessionFactory 。一个简单的明证就是, HibernateDaoSupport sessionFactory 属性的类型是 SessionFactory ,而我们在 spring 配置的时候注入的却是 LocalSessionFactoryBean

方案的实现

在整个这个方案中,我们需要实现的只有 MultiSessionFactory 类和我们可爱的 Spserver ,总共就两个类,然后呢就是一些 spring 的配置,就完成了。

MultiSessionFactory 实现了 SessionFactory ,同时为了得到 AplicationContext 而实现了 ApplicationContextAware MultiSessionFactory 的代码如下:

java 代码
  1. public   class  MultiSessionFactory  implements  SessionFactory, ApplicationContextAware {   
  2.      private   static   final   long  serialVersionUID = 2064557324203496378L;   
  3.      private   static   final  Log log = LogFactory.getLog(MultiSessionFactory. class );   
  4.      private  ApplicationContext applicationContext =  null ;   
  5.      private  SessionFactory sessionFactory =  null ;   
  6.      public  ApplicationContext getApplicationContext() {   
  7.          return  applicationContext;   
  8.     }   
  9.      public   void  setApplicationContext(ApplicationContext applicationContext) {   
  10.         this .applicationContext = applicationContext;   
  11.     }   
  12.      public  SessionFactory getSessionFactory(String sessionFactoryName) {   
  13.        log.debug( "sessionFactoryName:" +sessionFactoryName);   
  14.         try {   
  15.             if (sessionFactoryName== null ||sessionFactoryName.equals( "" )){   
  16.                return  sessionFactory;   
  17.            }   
  18.             return  (SessionFactory) this .getApplicationContext().getBean(sessionFactoryName);   
  19.        } catch (NoSuchBeanDefinitionException ex){   
  20.             throw   new  DaoException( "There is not the sessionFactory 
  21.        }   
  22.     }   
  23.   
  24.      public  SessionFactory getSessionFactory() {   
  25.        String sessionFactoryName = SpObserver.getSp();   
  26.         return  getSessionFactory(sessionFactoryName);   
  27.     }   
  28.   
  29.      public   void  setSessionFactory(SessionFactory sessionFactory) {   
  30.         this .sessionFactory = sessionFactory;   
  31.     }   
  32.   
  33.      // SessionFactory接口需要实现的方法    
  34.   
  35. ......   
  36.   
  37. }  

MultiSessionFactory的完整代码见我提供的附件。 setSessionFactory() 实际上是设定的默认 sessionFactory ,它在 spring 装载的时候调用,其对应的数据源应当是主数据源,即项目初始化中需要读取初始化数据的数据源。在任何多数据源项目中,都应当有一个存放初始化数据、系统维护数据、用户权限数据的数据源,这就是主数据源。因此 MultiSessionFactory 的配置应当这样写:

xml 代码
  1. < bean   id = "sessionFactory"   class = "com.htxx.service.dao.MultiSessionFactory" >   
  2.      < property   name = "sessionFactory" > < ref   bean = "hostSessionFactory" />property >  
  3. >   

SpServer的写法与《如何在 spring 框架中解决多数据源的问题》 中的一样,我就不再累赘了。

另外,在 spring 配置中配置多个数据源,每个数据源对应一个 sessionFactory ,这个对应的 sessionFactory 中的值对象应当是该数据源的值对象。客户程序在执行数据访问前,通过调用 SpServer putSp() 方法,告诉 MultiSessionFactory 需要切换到哪个 sessionFactory ,然后执行数据访问。这样,不同数据源的值对象通过放在不同的 sessionFactory 中,避免了张冠李戴的情况。具体的示例见附件的 MultiSessionFactoryTest

另外的方案

也许有些朋友对以上方案还不满意,因为在执行数据访问前毕竟还要多做一步指定 sessionFactory 的工作。实际上,对于各个数据源的数据结构不同的项目,一个值对象应当使用哪个数据源有一个非常确定的对应关系。如果通过配置文件将值对象与它的 sessionFactory 对应起来,那么我们在执行数据访问的时候传递的是哪个值对象, MultiSessionFactory 马上就可以去找到对应的 sessionFactory 。这个方案你可以通过 AOP 来制作一个拦截器拦截所有诸如 save() delete() get() load() 等方法来实现,也可以扩展 HibernateDaoSupport 来实现。这样的方案使客户程序甚至都不用知道他是在操作的一个多数据源系统。当然,这个方案感兴趣的朋友可以自己去实现。

另外,在这个方案中的核心是运用 Decorator 设计模式来解决切换 sessionFactory 的目的,即 MultiSessionFactory 的实现。至于通过什么方式来通知 MultiSessionFactory 应当切换到哪个 SessionFactory ,可以根据不同项目的情况自由选择。我在这里给大家提供了通过 SpOberver 和建立值对象与 sessionFactory 关系的配置文件这两个方案,你也可以有自己的方案解决。

第三种情况的解决方案

前面我已经给出了第一种和第二种情况的解决方案:各个数据源的数据结构不同的情况用 MultiSessionFactory 解决;各个数据源的数据结构相同的情况用 MultiDataSource 解决。那么第三种情况,各个数据源的数据结构部分相同又有部分不同,又应当如何解决呢?当然是将 MultiSessionFactory MultiDataSource 结合起来解决。对于数据结构不同的部分,其分别创建各自的 sessionFactory 然后通过 MultiSessionFactory 来切换,而对于数据结构相同的部分,建立共同的 sessionFactory 和多个不同的 dataSource 然后通过 MultiDataSource 来切换就可以了。

还有的朋友问到这样的方案其事务处理和二级缓存的情况。这个方案是在 spring 框架下的解决方案,其事务处理的能力也是由 spring 的能力来决定的。目前 spring 要处理跨数据库的事务处理是通过 JTA 来实现的,这种方式在该方案中同样可以实现,朋友们可以试一试。另外,本方案能使用二级缓存吗?当然可以。对于 MultiSessionFactory 当然没有任何问题,它通过不同的 sessionFactory 分离开了不同的数据源和值对象,我们可以毫无顾忌地使用。对于 MultiDataSource 来说,就有点问题了。 MultiDataSource 使多个数据源使用共同的 sessionFactory ,因此它仿佛就是将多个数据源在逻辑上合并为一个数据源。正因为如此,我们需要保证对于同一个表在所有数据源中都要主键唯一。什么意思呢?数据源 A 和数据源 B 都有表 T ,如果数据源 A 中的表 T 拥有 ID 001 的一条数据,那么在数据源 B 的表 T 中就不能有 ID 001 的记录。如果你总是通过 MultiDataSource 来执行表的插入操作,并且使用uuid.hex生成主键,这当然不会有问题。但如果你有通过其它方式插入表的操作,你应当保证这样的唯一性。另外,对于查询的操作,缓存中存放的既可能是数据源 A 的数据,也可能是数据源 B 的数据,因此你应当对数据有一个规划。对于表 T 的数据,哪些应当插入到数据源 A 中,哪些应当插入到 B 中,应当有一个定义。假如是通过不同单位来决定插入哪个数据源,那么在查询数据源 A 的表 T 是,应当增加条件只查询数据源 A 应当有的单位而排除调其它单位。如此这样,你只要注意到这两个问题,你就可以放心大胆地使用二级缓存。

分享到:
评论

相关推荐

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

    ### 如何在Spring框架中解决多数据源的问题 #### 问题背景及挑战 在实际的软件开发过程中,尤其是在企业级应用开发中,经常会遇到需要同时处理多个数据源的情况。例如,一个应用程序可能需要同时访问Oracle数据库...

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

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

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

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

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

    6. **事务管理**:在多数据源环境下,事务管理变得复杂。Spring的PlatformTransactionManager接口可以扩展以支持多数据源事务。我们可以使用`AbstractRoutingDataSource`作为基础,创建一个动态路由数据源,根据业务...

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

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

    Spring Boot+Jpa多数据源配置Demo(支持不同数据库)

    Spring Boot结合JPA(Java Persistence API)和JdbcTemplate,为开发者提供了灵活且强大的多数据源配置能力。本示例将详细介绍如何在Spring Boot项目中实现这样的配置,以支持不同类型的数据库。 首先,我们要理解...

    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 多数据源

    但在多数据源场景下,我们不能只依赖这些基本配置。 1. **配置多数据源** - 创建两个或更多的数据源配置类,每个数据源对应一个配置类,例如:`PrimaryDataSourceConfig` 和 `SecondaryDataSourceConfig`。 - 在...

    Spring动态切换多数据源Demo

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

    Spring+Hibernate多数据源

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

    spring多数据源

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

    基于Spring多数据源实例

    在多数据源切换实例中,我们假设已经部署了两个或更多的Oracle数据库实例,每个实例可能存储不同类型或者不同业务领域内的数据。 实现多数据源切换的关键步骤如下: 1. **配置数据源**:在Spring的配置文件中,...

    mybatis spring 多数据源

    "工具"可能是指像Druid、HikariCP这样的数据库连接池,它们在多数据源配置中起着至关重要的作用,提供高效且稳定的数据库连接管理。 至于压缩包文件名称 "JX_VIDEO_SYNCHRONIZATION",它看起来与视频同步相关,但...

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

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

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

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

    spring 动态多数据源配置代码

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

    SSM框架多数据源的配置

    1. 配置事务管理器:在多数据源的情况下,需要配置两个PlatformTransactionManager,对应每个数据源,并在需要的地方进行指定。 2. 数据源切换:在运行时,确保根据业务需求正确切换数据源,避免出现数据不一致的...

Global site tag (gtag.js) - Google Analytics