SpringBoot系列: 集成MyBatis

本文主要修改自下面博客:
http://www.ityouknow.com/springboot/2016/11/06/spring-boo-mybatis.html
http://tengj.top/2017/04/23/springboot9/
http://www.hifreud.com/2017/07/11/spring-boot-22-integrate-with-mybatis/
https://www.jianshu.com/p/2756e81d02ff

https://segmentfault.com/a/1190000004275305


SpringBoot 结合 Mybatis, 至少有下面两种写法:
1. mybatis-spring-boot-starter + SQL 的 XML 文件方式
2. mybatis-spring-boot-starter + SQL 注解方式
这里重点关注第一个写法.

==========================
pom.xml 配置
==========================
增加 mybatis boot 依赖 MyBatis-Spring-Boot-Starter, 该包将会提供如下:
1. 自动检测现有的 DataSource.
2. 将创建并注册 SqlSessionFactory 的实例,该实例使用 SqlSessionFactoryBean 将该 DataSource 作为输入进行传递.
3. 将创建并注册从 SqlSessionFactory 中获取的 SqlSessionTemplate 的实例.
4. 自动扫描您的 mappers,将它们链接到 SqlSessionTemplate 并将其注册到 Spring 上下文,以便将它们注入到您的 bean 中.
就是说,使用了该 Starter 之后,只需要定义一个 DataSource 即可(application.properties 中可配置),它会自动创建使用该 DataSource 的 SqlSessionFactoryBean 以及 SqlSessionTemplate.会自动扫描你的 Mappers,连接到 SqlSessionTemplate,并注册到 Spring 上下文中.

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

我比较喜欢将 MyBatis 的 SQL xml 文件和 Java interface 文件放在同一个目录下, 这样检查代码比较方便. 对于 java 目录, maven build 默认情况仅仅会编译打包 java 文件, xml 文件将会被忽略, 所以需要特别将这些 xml 标示为资源文件. 

<build>
    <finalName>mybatissample</finalName>
    <plugins>
        <!--optional, 加上 spring-boot-maven-plugin, 这样 jar/war 打包是可以 executable 的 -->
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>

        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <configuration>
                <verbose>true</verbose>
                <overwrite>true</overwrite>
            </configuration>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>src/main/java</directory>
            <includes>
                <include>**/*.properties</include>
                <include>**/*.xml</include>
            </includes>
            <filtering>true</filtering>
        </resource>
    </resources>
</build>


==========================
application.properties 的配置
==========================
不管是使用 Hibernate 还是 Mybatis 还是 JDBC, 默认情况下 springboot 都会自动加载 spring.datasource.* 相关配置.
spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8
spring.datasource.username = root
spring.datasource.password = root

因为我们使用 mybatis-spring-boot-starter, 上面这些 spring.datasource 属性还会用到 Mybatis 的 sqlSessionFactory 中, 而 sqlSessionFactory 会自动注入到 Mapper 中, 最终执行 SQL 时, 应用程序总是知道应该在哪个数据库中执行.

除了上面通用的数据源配置外, mybatis-spring-boot-starter 会自动读取一些 mybatis 开头的属性, 其中前三个属性比较重要, 后几个属性一般不用管.

# 重要属性:
mybatis.mapper-locations:
# mapper 配置文件的路径, 支持通配符方式.
mybatis.type-aliases-package:
# 用来扫描 Entity 的包.
mybatis.config-location:
# 指定 mybatis-config.xml 配置文件的路径, 其实所有的 mybatis 配置项都可以转移到 mybatis-config.xml 文件中, 这样 application.properties 中 mybatis 的配置项就很清爽.

# 其他属性
mybatis.type-handlers-package:
# 扫描 typeHandlers 的包
mybatis.checkConfigLocation:
# 检查配置文件是否存在
mybatis.executor-type:
# 设置执行模式, 取值有 SIMPLE/REUSE/BATCH,默认为 SIMPLE, REUSE 采用的 prepared statements 组件执行, BATCH 是批量执行模式.
configuration.map-underscore-to-camel-case:
# true 或 false, 是否开启自动驼峰命名规则 (camel case) 映射,即从经典数据库列名 A_COLUMN 到经典 Java 属性名 aColumn 的类似映射.
configuration.default-fetch-size:
# 为驱动的结果集获取数量(fetchSize)设置一个提示值,此参数只可以在查询设置中被覆盖.
configuration.default-statement-timeout:
# 设置超时时间,它决定驱动等待数据库响应的秒数.
configuration.auto-mapping-unknown-column-behavior:
# 指定发现自动映射目标未知列(或者未知属性类型)的行为.取值有 NONE/WARNING/FAILING.

下面是一个 application.properties 的配置示例.

spring.datasource.driverClassName = com.mysql.jdbc.Driver
spring.datasource.url = jdbc:mysql://localhost:3306/test1?useUnicode=true&characterEncoding=utf-8
spring.datasource.username = root
spring.datasource.password = root

