Spring Boot (七): Mybatis极简配置

1. 前言

ORM 框架的目的是简化编程中的数据库操作,经过这么多年的发展,基本上活到现在的就剩下两家了,一个是宣称可以不用写 SQL 的 Hibernate ,一个是对 SQL 非常友好的 Mybaties ,,两者各有特点,在企业级系统开发中可以根据需求灵活使用。发现一个有趣的现象:传统企业大都喜欢使用 Hibernate ,互联网行业通常使用 Mybatis 。

Hibernate 特点就是所有的 SQL 都用 Java 代码来生成,不用跳出程序去写(看) SQL ,有着编程的完整性,发展到最顶端就是 Spring Data Jpa 这种模式了,基本上根据方法名就可以生成对应的 SQL 了,有不太了解的可以看笔者的前两篇文章 Spring Boot (三): ORM 框架 JPA 与连接池 HikariSpring Boot (六): 为 JPA 插上翅膀的 QueryDSL

Mybatis 初期使用比较麻烦,需要各种配置文件、实体类、Dao 层映射关联、还有一大推其它配置。当然 Mybatis 也发现了这种弊端,初期开发了 generator 可以根据表结果自动生产实体类、配置文件和 Dao 层代码,可以减轻一部分开发量;后期也进行了大量的优化可以使用注解了,自动管理 Dao 层和配置文件等,发展到最顶端就是今天要讲的这种模式了,mybatis-spring-boot-starter 就是 Spring Boot + Mybatis 可以完全注解不用配置文件,也可以简单配置轻松上手。

2. 工程实战

首先创建父工程 spring-boot-mybatis,引入全局依赖包,如下:

代码清单:spring-boot-mybatis/pom.xml


<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.0</version>
</dependency> <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
  • mybatis-spring-boot-starter :目前最新版本为 2.1.0

2.1 极简 xml 版

创建子工程 spring-boot-mybatis-xml

2.1.1 配置文件

application.yml 配置文件如下:

代码清单:spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/application.yml


