springMVC+MyBatis多数据源动态切换

之前项目太忙,没有发布新文章。这两天得空,把我最新研究成果(虽然过了很久)发表出来,希望对大家有所帮助!

切入正题:在使用spring+mybatis方式进行数据库持久化,需要在配置文件(我的配置文件名称为“spring-config-dao.xml”)中加入

  1.     <!– 数据库操作Session工厂 –>
  2.     <bean id=“sqlSessionFactory” class=“org.mybatis.spring.SqlSessionFactoryBean”>
  3.         <property name=“dataSource” ref=“dataSource” />
  4.         <property name=“configLocation” value=“classpath:mybatis/mybatis-config.xml” />
  5.     </bean>

但如果要增加一个数据源呢?正常理解,再加一个不就好了?

<!-- 数据库操作Session工厂 -->
<bean id="sqlSessionFactoryA" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <property name="configLocation" value="classpath:mybatis/mybatis-config.xml"></property>
</bean>

<!-- 数据库操作Session工厂2 -->
<bean id="sqlSessionFactoryB" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource2"></property>
    <property name="configLocation" value="classpath:mybatis/mybatis-config-dos.xml"></property>
</bean>

但按照上述配置后,启动tomcat,却发现下列错误:

Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire method: public final void org.mybatis.spring.support.SqlSessionDaoSupport.setSqlSessionFactory(org.apache.ibatis.session.SqlSessionFactory); nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [org.apache.ibatis.session.SqlSessionFactory] is defined: expected single matching bean but found 2: [sqlSessionFactoryA, sqlSessionFactoryB]

分析:

这段话是说,SqlSessionFactory这个类必须是唯一的。但是现在发现两个:“sqlSessionFactoryA, sqlSessionFactoryB”。
那么如何才能使用两种或以上的数据源呢?经过一番搜索,发现我们的公共类BaseDao.java中,继承了SqlSessionDaoSupport。

  1. public abstract class BaseDao<extends Object> extends SqlSessionDaoSupport

而这个SqlSessionDaoSupport类中就有setSqlSessionFactory方法。源码如下:

  1.   @Autowired(required = false)
  2.   public final void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
  3.     if (!this.externalSqlSession) {
  4.       this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
  5.     }
  6.   }

于是上网搜索答案。终于,在国外网站上看到有人说可以用Qualifier来指定sqlSessionFactory。但没有给出具体方法,很是苦恼。

在经历无数次失败后,终于解决了问题。方法公布:

1、将原来BaseDao.java中继承的SqlSessionDaoSupport重写,命名为MySqlSessionDaoSupport

  1. package com.xx.icon.config.common.dao;
  2.  
  3. import org.apache.ibatis.session.SqlSession;
  4. import org.apache.ibatis.session.SqlSessionFactory;
  5. import org.mybatis.spring.SqlSessionTemplate;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.beans.factory.annotation.Qualifier;
  8. import org.springframework.dao.support.DaoSupport;
  9.  
  10. import static org.springframework.util.Assert.notNull;
  11.  
  12. /**
  13.  * MyBatis数据源切换
  14.  * @author : zoutuo
  15.  * @version : 1.0
  16.  * @date : 14-3-27 下午3:57
  17.  */
  18. public class MySqlSessionDaoSupport extends DaoSupport {
  19.  
  20.     private SqlSession sqlSession;
  21.  
  22.     private boolean externalSqlSession;
  23.  
  24.     @Autowired(required = false)
  25.     public final void setSqlSessionFactory(@Qualifier(“sqlSessionFactoryA”) SqlSessionFactory sqlSessionFactory) {
  26.         if (!this.externalSqlSession) {
  27.             this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
  28.         }
  29.     }
  30.  
  31.     @Autowired(required = false)
  32.     public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
  33.         this.sqlSession = sqlSessionTemplate;
  34.         this.externalSqlSession = true;
  35.     }
  36.  
  37.     /**
  38.      * Users should use this method to get a SqlSession to call its statement methods
  39.      * This is SqlSession is managed by spring. Users should not commit/rollback/close it
  40.      * because it will be automatically done.
  41.      *
  42.      * @return Spring managed thread safe SqlSession
  43.      */
  44.     public final SqlSession getSqlSession() {
  45.         return this.sqlSession;
  46.     }
  47.  
  48.     /**
  49.      * {@inheritDoc}
  50.      */
  51.     protected void checkDaoConfig() {
  52.         notNull(this.sqlSession, “Property ‘sqlSessionFactory’ or ‘sqlSessionTemplate’ are required”);
  53.     }
  54. }