mybatis.mapper-locations:classpath:mapper/*.xml
mybatis.type-aliases-package:com.springbootmybatis.mybatissample.entity
mybatis.config-location=classpath:mybatis-config.xml
 


==========================
mybatis-config.xml 文件配置
==========================
mybatis-config.xml 一般和 application.properties 放在同一个目录下. 对于 mybatis 的一些高级配置参数, 不推荐放到 application.properties 中, 最好还是放到 mybatis-config.xml 文件中. 具体配置项目说明, 可以参考博文<<mybatis 全局配置文件 mybatis-config.xml>>, 链接是 https://www.jianshu.com/p/2756e81d02ff

下面 mybatis-config.xml 文件其实相当于空文件, 已备后用.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <typeAliases>
        <!-- 下面的 type alias 其实可以省略 --> 
        <typeAlias alias="Integer" type="java.lang.Integer" />
        <typeAlias alias="Long" type="java.lang.Long" />
        <typeAlias alias="HashMap" type="java.util.HashMap" />
        <typeAlias alias="LinkedHashMap" type="java.util.LinkedHashMap" />
        <typeAlias alias="ArrayList" type="java.util.ArrayList" />
        <typeAlias alias="LinkedList" type="java.util.LinkedList" />
    </typeAliases>
    
    <mappers>
      <!--因为已经在 application.properties 中指定了 mybatis.mapper-locations 属性, 所以这里无需再指定 mapper 位置  -->
        <!-- 方式一:通过 classpath 相对路径进行指定 -->
        <!-- <mapper resource="mybatis/mapper/StudentMapper.xml"/> -->
         
        <!-- 方式二:通过文件系统的绝对路径进行指定 -->
        <!-- <mapper url="file:///D:/mybatisTest/src/mybatis/mapper/StudentMapper.xml"/> -->
         
        <!-- 方式三:通过 mapper java 接口的方式 -->
        <!-- <mapper class="mybatis.mapper.StudentMapper"/> -->
         
        <!-- 方式四:通过将指定包下面的所有 java mapper 接口进行映射的方式来实现 -->
        <!-- <package name="mybatis.mapper" />   -->    
    </mappers>
</configuration>

 

=========================
UserMapper.java
=========================

package com.springbootmybatis.mybatissample.dao;
import java.util.List;
import com.springbootmybatis.mybatissample.entity.UserEntity;

public interface UserMapper {
    List<UserEntity> getAll();
    UserEntity getOne(Long id);
    void insert(UserEntity user);
    void update(UserEntity user);
    void delete(Long id);
}

 

=========================
UserMapper.xml
=========================
将 UserMapper.xml 放到 UserMapper.java 同一目录下.

<?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.springbootmybatis.mybatissample.dao.UserMapper" >
    <resultMap id="BaseResultMap" type="com.springbootmybatis.mybatissample.entity.UserEntity" >
        <id column="id" property="id" jdbcType="BIGINT" />
        <result column="userName" property="userName" jdbcType="VARCHAR" />
        <result column="passWord" property="passWord" jdbcType="VARCHAR" />
        <result column="user_sex" property="userSex" javaType="com.springbootmybatis.mybatissample.enums.UserSexEnum"/>
        <result column="nick_name" property="nickName" jdbcType="VARCHAR" />
    </resultMap>

    <sql id="Base_Column_List" >
        id, userName, passWord, user_sex, nick_name
    </sql>

    <select id="getAll" resultMap="BaseResultMap"  >
       SELECT
       <include refid="Base_Column_List" />
       FROM users
    </select>

    <select id="getOne" parameterType="java.lang.Long" resultMap="BaseResultMap" >
        SELECT
       <include refid="Base_Column_List" />
       FROM users
       WHERE id = #{id}
    </select>

    <insert id="insert" parameterType="com.springbootmybatis.mybatissample.entity.UserEntity" >
       INSERT INTO
               users
               (userName,passWord,user_sex)
           VALUES
               (#{userName}, #{passWord}, #{userSex})
    </insert>

    <update id="update" parameterType="com.springbootmybatis.mybatissample.entity.UserEntity" >
       UPDATE
               users
       SET
           <if test="userName != null">userName = #{userName},</if>
           <if test="passWord != null">passWord = #{passWord},</if>
           nick_name = #{nickName}
       WHERE
               id = #{id}
    </update>

    <delete id="delete" parameterType="java.lang.Long" >
       DELETE FROM
                users
       WHERE
                id =#{id}
    </delete>
</mapper>


=========================
Spring 主程序
=========================

@SpringBootApplication
@MapperScan("com.springbootmybatis.mybatissample.dao")
public class App extends SpringBootServletInitializer {
    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(App.class);
    }

    public static void main(String[] args) throws Exception {
        SpringApplication.run(App.class, args);
    }
}


在启动类上增加@MapperScan 注解, 该注解的参数是 mapper java interface 所在的 package 名. 如果在主程序中省略了@MapperScan 注解, 则需要在每个 mapper java interface 上加注解 @Mapper.


=========================
UserMapperTest 程序
=========================

@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {

    @Autowired
    private UserMapper UserMapper;

    @Test
    public void testInsert() throws Exception {
        UserMapper.insert(new UserEntity("aa", "a123456", UserSexEnum.MAN));
        UserMapper.insert(new UserEntity("bb", "b123456", UserSexEnum.WOMAN));
        UserMapper.insert(new UserEntity("cc", "b123456", UserSexEnum.WOMAN));

        Assert.assertEquals(3, UserMapper.getAll().size());
    }

    @Test
    public void testQuery() throws Exception {
        List<UserEntity> users = UserMapper.getAll();
        System.out.println(users.toString());
    }
    
    @Test
    public void testUpdate() throws Exception {
        UserEntity user = UserMapper.getOne(3l);
        System.out.println(user.toString());
        user.setNickName("neo");
        UserMapper.update(user);
        Assert.assertTrue(("neo".equals(UserMapper.getOne(3l).getNickName())));
    }
}


=========================
MySQL users 表
=========================
本示例 Mysql table 的 DDL.

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键 id',
  `userName` varchar(32) DEFAULT NULL COMMENT '用户名',
  `passWord` varchar(32) DEFAULT NULL COMMENT '密码',
  `user_sex` varchar(32) DEFAULT NULL,
  `nick_name` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=28 DEFAULT CHARSET=utf8;

 

posted @ 2018-06-25 21:25  harrychinese  阅读(875)  评论(0编辑  收藏  举报