原文链接:http://blog.zous-windows.com/archives/207.html
在使用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中提到)。