MyBatis 是以SqlSessionFactory为核心的,Spring是以BeanFactory或ApplicationContext为核心的。把两者整合在一起,Mybatis-Spring封装了一个SqlSessionFactoryBean,在这个Bean里可以产生SqlSessionFactory。所以通过Spring的IoC实现SqlSessionFactoryBean的注入即可将二者整合。
使用Mybatis-Spring模块需要mybatis-spring-x.x.x.jar包,如果使用Maven,则需在pom.xml文件中添加下面代码:
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>x.x.x</version>
</dependency>
在MyBatis中,session工厂可以使用SqlSessionFactoryBuilder来创建。而在MyBatis-Spring中,则使用SqlSessionFactoryBean来替代。
要想实现对SqlSessionFactoryBean的注入,需要在spring的配置文件中添加这样的一个bean元素:
<!-- 读取properties文件 -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 配置数据源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="${jdbc.driver}" />
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<!-- SqlSessionFactoryBean -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!-- dataSource用于指定mybatis的数据源 -->
<property name="dataSource" ref="dataSource"/>
<!-- mapperLocations用于指定mybatis中mapper文件所在的位置 -->
<property name="mapperLocations" value="classpath:mapper/*.xml"/>
<!-- 自动重命名 -->
<property name="typeAliasesPackage" value="com.test.mybatis_spring.model" />
<!-- 用于指定mybatis配置文件的位置 -->
<property name="configLocation" value="classpath:mybatis-config.xml"/>
</bean>
构建SqlSessionFactoryBean的时候,dataSource属性是必须指定的,它表示用于连接数据库的数据源。我们也可以指定一些其他的属性,如:
typeAliasesPackage:实体类所在的包,自动取包中不包括包名的简单类名作为别名。 多个package之间可以用逗号或者分号等来进行分隔。typeAliases:数组类型,用来指定别名的。指定了这个属性后,Mybatis会把这个类型的短名称作为这个类型的别名, 前提是该类上没有@Alias注解,否则将使用该注解对应的值作为此种类型的别名。如: <property name="typeAliases">
<array>
<value>com.test.mybatis.model.Blog</value>
<value>com.test.mybatis.model.Comment</value>
</array>
</property>
plugins:数组类型,用来指定Mybatis的Interceptor。typeHandlersPackage:用来指定TypeHandler所在的包,自动把该包下面的类注册为对应的TypeHandler。多个package之间可以用逗号或者分号等来进行分隔。typeHandlers:数组类型,用来指定TypeHandler。通过SqlSessionFactoryBean可以产生SqlSessionFactory,在MyBatis中,通过sqlSessionFactory.openSession()得到sqlSession,然后通过session.getMapper(xxx.class)得到对应的Mapper。在Spring中,通过MapperFactoryBean可以获取到我们想要的Mapper对象。
MapperFactoryBean实现了Spring的FactoryBean接口,所以MapperFactoryBean是通过FactoryBean接口中定义的getObject方法来获取对应的Mapper对象的。在定义一个MapperFactoryBean的时候有两个属性需要我们注入,一个是Mybatis-Spring用来生成实现了SqlSession接口的SqlSessionTemplate对象的sqlSessionFactory;另一个是我们所要返回的对应的Mapper接口。
比如,有一个UserMapper接口:
//UserMapper.java
public interface UserMapper {
@Select("SELECT * FROM users WHERE id = #{userId}")
User getUser(@Param("userId") String userId);
}
使用MapperFactoryBean把接口加入到 Spring 中:
<bean id="userMapper" class="org.mybatis.spring.mapper.MapperFactoryBean">
<!-- 指定的映射器类必须是一个接口,而不是具体的实现类 -->
<property name="mapperInterface" value="com.test.mybatis_spring.mapper.UserMapper" />
<property name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>
定义好Mapper接口对应的MapperFactoryBean之后,就可以把对应的Mapper接口注入到由Spring管理的bean对象中了。当我们需要使用到相应的Mapper接口时,MapperFactoryBean会从它的getObject方法中获取对应的Mapper接口,而getObject内部还是通过我们注入的属性调用SqlSession接口的getMapper()方法来返回对应的Mapper接口。这样就通过把SqlSessionFactory和相应的Mapper接口交给Spring管理实现了Mybatis跟Spring的整合。
像上面一个Mapper就需要定义一个对应的MapperFactoryBean。Mybatis-Spring提供了一个叫MapperScannerConfigurer的类,可以自动注册Mapper对应的MapperFactoryBean对象。我们只需要在配置文件中添加这样的内容:
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.test.mybatis_spring.mapper" />
</bean>
MapperScannerConfigurer有一个basePackage属性必须指定。basePackage用来指定Mapper接口文件所在的包,在这个包或其子包下面的Mapper接口都将被搜索到。多个包之间可以使用逗号或者分号进行分隔。另外还有两个可以缩小搜索和注册范围的属性,一个是annotationClass,另一个是markerInterface。
annotationClass:当指定了annotationClass时,MapperScannerConfigurer将只注册使用了annotationClass注解标记的接口。markerInterface:markerInterface用于指定一个接口,当指定了markerInterface之后,MapperScannerConfigurer将只注册继承自markerInterface的接口。如果上述两个属性都指定了的话,那么MapperScannerConfigurer将取它们的并集,而不是交集。
MyBatis-Spring利用了存在于Spring中的DataSourceTransactionManager进行事务管理。一旦Spring的PlatformTransactionManager配置好了,就可以在Spring中以你通常的做法(@Transactional注解)来配置事务。在事务处理期间,会创建一个单独的SqlSession对象,当事务完成时,这个session会以合适的方式提交或回滚。
要开启Spring的事务处理,需要在Spring的配置文件中创建一个DataSourceTransactionManager对象:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
下面这段代码展示如何编程式地控制事务:
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatus status = txManager.getTransaction(def);
try {
userMapper.insertUser(user);
}
catch (MyException ex) {
txManager.rollback(status);
throw ex;
}
txManager.commit(status);