《深入浅出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 中通过注解注入即可。

 

posted @ 2018-06-23 13:11  肆尾葱  阅读(149)  评论(0)    收藏  举报