我们公司的项目使用spring+mybatis组合。所以就必须得使用mybatis-spring了。所以此处就昨日mybatis-spring从1.1升级到1.2所带来的dao层级的编写问题,做了一个总结。
我们可以先来看看mybatis-spring框架的1.1.1版本中关于SqlSessionDaoSupport的代码吧:
1 package org.mybatis.spring.support; 2 3 import static org.springframework.util.Assert.*; 4 5 import org.apache.ibatis.session.SqlSession; 6 import org.apache.ibatis.session.SqlSessionFactory; 7 import org.mybatis.spring.SqlSessionTemplate; 8 import org.springframework.beans.factory.annotation.Autowired; 9 import org.springframework.dao.support.DaoSupport; 10 11 /** 12 * Convenient super class for MyBatis SqlSession data access objects. 13 * It gives you access to the template which can then be used to execute SQL methods. 14 * <p> 15 * This class needs a SqlSessionTemplate or a SqlSessionFactory. 16 * If both are set the SqlSessionFactory will be ignored. 17 * 18 * @see #setSqlSessionFactory 19 * @see #setSqlSessionTemplate 20 * @see SqlSessionTemplate 21 * @version $Id: SqlSessionDaoSupport.java 4885 2012-03-12 09:58:54Z simone.tripodi $ 22 */ 23 public abstract class SqlSessionDaoSupport extends DaoSupport { 24 25 private SqlSession sqlSession; 26 27 private boolean externalSqlSession; 28 29 @Autowired(required = false) 30 public final void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { 31 if (!this.externalSqlSession) { 32 this.sqlSession = new SqlSessionTemplate(sqlSessionFactory); 33 } 34 } 35 36 @Autowired(required = false) 37 public final void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { 38 this.sqlSession = sqlSessionTemplate; 39 this.externalSqlSession = true; 40 } 41 42 /** 43 * Users should use this method to get a SqlSession to call its statement methods 44 * This is SqlSession is managed by spring. Users should not commit/rollback/close it 45 * because it will be automatically done. 46 * 47 * @return Spring managed thread safe SqlSession 48 */ 49 public final SqlSession getSqlSession() { 50 return this.sqlSession; 51 } 52 53 /** 54 * {@inheritDoc} 55 */ 56 protected void checkDaoConfig() { 57 notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required"); 58 } 59 60 }
从上面的源码可以看出:在方法setSqlSessionFactory和setSqlSessionTemplate方法上面都标注有:“@Autowired(required = false)”这样的注解。
所以我们在编写dao层级代码的时候只需要dao直接继承SqlSessionDaoSupport,并标注注解@Repository,然后就可 以使用类似的getSqlSession().selectList("User.selectUsers");这样的方法来使用它了,而且在 spring的配置文件中的配置也比较少:
1 <tx:annotation-driven transaction-manager="txManager" 2 proxy-target-class="true"/> 3 4 <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 5 <property name="dataSource" ref="dataSource"/> 6 </bean> 7 8 <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> 9 <property name="dataSource" ref="dataSource"/> 10 <property name="configLocation" value="classpath:mybatis-config.xml"/> 11 </bean>
但是升级到1.2之后,我们看看SqlSessionDaoSupport的源代码:
1 public abstract class SqlSessionDaoSupport extends DaoSupport { 2 3 private SqlSession sqlSession; 4 5 private boolean externalSqlSession; 6 7 public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { 8 if (!this.externalSqlSession) { 9 this.sqlSession = new SqlSessionTemplate(sqlSessionFactory); 10 } 11 } 12 13 public void setSqlSessionTemplate(SqlSessionTemplate sqlSessionTemplate) { 14 this.sqlSession = sqlSessionTemplate; 15 this.externalSqlSession = true; 16 } 17 18 /** 19 * Users should use this method to get a SqlSession to call its statement methods 20 * This is SqlSession is managed by spring. Users should not commit/rollback/close it 21 * because it will be automatically done. 22 * 23 * @return Spring managed thread safe SqlSession 24 */ 25 public SqlSession getSqlSession() { 26 return this.sqlSession; 27 } 28 29 /** 30 * {@inheritDoc} 31 */ 32 protected void checkDaoConfig() { 33 notNull(this.sqlSession, "Property 'sqlSessionFactory' or 'sqlSessionTemplate' are required"); 34 } 35 36 }
从上面的源码可以看出:在方法setSqlSessionFactory和setSqlSessionTemplate方法上面现在都没有标注有:“@Autowired(required = false)”这样的注解。
如果一些系统直接从mybatis-spring1.1.1升级到1.2版本的时候,就会出现问题。
在1.2版本下面有几种方式来使用:
从上面的源码可以看出:在方法setSqlSessionFactory和setSqlSessionTemplate方法上面现在都没有标注有:“@Autowired(required = false)”这样的注解。
如果一些系统直接从mybatis-spring1.1.1升级到1.2版本的时候,就会出现问题。
在1.2版本下面有几种方式来使用:
1 @Repository 2 public class UserDao extends SqlSessionDaoSupport{ 3 public List<User> userList() { 4 return getSqlSession().selectList("User.selectUsers"); 5 } 6 7 @Override 8 @Autowired 9 public void setSqlSessionFactory(SqlSessionFactory sqlSessionFactory) { 10 super.setSqlSessionFactory(sqlSessionFactory); 11 } 12 }
我们自己重写set方法就可以了。在这种情况下spring的配置文件不需要修改。这个实例是随意写的,如果你的工程中dao类很多(绝大多数情况 都是),这样你就可以编写一个BaseDao,然后在这个BaseDao中重写这个方法,其他的dao只需要继承这个BaseDao就可以了。
第二章基于xml文件配置:
1 public class UserDao extends SqlSessionDaoSupport { 2 public List<User> userList() { 3 return getSqlSession().selectList("User.selectUsers"); 4 } 5 }
但是需要在spring的配置文件中增加这个UserDao的配置:
1 <bean id="userDao" class="com.qunar.corp.paginator.dao.UserDao"> 2 <property name="sqlSessionFactory" ref="sqlSessionFactory"/> 3 </bean>
第一种基于注解的配置,好处是不需要编写xml,但是这种比较容易侵入业务逻辑。
第二种基于xml配置,好处是不侵入业务逻辑,但是当dao的数量很多的时候,需要在xml中配置好多。
所以最后具体选择哪种,大家可以结合自己的情况。