《深入浅出MyBatis技术原理与实战》摘要 --- MyBatis-Spring
以下内容来源《深入浅出MyBatis技术原理与实战》
第 8 章 MyBatis-Spring
MyBatis 提供了和 Spring 无缝对接的功能,它主要通过 myBatis-spring.jar 实现。
8.1 Spring 的基础知识
略
8.2 MyBatis-Spring 应用
8.2.1 概述
Spring 配置的方法较多,可通过 XML 进行配置,也可以通过注解配置,但是通过注解配置已经成为了主流,所以本书主要讲解通过注解配置 MyBatis-Spring 。
配置 MyBatis-Spring 分为下面几个部分。
- 配置数据源
- 配置 SqlSessionFactory
- 配置 SqlSessionTemplate
- 配置 Mapper
- 事务处理
在 MyBayis 中要构建 SqlSessionFactory 对象,让它来产生 SqlSession,而在 MyBatis-Spring 项目中 SqlSession 的使用是通过 SqlSessionTemplate 来实现的,它提供了对 SqlSession 操作的封装。所以通过 SqlSessionTemplate 可以得到 Mapper。
8.2.2 配置 SqlSessionFactory
MyBatis-Spring 项目提供了 org.mybatis.spring.SqlSessionFactoryBean 类给我们去配置。一般而言,我们需要给出两个参数,一个是数据源,另一个是 MyBatis 的配置文件路径,这样 Spring IOC 容器就会初始化这个 SqlSessionFactory Bean,解析 MyBatis 配置文件并连同数据源一同保存在 Spring Bean 里面。
代码1 在 Spring 配置文件中配置 SqlSessionFactory
<!-- 创建 DataSource Bean --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName">com.mysql.jdbc.Driver</property> <property name="url">jdbc:mysql://localhost:3306/mybatistest?useSSL=true</property> <property name="username">root</property> <property name="password">root</property> </bean> <!-- 创建 SqlSessionFactory Bean --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"></property> <property name="configLocation" value="classpath:sqlMapConfig.xml"></property> </bean>
由于 Spring 帮助我们初始化了数据源,MyBatis 的配置文件就无需再配置关于数据库的 environments 的节点信息了。
8.2.3 配置 SqlSessionTemplate
SqlSessionTemplate(org.mybatis.spring.SqlSessionTemplate)是一个模板类,通过调用 SqlSession 来完成工作,所以在 MyBatis-Spring 项目中它是一个核心类。它有两种构建方法,一种是只有一个 SqlSessionFactory 作为参数的;另一种有两个参数,SqlSessionFactory 和 执行器类型(它是一个枚举类 ExecutorType)。
代码2 构建 SqlSessionTemplate 的两种方式
<!-- 使用两个参数(SqlSessionFactory、ExecutorType)构建 --> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate" scope="prototype"> <constructor-arg index="0" ref="sqlSessionFactory" /> <constructor-arg name="1" value="BATCH" /> </bean>
第二个 ExecutorType 的取值范围是:SIMPLE、REUSE、BATCH。
通过这些配置,Spring 就会把 SqlSessionFactory 设置到 SqlSessionTemplate 中。如果我们同事设置了 SqlSessionFactory 和 SqlSessionTemplate ,那么系统就只会用 SqlSessionTemplate 去覆盖掉 SqlSessionFactory。
SqlSessionTemplate 可以执行许多功能,但是在目前 MyBatis 的编程中用得不多,因为我们完全可以直接通过映射器擦除它,这样更易于理解。
代码3 简单的使用 SqlSessionTemplate 的示例
1 public class RoleDAOImpl implements RoleDAO{ 2 3 @Autowired 4 private SqlSessionTemplate sqlSessionTemplate; 5 6 @Override 7 public Role getRole(Long id) { 8 Role role = (Role)this.sqlSessionTemplate.selectOne("com.learn.dao.RoleDAO.getRole", id); 9 return role; 10 } 11 12 @Override 13 public List<Role> findRole(String roleName) { 14 return this.sqlSessionTemplate.selectList("com.learn.dao.RoleDAO.findRole", roleName); 15 } 16 17 @Override 18 public int updateRole(Role role) { 19 return this.sqlSessionTemplate.update("com.learn.dao.RoleDAO.updateRole", role); 20 } 21 22 @Override 23 public int insertRole(Role role) { 24 return this.sqlSessionTemplate.insert("com.learn.dao.RoleDAO.insertRole", role); 25 } 26 27 @Override 28 public int deleteRole(Long id) { 29 return this.sqlSessionTemplate.delete("com.learn.dao.RoleDAO.deleteRole", id); 30 } 31 32 }
我们不建议使用这样的编程方式,原因有两个:
1、SqlSessionTemplate 是 MyBatis 的类,我们要使用一个 id,去标出我们将会调用的那条 SQL,这对于编程来说是困难的,有侵入框架之嫌,可读性较低。
2、我们在编写代码时不能保证 id 的正确性。因为 IDE 无法识别 id 是否正确,需要运行的时候才能知道。
因此笔者建议大家采用 Mapper 接口的编程方式。
8.2.4 配置 Mapper
在代码中,大部分场景都不建议使用 SqlSessionTemplate 或者 SqlSession 的方式。这里我们采用 Mapper 接口编程的方式。
8.2.4.1 MapperFactoryBean
在 MyBatis 中,Mapper 只需要一个接口,而不是实现类,它是由 MyBatis 通过动态代理的形式生成代理对象去运行的,Spring 没有办法为其生成实现类。
所以,Mybatis-Spring 团队提供了一个 MapperFactoryBean 类作为中介,我们可以通过配置它来实现我们想要的Mapper。配置 MapperFactoryBean 有 3 个参数,mapperInterface、SQLSessionFactory 和 SqlSessionTemplate 。
- mapperInterface,用来指定接口,当我们的接口继承了配置的接口,那么 MyBatis 就认为它是一个 Mapper。
- SqlSessionFactory,当 SqlSessionTemplate 属性没有配置时,MyBatis-Spring 才会去设置它。
- SqlSessionTemplate,当它被设置的时候,SqlSessionFactory 将被作废。
代码4 配置 MapperFactoryBean 的 Mapper
<bean id="roleDao" class="org.mybatis.spring.mapper.MapperFactoryBean"> <!-- RoleDAO 接口将被扫描为 Mapper --> <property name="mapperInterface" value="com.learn.dao.RoleDAO" /> <!-- <property name="sqlSessionFactory" ref="sqlSessionFactory"></property> --> <!-- 如果同时注入 SqlSessionTemplate 和 SqlSessionFactory,则只会启用 sqlSessionTemplate --> <property name="sqlSessionTemplate" ref="sqlSessionTemplate" /> </bean>
这样我们就可以使用这个接口进行编程了,它的效果等同于 sqlSession.getMapper(RoleDAO.class)。
8.2.4.2 MapperScannerConfigurer
MapperScannerConfigurer 采用自动扫描的形式来配置我们的映射器,这样我们就可以在很少的代码情况下完成对众多映射器的配置,大大提高了效率。
在 MyBatis 项目中,我们采用的是 MapperScannerConfigurer。我们可以配置这么几个属性。
- basePackage,指定让 Spring 自动扫描什么包,它会逐层深入扫描。
- annotationClass,表示如果类被这个注解标识的时候,才进行扫描。
- sqlSessionFactoryBeanName,指定在 Spring 中定义 sqlSessionFactory 的 bean 名称。如果它被定义,sqlSessionFactory 将不起作用。
- sqlSessionTemplateBeanName,指定在 Spring 中定义 sqlSessionTemplate 的 bean 名称。如果它被定义,sqlSessionFactoryBeanName 将不起作用。
- markerInterface,指定是实现了什么接口就认为它是 Mapper。我们需要提供一个公共的接口去标记。在 Spring 配置前需要给 需要给 DAO 一个注解。在 Spring 中往往是使用注解 @Repository 表示 DAO层。
代码5 扫描指定包中的类中被指定注解标识的类配置映射器示例
<!-- 采用自动扫描方式创建 mapper bean --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.learn.dao" /> <property name="sqlSessionTemplateBeanName" value="sqlSessionTemplae" /> <property name="annotationClass" value="org.springframework.stereotype.Repository" /> </bean>
代码 5 配置后,Spring 上下文就会自动扫描 com.learn.dao 从而找到标注了 Repository 的接口,自动生成 Mapper,而无需多余的配置。
8.2.5 配置事务
MyBatis 和 Spring 结合后是使用 Spring AOP 去管理事务。
代码6 配置 Spring 声明式事务示例
<!-- 事务管理器 --> <bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource" /> </bean> <!-- 使用声明式事务管理方式 --> <tx:annotation-driven transaction-manager="txManager" />
这个时候我们往往需要业务层,业务层即是处理业务的地方,又是管理数据库事务的地方,我们可以使用 Spring 的注解 Service 来表示哪个类为业务层的类。同样,我们也可以通过自动扫描的方法读取 Service 对象到 Spring 上下文。
代码7 Spring 配置业务层示例
<context:component-scan base-package="com" use-default-filters="false"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Service" /> </context:component-scan>
这样 Spring 就会自动扫描这些 Service 对象的 bean 读取到上下文中。MyBatis 的事务就交由 Spring 去控制了。我们只需要在 Spring 中通过注解注入即可。

浙公网安备 33010602011771号