可以看到,上面的setSqlSessionFactory方法中增加了代码“@Qualifier(“sqlSessionFactoryA”)”。这就是说指定某个特定的Factory。

2、将原来的BaseDao.java中extend换为刚才创建的MySqlSessionDaoSupport

  1. public abstract class BaseDao<extends Object> extends MySqlSessionDaoSupport

3、新建MySqlSessionDaoSupport2,增加“@Qualifier(“sqlSessionFactoryB”)

  1. package com.xx.icon.config.common.dao;
  2.  
  3. import org.apache.ibatis.session.SqlSession;
  4. import org.apache.ibatis.session.SqlSessionFactory;
  5. import org.mybatis.spring.SqlSessionTemplate;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.beans.factory.annotation.Qualifier;
  8. import org.springframework.dao.support.DaoSupport;
  9.  
  10. import static org.springframework.util.Assert.notNull;
  11.  
  12. /**
  13.  * MyBatis数据源切换
  14.  * @author : zoutuo
  15.  * @version : 1.0
  16.  * @date : 14-3-27 下午3:57
  17.  */
  18. public class MySqlSessionDaoSupport2 extends DaoSupport {
  19.  
  20.     private SqlSession sqlSession;
  21.  
  22.     private boolean externalSqlSession;
  23.  
  24.     @Autowired(required = false)
  25.     public final void setSqlSessionFactory(@Qualifier(“sqlSessionFactoryB”) SqlSessionFactory sqlSessionFactory) {
  26.         if (!this.externalSqlSession) {
  27.             this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
  28.         }
  29.     }
  30.  
  31.     @Autowired(required = false)
  32.     public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
  33.         this.sqlSession = sqlSessionTemplate;
  34.         this.externalSqlSession = true;
  35.     }
  36.  
  37.     /**
  38.      * Users should use this method to get a SqlSession to call its statement methods
  39.      * This is SqlSession is managed by spring. Users should not commit/rollback/close it
  40.      * because it will be automatically done.
  41.      *
  42.      * @return Spring managed thread safe SqlSession
  43.      */
  44.     public final SqlSession getSqlSession() {
  45.         return this.sqlSession;
  46.     }
  47.  
  48.     /**
  49.      * {@inheritDoc}
  50.      */
  51.     protected void checkDaoConfig() {
  52.         notNull(this.sqlSession, “Property ‘sqlSessionFactory’ or ‘sqlSessionTemplate’ are required”);
  53.     }
  54. }

 

至此,第二个数据源配置好了。在调用时,需要用到两个BaseDao。一个是继承MySqlSessionDaoSupport,另一个继承MySqlSessionDaoSupport2就可以了。

需要注意的是,这种方式的双数据源,需要两个BaseDao,两个MySqlSessionDaoSupport,两个mybatis-config.xml(文章最开始处spring-config-dao.xml中提到)。

5 comments on “springMVC+MyBatis多数据源动态切换

    • 当初也搞了好久,最后是在国外网站上看到的一个说法,自己给实现了,方法放出,方便大家开发。
      多谢支持!

Submit comment

Allowed HTML tags: <a href="http://google.com">google</a> <strong>bold</strong> <em>emphasized</em> <code>code</code> <blockquote>
quote
</blockquote>