我們公司的項目使用spring+mybatis組合。所以就必須得使用mybatis-spring了。所以此處就昨日mybatis-spring從1.1升級到1.2所帶來的dao層級的編寫問題,做了一個總結。
我們可以先來看看mybatis-spring框架的1.1.1版本中關於SqlSessionDaoSupport的代碼吧:
package org.mybatis.spring.support;
import static org.springframework.util.Assert.*;
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.dao.support.DaoSupport;
/**
* Convenient super class for MyBatis SqlSession data access objects.
* It gives you access to the template which can then be used to execute SQL methods.
* <p>
* This class needs a SqlSessionTemplate or a SqlSessionFactory.
* If both are set the SqlSessionFactory will be ignored.
*
* @see #setSqlSessionFactory
* @see #setSqlSessionTemplate
* @see SqlSessionTemplate
* @version $Id: SqlSessionDaoSupport.java 4885 2012-03-12 09:58:54Z simone.tripodi $
*/
public abstract class SqlSessionDaoSupport extends DaoSupport {
private SqlSession sqlSession;
private boolean externalSqlSession;
@Autowired(required = false)
public final void setSqlSessionFactory(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和setSqlSessionTemplate方法上面都標注有:“@Autowired(required = false)”這樣的注解。
所以我們在編寫dao層級代碼的時候只需要dao直接繼承SqlSessionDaoSupport,並標注注解@Repository,然后就可以使用類似的getSqlSession().selectList("User.selectUsers");這樣的方法來使用它了,而且在spring的配置文件中的配置也比較少:
<tx:annotation-driven transaction-manager="txManager"
proxy-target-class="true"/>
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource"/>
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
但是升級到1.2之后,我們看看SqlSessionDaoSupport的源代碼:
public abstract class SqlSessionDaoSupport extends DaoSupport {
private SqlSession sqlSession;
private boolean externalSqlSession;
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
if (!this.externalSqlSession) {
this.sqlSession = new SqlSessionTemplate(sqlSessionFactory);
}
}
public 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 SqlSession getSqlSession() {
return this.sqlSession;
}
/**
* {@inheritDoc}
*/
protected void checkDaoConfig() {
notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required");
}
}
從上面的源碼可以看出:在方法setSqlSessionFactory和setSqlSessionTemplate方法上面現在都沒有標注有:“@Autowired(required = false)”這樣的注解。
如果一些系統直接從mybatis-spring1.1.1升級到1.2版本的時候,就會出現問題。
在1.2版本下面有幾種方式來使用:
第一種,基於注解:
@Repository
public class UserDao extends SqlSessionDaoSupport{
public List<User> userList() {
return getSqlSession().selectList("User.selectUsers");
}
@Override
@Autowired
public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) {
super.setSqlSessionFactory(sqlSessionFactory);
}
}
我們自己重寫set方法就可以了。在這種情況下spring的配置文件不需要修改。這個實例是隨意寫的,如果你的工程中dao類很多(絕大多數情況都是),這樣你就可以編寫一個BaseDao,然后在這個BaseDao中重寫這個方法,其他的dao只需要繼承這個BaseDao就可以了。
第二章基於xml文件配置:
public class UserDao extends SqlSessionDaoSupport {
public List<User> userList() {
return getSqlSession().selectList("User.selectUsers");
}
}
但是需要在spring的配置文件中增加這個UserDao的配置:
<bean id="userDao" class="com.xxx.paginator.dao.UserDao">
<property name="sqlSessionFactory" ref="sqlSessionFactory"/>
</bean>
第一種基於注解的配置,好處是不需要編寫xml,但是這種比較容易侵入業務邏輯。
第二種基於xml配置,好處是不侵入業務邏輯,但是當dao的數量很多的時候,需要在xml中配置好多。
所以最后具體選擇哪種,大家可以結合自己的情況。
