之前项目太忙,没有发布新文章。这两天得空,把我最新研究成果(虽然过了很久)发表出来,希望对大家有所帮助!
切入正题:在使用spring+mybatis方式进行数据库持久化,需要在配置文件(我的配置文件名称为“spring-config-dao.xml”)中加入
- <!– 数据库操作Session工厂 –>
- <bean id=“sqlSessionFactory” class=“org.mybatis.spring.SqlSessionFactoryBean”>
- <property name=“dataSource” ref=“dataSource” />
- <property name=“configLocation” value=“classpath:mybatis/mybatis-config.xml” />
- </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。
- public abstract class BaseDao<T extends Object> extends SqlSessionDaoSupport
而这个SqlSessionDaoSupport类中就有setSqlSessionFactory方法。源码如下:
- @Autowired(required = false)
- public final void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
- if (!this.externalSqlSession) {
- this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
- }
- }
于是上网搜索答案。终于,在国外网站上看到有人说可以用Qualifier来指定sqlSessionFactory。但没有给出具体方法,很是苦恼。
在经历无数次失败后,终于解决了问题。方法公布:
1、将原来BaseDao.java中继承的SqlSessionDaoSupport重写,命名为MySqlSessionDaoSupport:
- package com.xx.icon.config.common.dao;
- import org.apache.ibatis.session.SqlSession;
- import org.apache.ibatis.session.SqlSessionFactory;
- import org.mybatis.spring.SqlSessionTemplate;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Qualifier;
- import org.springframework.dao.support.DaoSupport;
- import static org.springframework.util.Assert.notNull;
- /**
- * MyBatis数据源切换
- * @author : zoutuo
- * @version : 1.0
- * @date : 14-3-27 下午3:57
- */
- public class MySqlSessionDaoSupport extends DaoSupport {
- private SqlSession sqlSession;
- private boolean externalSqlSession;
- @Autowired(required = false)
- public final void setSqlSessionFactory(@Qualifier(“sqlSessionFactoryA”) SqlSessionFactory sqlSessionFactory) {
- if (!this.externalSqlSession) {
- this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
- }
- }
- @Autowired(required = false)
- public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
- this.sqlSession = sqlSessionTemplate;
- this.externalSqlSession = true;
- }
- /**
- * Users should use this method to get a SqlSession to call its statement methods
- * This is SqlSession is managed by spring. Users should not commit/rollback/close it
- * because it will be automatically done.
- *
- * @return Spring managed thread safe SqlSession
- */
- public final SqlSession getSqlSession() {
- return this.sqlSession;
- }
- /**
- * {@inheritDoc}
- */
- protected void checkDaoConfig() {
- notNull(this.sqlSession, “Property ‘sqlSessionFactory’ or ‘sqlSessionTemplate’ are required”);
- }
- }
可以看到,上面的setSqlSessionFactory方法中增加了代码“@Qualifier(“sqlSessionFactoryA”)”。这就是说指定某个特定的Factory。
2、将原来的BaseDao.java中extend换为刚才创建的MySqlSessionDaoSupport
- public abstract class BaseDao<T extends Object> extends MySqlSessionDaoSupport
3、新建MySqlSessionDaoSupport2,增加“@Qualifier(“sqlSessionFactoryB”)”
- package com.xx.icon.config.common.dao;
- import org.apache.ibatis.session.SqlSession;
- import org.apache.ibatis.session.SqlSessionFactory;
- import org.mybatis.spring.SqlSessionTemplate;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.beans.factory.annotation.Qualifier;
- import org.springframework.dao.support.DaoSupport;
- import static org.springframework.util.Assert.notNull;
- /**
- * MyBatis数据源切换
- * @author : zoutuo
- * @version : 1.0
- * @date : 14-3-27 下午3:57
- */
- public class MySqlSessionDaoSupport2 extends DaoSupport {
- private SqlSession sqlSession;
- private boolean externalSqlSession;
- @Autowired(required = false)
- public final void setSqlSessionFactory(@Qualifier(“sqlSessionFactoryB”) SqlSessionFactory sqlSessionFactory) {
- if (!this.externalSqlSession) {
- this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
- }
- }
- @Autowired(required = false)
- public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) {
- this.sqlSession = sqlSessionTemplate;
- this.externalSqlSession = true;
- }
- /**
- * Users should use this method to get a SqlSession to call its statement methods
- * This is SqlSession is managed by spring. Users should not commit/rollback/close it
- * because it will be automatically done.
- *
- * @return Spring managed thread safe SqlSession
- */
- public final SqlSession getSqlSession() {
- return this.sqlSession;
- }
- /**
- * {@inheritDoc}
- */
- protected void checkDaoConfig() {
- notNull(this.sqlSession, “Property ‘sqlSessionFactory’ or ‘sqlSessionTemplate’ are required”);
- }
- }
至此,第二个数据源配置好了。在调用时,需要用到两个BaseDao。一个是继承MySqlSessionDaoSupport,另一个继承MySqlSessionDaoSupport2就可以了。
需要注意的是,这种方式的双数据源,需要两个BaseDao,两个MySqlSessionDaoSupport,两个mybatis-config.xml(文章最开始处spring-config-dao.xml中提到)。
按照博主的方法操作,没有任何问题,赞一个!
感谢博主分享!
楼主威武!
完美解决问题,十分感谢博主!!!
当初也搞了好久,最后是在国外网站上看到的一个说法,自己给实现了,方法放出,方便大家开发。
多谢支持!