MybatisPlus的入门学习

1.MybatisPlus的介绍

1.1 MybatisPlus简介

MybatisPlus官方地址:MyBatis-Plus (baomidou.com)

MybatisPlus 简称 MP ,是一个Mybatis的增强工具,在Mybatis的基础上只做增强不做改变,为简化开发、提高效率而生。

使用了MybatisPlus并不意味着不使用Mybatis技术,就如官方说的:在Mybatis的基础上只做增强不做改变.

1.2 MybatisPlus的特性

  • 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
  • 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
  • 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
  • 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
  • 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
  • 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
  • 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
  • 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
  • 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
  • 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
  • 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
  • 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作

2.MybatisPlus的快速使用

2.1 导入sql

在使用MybatisPlus之前首先导入所需sql

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
-- 导出 mp 的数据库结构
CREATE DATABASE IF NOT EXISTS `mp` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
USE `mp`;

-- 导出 表 mp.address 结构
CREATE TABLE IF NOT EXISTS `address` (
`id` bigint NOT NULL AUTO_INCREMENT,
`user_id` bigint DEFAULT NULL COMMENT '用户ID',
`province` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '省',
`city` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '市',
`town` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '县/区',
`mobile` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '手机',
`street` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '详细地址',
`contact` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '联系人',
`is_default` bit(1) DEFAULT b'0' COMMENT '是否是默认 1默认 0否',
`notes` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '备注',
`deleted` bit(1) DEFAULT b'0' COMMENT '逻辑删除',
PRIMARY KEY (`id`) USING BTREE,
KEY `user_id` (`user_id`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=71 DEFAULT CHARSET=utf8mb3 ROW_FORMAT=COMPACT;

-- 正在导出表 mp.address 的数据:~11 rows (大约)

INSERT INTO `address` (`id`, `user_id`, `province`, `city`, `town`, `mobile`, `street`, `contact`, `is_default`, `notes`, `deleted`) VALUES
(59, 2, '北京', '北京', '朝阳区', '13900112222', '金燕龙办公楼', 'Rose', b'1', NULL, b'0'),
(60, 1, '北京', '北京', '朝阳区', '13700221122', '修正大厦', 'Jack', b'0', NULL, b'0'),
(61, 1, '上海', '上海', '浦东新区', '13301212233', '航头镇航头路', 'Jack', b'1', NULL, b'0'),
(63, 2, '广东', '佛山', '永春', '13301212233', '永春武馆', 'Rose', b'0', NULL, b'0'),
(64, 3, '浙江', '杭州', '拱墅区', '13567809102', '浙江大学', 'Hope', b'1', NULL, b'0'),
(65, 3, '浙江', '杭州', '拱墅区', '13967589201', '左岸花园', 'Hope', b'0', NULL, b'0'),
(66, 4, '湖北', '武汉', '汉口', '13967519202', '天天花园', 'Thomas', b'1', NULL, b'0'),
(67, 3, '浙江', '杭州', '拱墅区', '13967589201', '左岸花园', 'Hopey', b'0', NULL, b'0'),
(68, 4, '湖北', '武汉', '汉口', '13967519202', '天天花园', 'Thomas', b'1', NULL, b'0'),
(69, 3, '浙江', '杭州', '拱墅区', '13967589201', '左岸花园', 'Hopey', b'0', NULL, b'0'),
(70, 4, '湖北', '武汉', '汉口', '13967519202', '天天花园', 'Thomas', b'1', NULL, b'0');

-- 导出 表 mp.user 结构
CREATE TABLE `user` (
`id` BIGINT(19) NOT NULL AUTO_INCREMENT COMMENT '用户id',
`username` VARCHAR(50) NOT NULL COMMENT '用户名' COLLATE 'utf8_general_ci',
`password` VARCHAR(128) NOT NULL COMMENT '密码' COLLATE 'utf8_general_ci',
`phone` VARCHAR(20) NULL DEFAULT NULL COMMENT '注册手机号' COLLATE 'utf8_general_ci',
`info` JSON NOT NULL COMMENT '详细信息',
`status` INT(10) NULL DEFAULT '1' COMMENT '使用状态(1正常 2冻结)',
`balance` INT(10) NULL DEFAULT NULL COMMENT '账户余额',
`create_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `username` (`username`) USING BTREE
)
COMMENT='用户表'
COLLATE='utf8_general_ci'
ENGINE=InnoDB
ROW_FORMAT=COMPACT
AUTO_INCREMENT=5
;

-- 正在导出表 mp.user 的数据:~4 rows (大约)

INSERT INTO `user` (`id`, `username`, `password`, `phone`, `info`, `status`, `balance`, `create_time`, `update_time`) VALUES
(1, 'Jack', '123', '13900112224', '{"age": 20, "intro": "佛系青年", "gender": "male"}', 1, 1600, '2023-05-19 20:50:21', '2023-06-19 20:50:21'),
(2, 'Rose', '123', '13900112223', '{"age": 19, "intro": "青涩少女", "gender": "female"}', 1, 600, '2023-05-19 21:00:23', '2023-06-19 21:00:23'),
(3, 'Hope', '123', '13900112222', '{"age": 25, "intro": "上进青年", "gender": "male"}', 1, 100000, '2023-06-19 22:37:44', '2023-06-19 22:37:44'),
(4, 'Thomas', '123', '17701265258', '{"age": 29, "intro": "伏地魔", "gender": "male"}', 1, 800, '2023-06-19 23:44:45', '2023-06-19 23:44:45');

创建完成后使用本地的Navicat工具查询两张表看是否执行成功

使用 select * from use查询user表得到下图数据

user表查询结果

使用select * from address查询address表得到下图数据

查询address表结果

2.2 创建SpringBoot项目工程

创建SpringBoot项目工程,创建时选择所需依赖MysqllombokMybatis,单元测试依赖.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</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>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.3.1</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.11</version>
</dependency>
</dependencies>

2.2.1 准备配置

项目创建好后准备所需配置,在properties目录下创建application.yaml,并填写相关配置例如:数据库配置等

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
spring:
datasource:
# 数据库url地址
url:
# 驱动名称 mysql8.0版本后需要加入cj
driver-class-name: com.mysql.cj.jdbc.Driver
# 用户名
username:
# 密码
password: 20212501006
logging:
pattern:
dateformat: HH:mm:ss
# mybatis xml 配置文件扫描
mybatis:
mapper-locations: classpath*:mapper/*.xml

2.2.2 准备相关类以及xml配置文件

在项目根目录下创建mapper包,包中添加UserMapper接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Mapper
public interface UserMapper{

void saveUser(User user);

void deleteUser(Long id);

void updateUser(User user);

User queryUserById(@Param("id") Long id);

List<User> queryUserByIds(@Param("ids") List<Long> ids);
}

在resource目录下创建mapper包,创建UserMapper.xml文件(UserMapper.xml相对于resource的路径要与UserMapper相对于java根目录的路径相同):

这里可以看出,如果使用Mybatis进行sql语句的开发,还是需要写很多繁琐的sql,MP就是简化了这些sql的书写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
<?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.itheima.mp.mapper.UserMapper">
<insert id="saveUser" parameterType="com.itheima.mp.domain.po.User">
INSERT INTO `user` (`id`, `username`, `password`, `phone`, `info`, `balance`)
VALUES
(#{id}, #{username}, #{password}, #{phone}, #{info}, #{balance});
</insert>
<update id="updateUser" parameterType="com.itheima.mp.domain.po.User">
UPDATE `user`
<set>
<if test="username != null">
`username`=#{username}
</if>
<if test="password != null">
`password`=#{password}
</if>
<if test="phone != null">
`phone`=#{phone}
</if>
<if test="info != null">
`info`=#{info}
</if>
<if test="status != null">
`status`=#{status}
</if>
<if test="balance != null">
`balance`=#{balance}
</if>
</set>
WHERE `id`=#{id};
</update>
<delete id="deleteUser" parameterType="com.itheima.mp.domain.po.User">
DELETE FROM user WHERE id = #{id}
</delete>

<select id="queryUserById" resultType="com.itheima.mp.domain.po.User">
SELECT *
FROM user
WHERE id = #{id}
</select>

<select id="queryUserByIds" resultType="com.itheima.mp.domain.po.User">
SELECT *
FROM user
<if test="ids != null">
WHERE id IN
<foreach collection="ids" open="(" close=")" item="id" separator=",">
#{id}
</foreach>
</if>
LIMIT 10
</select>
</mapper>

项目创建完成后,导入使用所需类User类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
@Data
public class User {

/**
* 用户id
*/
private Long id;

/**
* 用户名
*/
private String username;

/**
* 密码
*/
private String password;

/**
* 注册手机号
*/
private String phone;

/**
* 详细信息
*/
private String info;

/**
* 使用状态(1正常 2冻结)
*/
private Integer status;

/**
* 账户余额
*/
private Integer balance;

/**
* 创建时间
*/
private LocalDateTime createTime;

/**
* 更新时间
*/
private LocalDateTime updateTime;
}

导入所需的类后需要在启动类上加上两个注解

  • @SpringBootApplication:SpringBoot程序启动类
  • @MapperScan() 扫描Mapper接口包

2.3 使用MybatisPlus

2.3.1 引入MybatisPlus依赖

MyBatisPlus官方提供了starter,其中集成了Mybatis和MybatisPlus的所有功能,并且实现了自动装配效果。因此我们可以用MybatisPlus的starter代替Mybatis的starter.

注释掉pom文件中的mybatis依赖,导入MybatisPlus依赖

1
2
3
4
5
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>

2.3.2 定义Mapper

在之前写的Mapper接口上继承BaseMapper并指定泛型为操作的实体类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 需要继承BaseMapper 并 指定泛型为操作的类 这里是User类
@Mapper
public interface UserMapper extends BaseMapper<User> {

void saveUser(User user);

void deleteUser(Long id);

void updateUser(User user);

User queryUserById(@Param("id") Long id);

List<User> queryUserByIds(@Param("ids") List<Long> ids);
}

2.3.3 测试mapper

2.3.3.1 测试Mybatis方法

由于MybatisPlus对Mybatis是无侵入的,因此即使继承了BaseMapper,自己在Mapper中定义的接口依然可以调用

编写测试类以及测试方法testSelectById()

1
2
3
4
5
@Test
void testSelectById() {
User user = userMapper.queryUserById(4L);
System.out.println("user = " + user);
}

这里会调用自己在xml文件中写的方法

查看结果,查询成功

查询成功

虽然成功了,但是sql十分复杂

2.3.3.2 测试MybatisPlus方法

为简化Mybatis开发的复杂性,MybatisPlus简化了sql的书写,不需要开发者自己书写单表的部分sql

删除xml中的sql语句以及mapper接口中的所有方法(这里只是删除了简单但是繁琐的sql,如果有特殊需要还是需要自己定义方法并实现)

1
2
3
4
5
<?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.itheima.mp.mapper.UserMapper">

</mapper>
1
2
3
@Mapper
public interface UserMapper extends BaseMapper<User> {
}

在测试方法中使用MybatisPlus的方法进行测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Test
void testInsert() {
User user = new User();
user.setId(5L);
user.setUsername("Lucy");
user.setPassword("123");
user.setPhone("18688990011");
user.setBalance(200);
user.setInfo("{\"age\": 24, \"intro\": \"英文老师\", \"gender\": \"female\"}");
user.setCreateTime(LocalDateTime.now());
user.setUpdateTime(LocalDateTime.now());
userMapper.insert(user);
}

@Test
void testSelectById() {
User user = userMapper.selectById(4L);
System.out.println("user = " + user);
}

@Test
void testUpdateById() {
User user = new User();
user.setId(5L);
user.setBalance(20000);
userMapper.updateById(user);
}

@Test
void testDeleteUser() {
userMapper.deleteById(5L);
}

测试通过

2.4 MybatisPlus API总结

MybatisPlus API总结

3.Mybatis常用注解

MyBatisPlus通过扫描实体类,并基于反射获取实体类信息作为数据库表信息。这里体现在在定义mapper时需继承BaseMapper并指定泛型为所操作的实体类.

因此在使用MybatisPlus进行开发的时候有些规定:

  • 类名驼峰转下划线作为表明

例如实体类的名称为User,则对应的表名为User;实体类的名称为UserInfo,则对应的表名为user_info(数据库表名不区分大小写)

  • 名为id的字段作为主键
  • 变量名驼峰转下划线作为表的字段名

例如实体类中的属性createTime对应着表中的create_time字段,单字段的则属性名和字段名相同,例如username,phone,info等

使用这种方法,MybatisPlus则可以通过反射知道实体类与表的相关联系

如果定义类中的属性名和MP规定的不一致怎么办?

通过注解自定义配置

3.1 注解介绍

MybatisPlus中比较常用的几个注解如下:

  • @TableName:用来指定表名
  • @TableId:用来指定表中的主键字段信息
  • @TableField:用来指定表中的普通字段信息

例如:

  • 表的名称为tb_user,但是实体类的名称为User,则出现了不符合MP规范的情况,则可以使用@TableName(value=”tb_user”)来进行匹配
  • 表的主键为id,实体类的属性名叫userId,则出现了不符合规范的情况,使用@TableId(value = “id”)(如果一致则不需要使用注解)

在数据库的表中,主键常常具有类型,例如:自增等。MybatisPlus对此也有对应的属性来指定主键的类型 @TableId(value=””,type=”IdType.AUTO”)

  • AUTO : 数据库自增长
  • INPUT:通过set方法自行输入
  • ASSIGN_ID:分配id,接口IdentifierGenerator的方法nextId来生成id,默认实现类为DefaultifierGenerator雪花算法

这里需要注意的是表中一定要有主键,不然后续无法使用MybatisPlus根据主键进行增删改查操作

如果类中的属性名和表的字段名没有按照MP的规范,则需要使用@TableField来进行匹配

  • 例如类中的属性名为name,但是表中的字段名为username,则需要使用注解匹配 @TableField(“username”)
  • 如果类中的属性名为is开头的布尔类型,属性名为isMarried,字段名为is_married则也需要使用@TableField(“is_married”)
  • 属性名和数据库的关键字冲突,则也需要使用@TableField(“ order“)注解
  • 如果类中的属性不为表中的字段,则需要使用@TableField(exist = false)

以上注解不是MP的全部注解,只是部分,如果了解更多注解,可以去官网查看

4.Mybatis配置项

1
2
3
4
5
6
7
8
9
10
11
12
13
# MybatisPlus 下面的配置大多数都是默认值 除了包扫描
mybatis-plus:
type-aliases-package: com.itheima.mp.domain.po # 别名扫描包
mapper-locations: "classpath*:/mapper/**/*.xml" # Mapper.xml文件地址,默认值
configuration:
map-underscore-to-camel-case: true # 是否开启下划线和驼峰的映射
cache-enabled: false # 是否开启二级缓存
global-config:
db-config:
id-type: assign_id # id为雪花算法生成
# 例如根据id更新User类时,传递的是User实体类,User实体类中只有Id和username是非空的 因此会根据id更改username
update-strategy: not_null # 更新策略:只更新非空字段

如果配置类记不清楚可以去官网查询 MyBatis-Plus (baomidou.com),或者根据yaml文件的自动提示书写

5.总结

使用MybatisPlus的步骤:

  1. 引入MybatisPlus的依赖替代Mybatis依赖
  2. 自定义Mapper并继承BaseMapper指定泛型
  3. 在实体类添加注解声明表信息以及启动类上扫描mapper
  4. 在application.yaml中填写配置信息例如包扫描,驼峰命名,起别名等
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights ©本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处! yang
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信