【MyBatis源码学习】MyBatis与Spring整合


前言

目前大部分项目中运用MyBatis均与Spring有关,尤其是Spring Boot大行其道,普通程序员基本上可以无缝的完成一个简单的CRUD项目。通过前面对于MyBatis 源码的学习,我已经对其了(一)如(脸)指(懵)掌(逼),本章我们来玩玩MyBatis与Spring的结合以及它们的融合原理。

一、什么是Mybatis-Spring

一句话:将 MyBatis 代码无缝地整合到 Spring 中。集成过程中的增强处理主要体现在以下几个方面:

  • Spring 将会加载必要的 MyBatis 工厂类和 session 类
  • 提供一个简单的方式来注入 MyBatis 数据映射器和 SqlSession 到业务层的 bean 中
  • 方便集成Spring事务
  • 翻译 MyBatis 的异常到 Spring 的 DataAccessException 异常(数据访问异常)中

二、关键配置类

1.SqlSessionFactoryBean

SqlSessionFactoryBean作用:用于创建SqlSessionFactory。关键参数有:

  • dataSource :必填。用于配置数据源,必须通过这个属性配置数据源。
  • mapperLocations : 配置 SqlSessionFactoryBean 扫描*mapper.xml映射文件的路径。
  • configLocation :用于配置mybatis-config.xml的路径,除了数据源外,对MyBatis的各种配直仍然可以通过这种方式进行,并且配置MyBatis settings 时只能使用这种方式。但配置文件中任意环境,数据源和 MyBatis 的事务管理器都会被忽略;
  • typeAliasesPackage : 配置包中类的别名,配置后,包中的类在 XML 映射文件中使用时可以省略包名部分,直接使用类名。这个配置不支持Ant风格的路径,当需要配置多个包路径时可以使用分号或逗号进行分隔.

2.MapperScannerConfigurer

作用:自动扫描所有的 Mapper 接口,使用时可以直接注入接口。
关键参数:

  • basePackage :用于配置基本的包路径。可以使用分号或逗号作为分隔符设置多于一个的包路径,每个映射器将会在指定的包路径中递归地被搜索到 。
  • annotationClass :用于过滤被扫描的接口,如果设置了该属性,那么 MyBatis 的接口只有包含该注解才会被扫描进去。

三、MyBatis与Spring融合实战

1.依赖

<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
       <dependency>
           <groupId>mysql</groupId>
           <artifactId>mysql-connector-java</artifactId>
           <version>5.1.42</version>
       </dependency>

       <dependency>
           <groupId>org.mybatis</groupId>
           <artifactId>mybatis</artifactId>
           <version>3.5.0</version>
       </dependency>
       <dependency>
           <groupId>org.mybatis</groupId>
           <artifactId>mybatis-spring</artifactId>
           <version>1.3.3</version>
       </dependency>

	<!-- 数据库连接池 -->
	<dependency>
		<groupId>com.alibaba</groupId>
		<artifactId>druid</artifactId>
		<version>1.0.20</version>
	</dependency>

       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-core</artifactId>
           <version>${spring.version}</version>
       </dependency>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-context</artifactId>
           <version>${spring.version}</version>
       </dependency>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-beans</artifactId>
           <version>${spring.version}</version>
       </dependency>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-jdbc</artifactId>
           <version>${spring.version}</version>
       </dependency>
       <dependency>
           <groupId>org.springframework</groupId>
           <artifactId>spring-test</artifactId>
           <version>${spring.version}</version>
       </dependency>

其中spring.version为4.3.3.RELEASE。

2.Spring配置文件

本项目中的spring配置文件名为applicationContext.xml,主要用于配置:

  • 数据源
  • sqlSessionFactory
  • MapperScannerConfigurer
<context:property-placeholder location="classpath:db.properties" ignore-unresolvable="true" />
<context:component-scan base-package="com.*"/>
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" init-method="init" destroy-method="close">
	<!-- 基本属性 url、user、password -->
	<property name="driverClassName" value="${jdbc_driver}" />
	<property name="url" value="${jdbc_url}" />
	<property name="username" value="${jdbc_username}" />
	<property name="password" value="${jdbc_password}" />
	<!-- 配置初始化大小、最小、最大 -->
	<property name="initialSize" value="1" />
	<property name="minIdle" value="1" />
	<property name="maxActive" value="20" />
	<!-- 配置获取连接等待超时的时间 -->
	<property name="maxWait" value="60000" />
	<!-- 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 -->
	<property name="timeBetweenEvictionRunsMillis" value="60000" />
	<!-- 配置一个连接在池中最小生存的时间,单位是毫秒 -->
	<property name="minEvictableIdleTimeMillis" value="300000" />
	<property name="validationQuery" value="SELECT 'x'" />
	<property name="testWhileIdle" value="true" />
	<property name="testOnBorrow" value="false" />
	<property name="testOnReturn" value="false" />
	<!-- 打开PSCache,并且指定每个连接上PSCache的大小 -->
	<property name="poolPreparedStatements" value="true" />
	<property name="maxPoolPreparedStatementPerConnectionSize" value="20" />
	<!-- 配置监控统计拦截的filters -->
	<property name="filters" value="stat" />