server:
port: 8080
spring:
application:
name: spring-boot-mybatis-xml
datasource:
url: jdbc:mysql://localhost:3306/test?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.zaxxer.hikari.HikariDataSource
hikari:
auto-commit: true
minimum-idle: 2
idle-timeout: 60000
connection-timeout: 30000
max-lifetime: 1800000
pool-name: DatebookHikariCP
maximum-pool-size: 5
mybatis:
type-aliases-package: com.springboot.springbootmybatisxml.model
config-location: classpath:mybatis/mybatis-config.xml
mapper-locations: classpath:mybatis/mapper/*.xml
  • 这里使用 hikari 作为数据库连接池
  • Spring Boot 会自动加载 spring.datasource.* 相关配置,数据源会自动注入到 sqlSessionFactory 中, sqlSessionFactory 会自动注入到 Mapper 中。
  • 这里需要指定基础配置文件和实体类映射文件的地址

mybatis-config.xml 配置文件如下:

代码清单:spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mybatis-config.xml


<configuration>
<typeAliases>
<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>
</configuration>

2.1.2 Mapper 映射文件

代码清单:spring-boot-mybatis/spring-boot-mybatis-xml/src/main/resources/mybatis/mapper/UserMapper.xml


<mapper namespace="com.springboot.springbootmybatisxml.mapper.UserMapper" >

    <resultMap id="BaseResultMap" type="com.springboot.springbootmybatisxml.model.User" >
<id column="id" property="id" jdbcType="VARCHAR" />
<result column="nick_name" property="nickName" jdbcType="VARCHAR" />
<result column="age" property="age" jdbcType="INTEGER" />
<result column="create_date" property="createDate" jdbcType="TIME"/>
</resultMap> <sql id="Base_Column_List" >
id, nick_name, age, create_date
</sql> <select id="getAll" resultMap="BaseResultMap" >
SELECT
<include refid="Base_Column_List" />
FROM user
</select> <select id="getUser" parameterType="java.lang.String" resultMap="BaseResultMap" >
SELECT
<include refid="Base_Column_List" />
FROM
user
WHERE id = #{id}
</select> <insert id="insertUser" parameterType="com.springboot.springbootmybatisxml.model.User">
<selectKey keyProperty="id" resultType="java.lang.String" order="BEFORE">
select uuid() as id from dual
</selectKey>
INSERT INTO
user
(id, nick_name, age, create_date)
VALUES
(#{id}, #{nickName}, #{age}, #{createDate})
</insert> <update id="updateUser" parameterType="com.springboot.springbootmybatisxml.model.User">
UPDATE
user
SET
<if test="nickName != null">nick_name = #{nickName},</if>
<if test="age != null">age = #{age},</if>
<if test="createDate != null">create_date = #{createDate}</if>
WHERE
id = #{id}
</update> <delete id="deleteUser" parameterType="java.lang.String">
DELETE FROM
user
WHERE
id = #{id}
</delete> </mapper>
  • namespace :需配置对应的接口
  • 实现了简单的 CRUD 操作
  • 新增数据时选用 UUID 作为主键
  • 动态条件可使用 <if> 标签作判断

2.1.3 Mapper 层代码

代码清单:spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/springboot/springbootmybatisxml/mapper/UserMapper.java


public interface UserMapper {

    List<User> getAll();

    User getUser(String id);

    Long insertUser(User user);

    Long updateUser(User user);

    Long deleteUser(String id);
}
  • 这里仅需定义接口方法, mybaties 会自动帮我们调用 xml 映射文件中的代码。

2.1.4 启动主类

代码清单:spring-boot-mybatis/spring-boot-mybatis-xml/src/main/java/com/springboot/springbootmybatisxml/SpringBootMybatisXmlApplication.java


@SpringBootApplication
@MapperScan("com.springboot.springbootmybatisxml.mapper")
public class SpringBootMybatisXmlApplication { public static void main(String[] args) {
SpringApplication.run(SpringBootMybatisXmlApplication.class, args);
} }
  • 在启动主类上配置 @MapperScan 或者直接在 Mapper 类上增加注解 @Mapper ,两种方法起到的结果是一样的。不过建议选择在启动主类上配置 @MapperScan ,不然在每个 Mapper 类上加注解也麻烦,还容易漏加。

2.2 无配置文件注解版

2.2.1 配置

配置文件 application.yml 如下:

代码清单:


mybatis:
type-aliases-package: com.springboot.springbootmybatisannotation.model
  • 剩余部分和上面一致, mybatis 的配置仅需配置这一条足够

2.2.2 Mapper 类

注解版的核心就是这个类,所有的 SQL 都在这个类里面,代码如下:

代码清单:


public interface UserMapper {

    @Select("select * from user")
@Results({
@Result(property = "id", column = "id"),
@Result(property = "nickName", column = "nick_name"),
@Result(property = "age", column = "age"),
@Result(property = "createDate", column = "create_date")
})
List<User> getAll(); @Select("SELECT * FROM user WHERE id = #{id}")
@Results({
@Result(property = "nickName", column = "nick_name")
})
User getUser(String id); @Insert("INSERT INTO user(id, nick_name, age, create_date) VALUES(#{id}, #{nickName}, #{age}, #{createDate})")
@SelectKey(keyProperty = "id", resultType = String.class, before = true, statement = "select uuid() as id from dual")
Long insertUser(User user); @Update("UPDATE user SET nick_name = #{nickName}, age = #{age} WHERE create_date = #{createDate}")
Long updateUser(User user); @Delete("DELETE FROM user WHERE id = #{id}")
Long deleteUser(String id);
}
  • @Select 是查询类的注解,所有的查询均使用这个
  • @Result 修饰返回的结果集,关联实体类属性和数据库字段一一对应,如果实体类属性和数据库属性名保持一致,就不需要这个属性来修饰。
  • @Insert 插入数据库使用,直接传入实体类会自动解析属性到对应的值
  • @Update 负责修改,也可以直接传入对象
  • @delete 负责删除

注意:使用 # 符号和 $ 符号是不同的

#{}

使用 #{} 意味着使用的预编译的语句,即在使用 jdbc 时的 preparedStatement , sql 语句中如果存在参数则会使用 ? 作占位符。

${}

使用 ${} 时的sql不会当做字符串处理,是什么就是什么,如上边的语句:select * from table1 where id=${id} 在调用这个语句时控制台打印的为:select * from table1 where id=2 ,假设传的参数值为2

从上边的介绍可以看出这两种方式的区别,最好是能用 #{} 则用它,可以防止 sql 注入,且是预编译的,在需要原样输出时才使用 ${}

3. 小结

两种模式各有特点,注解版适合简单快速的模式,其实像现在流行的这种微服务模式,一个微服务就会对应一个自已的数据库,多表连接查询的需求会大大的降低,会越来越适合这种模式。另外插一句, Hibernate 对单表的支持是非常好的,为什么不选用 Spring Boot JPA + QueryDSL呢?

Xml 配置模式比较适合大型项目,可以酣畅淋漓的写 SQL ,可以灵活的动态生成 SQL ,方便调整 SQL 。

4. 示例代码

示例代码-Github

示例代码-Gitee

5. 参考

http://www.ityouknow.com/springboot/2016/11/06/spring-boot-mybatis.html

Spring Boot (七): Mybatis极简配置的更多相关文章

  1. spring boot(七)mybatis多数据源解决方案

    说起多数据源,一般都来解决那些问题呢,主从模式或者业务比较复杂需要连接不同的分库来支持业务.我们项目是后者的模式,网上找了很多,大都是根据jpa来做多数据源解决方案,要不就是老的spring多数据源解 ...

  2. 太妙了!Spring boot 整合 Mybatis Druid,还能配置监控?

    Spring boot 整合 Mybatis Druid并配置监控 添加依赖 <!--druid--> <dependency> <groupId>com.alib ...

  3. Spring Boot 整合 Mybatis 实现 Druid 多数据源详解

    摘要: 原创出处:www.bysocket.com 泥瓦匠BYSocket 希望转载,保留摘要,谢谢! “清醒时做事,糊涂时跑步,大怒时睡觉,独处时思考” 本文提纲一.多数据源的应用场景二.运行 sp ...

  4. Spring Boot 2.x 多数据源配置之 MyBatis 篇

    场景假设:现有电商业务,商品和库存分别放在不同的库 配置数据库连接 app: datasource: first: driver-class-name: com.mysql.cj.jdbc.Drive ...

  5. spring boot集成mybatis(3) - mybatis generator 配置

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  6. spring boot + druid + mybatis + atomikos 多数据源配置 并支持分布式事务

    文章目录 一.综述 1.1 项目说明 1.2 项目结构 二.配置多数据源并支持分布式事务 2.1 导入基本依赖 2.2 在yml中配置多数据源信息 2.3 进行多数据源的配置 三.整合结果测试 3.1 ...

  7. Spring Boot 整合MyBatis(1)

    这篇文章介绍如何在Spring boot中整合Mybatis,其中sql语句采用注解的方式插入.后续文章将会介绍,如何使用xml方式. SSM SSH框架已经满足轻量级这个需求了,但是对于开发人员而言 ...

  8. spring boot集成mybatis(1)

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

  9. spring boot集成mybatis(2) - 使用pagehelper实现分页

    Spring Boot 集成教程 Spring Boot 介绍 Spring Boot 开发环境搭建(Eclipse) Spring Boot Hello World (restful接口)例子 sp ...

随机推荐

  1. CocosBuilder 学习笔记(3) AnimationManager 与 ccbi 文件解析

    [CocosBuilder]学习笔记目录 1. 相关的类 先介绍和AnimationManager相关的几个类: CCBSequence 时间线.有成员duration(时间线时间,默认10秒).na ...

  2. ES5新增数组的一些方法

    1.Array.indexof(value1,value2) Tip:用于返回某个数组或字符串中规定字符或者字符串的位置. (1)当Array.indexof(value1);里面只有一个值的时候,表 ...

  3. springboot--事务的使用

    @Transactional原理 事务是一些sql语句对数据库操作的集合,因此如果在一个Java方法里涉及了对数据库的操作,业务需要的话我们就可以考虑把这些操作作为一个事务.通过在方法上加个@Tran ...

  4. HDU2222Keywords Search AC_自动机

    http://blog.csdn.net/niushuai666/article/details/7002823 #include <iostream> #include <cstd ...

  5. HDU 4607 Park Visit 树的最大直径

    题意: 莱克尔和她的朋友到公园玩,公园很大也很漂亮.公园包含n个景点通过n-1条边相连.克莱尔太累了,所以不能去参观所有点景点. 经过深思熟虑,她决定只访问其中的k个景点.她拿出地图发现所有景点的入口 ...

  6. codeforces 830 B. Cards Sorting(线段树)

    题目链接:http://codeforces.com/contest/830/problem/B 题解:其实这题就是求当前大小的数到下一个大小的数直接有多少个数,这时候可以利用数据结构来查询它们之间有 ...

  7. 染色 Wannafly挑战赛20 A 思维

    链接:https://www.nowcoder.com/acm/contest/133/A来源:牛客网 现在有一棵被Samsara-Karma染了k种颜色的树,每种颜色有着不同的价值 Applese觉 ...

  8. hdu5491 The Next 模拟

    Let LL denote the number of 1s in integer DD’s binary representation. Given two integers S1S1 and S2 ...

  9. 洛谷 P1666 前缀单词 题解

    题意:给n个单词,如果单词a为单词b的前缀则a,b不能共存,问能共存的集合数(包括空集) 一道dp题,排序后判断,f[i][j]表示i和j是否能共存,f[i][j]=1表示能共存,初始化dp[i]=1 ...

  10. Codeforce Round #574(Div.2)

                                                                                                        ...