</bean>

<!-- spring和MyBatis完美整合,不需要mybatis的配置映射文件 -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
	<property name="dataSource" ref="dataSource" />
	<property name="typeAliasesPackage" value="com.enjoylearning.mybatis.entity" />
	<property name="mapperLocations" value="classpath:sqlmapper/*.xml" />
</bean>

<!-- DAO接口所在包名,Spring会自动查找其下的类 -->
	 <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
	<property name="basePackage" value="com.enjoylearning.mybatis.mapper" />
</bean>

<!-- (事务管理)transaction manager -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
	<qualifier value="transactionManager" />
</bean>

<tx:annotation-driven transaction-manager="transactionManager" />

3.Mybatis配置文件

文件名为mybatis-config.xml,注意该文件除了settings必须配置在里面外,其他都可以在spring配置文件中配置。

<settings>
	<setting name="mapUnderscoreToCamelCase" value="true" />
</settings>

<!-- 别名定义 -->
<typeAliases>
	<package name="com.enjoylearning.mybatis.entity"/>
</typeAliases>

4.mapper

还是以UserInfoMapper.xml为例,文件内容如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.enjoylearning.mybatis.mapper.UserInfoMapper">
    <resultMap id="BaseResultMap" type="com.enjoylearning.mybatis.entity.UserInfo">
        <id column="id" property="id" jdbcType="VARCHAR"/>
        <result column="username" property="username" jdbcType="VARCHAR"/>
        <result column="password" property="password" jdbcType="VARCHAR"/>
        <result column="openid" property="openid" jdbcType="VARCHAR"/>
        <result column="role" property="role" jdbcType="BIT"/>
        <result column="create_time" property="createTime" jdbcType="TIMESTAMP"/>
        <result column="update_time" property="updateTime" jdbcType="TIMESTAMP"/>
    </resultMap>
    <sql id="Base_Column_List">
        id, username, password, openid, role, create_time, update_time
    </sql>
    <select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.String">
        select
        <include refid="Base_Column_List"/>
        from user_info
        where id = #{id,jdbcType=VARCHAR}
    </select>
</mapper>

对应dao:

public interface UserInfoMapper {
    UserInfo selectByPrimaryKey(String id);
}

po:

public class UserInfo {
    private String id;
    private String username;
    private String password;
    private String openid;
    private Boolean role;
    private Date createTime;
    private Date updateTime;
	//省略getter、setter
}

5.测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class MybatisSpringTest {
	@Autowired
    private UserInfoMapper userInfoMapper;

    @Test
    public void test_selectByPrimaryKey() {
        UserInfo userInfo= userInfoMapper.selectByPrimaryKey(1);
        System.out.println(userInfo.toString());
    }
}

四、Mybatis与SpringBoot融合实战

1.依赖

<dependency>
	<groupId>org.mybatis.spring.boot</groupId>
	<artifactId>mybatis-spring-boot-starter</artifactId>
	<version>2.0.1</version>
</dependency>

<!-- mysql驱动 -->
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.18</version>
      </dependency>
      
<!-- 单元测试相关依赖 -->
      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>4.12</version>
          <scope>test</scope>
      </dependency>

      <dependency>
          <groupId>org.projectlombok</groupId>
          <artifactId>lombok</artifactId>
          <version>1.18.18</version>
          <optional>true</optional>
      </dependency>
      
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-test</artifactId>
	<scope>test</scope>
</dependency>

2.application.yml

#DataSource config 配置数据源信息
spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/springcloudsell?useUnicode=true&characterEncoding=utf-8
    username: root
    password: root
# 配置MyBatis的配置文件地址和MyBatis的映射文件地址
mybatis:
  mapper-locations: classpath*:sqlmapper/*.xml
  configuration:
    # 关闭二级缓存
    cache-enabled: false
    map-underscore-to-camel-case: true

logging:
  level:
    root: info
    org.springframework.web: info
    #    打印sql
    com.enjoylearning.mybatis.mapper: DEBUG
server:
  port: 8081

3.启动类

为了不用在每个mapper.java中添加@Mapper注解,可以统一在启动类加上@MapperScan注解。

@SpringBootApplication
@MapperScan(basePackages = "com.enjoylearning.mybatis.dao")
@Slf4j
public class MybatisSpringbootDemoApplication {

    public static void main(String[] args) {
        log.info("------------------MybatisSpringbootDemoApplication-----------start ");
        SpringApplication.run(MybatisSpringbootDemoApplication.class, args);
        log.info("------------------MybatisSpringbootDemoApplication------------end ");
    }

}

4.测试类

@RunWith(SpringRunner.class)
@SpringBootTest(classes = MybatisSpringbootDemoApplication.class)
public class StudentMapperTest{
	@Autowired
	private UserInfoMapper userInfoMapper;
	@Test
	public void selectStudentById() throws Exception {
	    UserInfo userInfo = userInfoMapper.selectByPrimaryKey("1");
	    System.out.println("---->查询结果为={}" + userInfo);
	}
}

文章作者: Kezade
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 Kezade !
评论
  目录