1 介绍ORM(Object-Relational Mapping)是一种将数据库和面向对象编程语言中的对象之间进行转换的技术。目的是可以使用面向对象思维进行数据库操作。
ORM 框架通常有半自动和全自动两种方式。
半自动 ORM 通常需要程序员手动编写 SQL 语句或者配置文件,将实体类和数据表进行映射,还需要手动将查询的结果集转换成实体对象。—MyBatis 全自动 ORM 则是将实体类和数据表进行自动映射,使用 API 进行数据库操作时,ORM 框架会自动执行 SQL 语句并将查询结果转换成实体对象,程序员无需再手动编写 SQL 语句和转换代码。—MyBatis-Plus MyBatis-Plus使用文档
2 案例导入依赖 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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns= "http://maven.apache.org/POM/4.0.0"
xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation= "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" >
<modelVersion> 4.0.0</modelVersion>
<parent>
<groupId> org.springframework.boot</groupId>
<artifactId> spring-boot-starter-parent</artifactId>
<version> 3.0.5</version>
</parent>
<groupId> com.atguigu</groupId>
<artifactId> springboot-starter-mybatis-plus-06</artifactId>
<version> 1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source> 17</maven.compiler.source>
<maven.compiler.target> 17</maven.compiler.target>
<project.build.sourceEncoding> UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId> org.springframework.boot</groupId>
<artifactId> spring-boot-starter</artifactId>
</dependency>
<!-- 测试环境 -->
<dependency>
<groupId> org.springframework.boot</groupId>
<artifactId> spring-boot-starter-test</artifactId>
</dependency>
<!-- mybatis-plus -->
<dependency>
<groupId> com.baomidou</groupId>
<artifactId> mybatis-plus-boot-starter</artifactId>
<version> 3.5.3.1</version>
</dependency>
<!-- 数据库相关配置启动器 -->
<dependency>
<groupId> org.springframework.boot</groupId>
<artifactId> spring-boot-starter-jdbc</artifactId>
</dependency>
<!-- druid启动器的依赖 -->
<dependency>
<groupId> com.alibaba</groupId>
<artifactId> druid-spring-boot-3-starter</artifactId>
<version> 1.2.18</version>
</dependency>
<!-- 驱动类-->
<dependency>
<groupId> mysql</groupId>
<artifactId> mysql-connector-java</artifactId>
<version> 8.0.28</version>
</dependency>
<dependency>
<groupId> org.projectlombok</groupId>
<artifactId> lombok</artifactId>
<version> 1.18.28</version>
</dependency>
</dependencies>
<!-- SpringBoot应用打包插件-->
<build>
<plugins>
<plugin>
<groupId> org.springframework.boot</groupId>
<artifactId> spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
配置文件 /**
*Springboot3条件下
*/
文件夹:META-INF.spring
文件名:org.springframework.boot.autoconfigure.AutoConfiguration.imports
内容:com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure
1
2
3
4
5
6
7
8
9
10
# 文件名: application.yaml
# 连接池配置
spring :
datasource :
type : com.alibaba.druid.pool.DruidDataSource
druid :
url : jdbc:mysql:///day01
username : root
password : root
driver-class-name : com.mysql.cj.jdbc.Driver
1
2
3
4
5
6
7
8
9
/**
*启动类
*/
@SpringBootApplication
public class MainApplication {
public static void main ( String [] args ) {
SpringApplication . run ( MainApplication . class , args );
}
}
编写Mapper包下相关接口 1
2
3
public interface UserMapper extends BaseMapper < User > {
//继承mybatis-plus提供的基础Mapper接口,自带crud方法
}
测试和使用 1
2
3
4
5
6
7
8
9
10
11
@SpringBootTest //springboot下测试环境注解
public class SampleTest {
@Autowired
private UserMapper userMapper ;
@Test
public void testSelect () {
System . out . println (( "----- selectAll method test ------" ));
List < User > userList = userMapper . selectList ( null );
userList . forEach ( System . out :: println );
}
}
3 核心功能3.1 基于Mapper接口的CRUD
1
2
3
public interface UserMapper extends BaseMapper < User > {
//User为实体类,实体类类名会转化为表名
}
1
2
3
4
5
6
7
8
9
10
11
// 根据 entity 条件,删除记录
int delete ( @Param ( Constants . WRAPPER ) Wrapper < T > wrapper );
// 删除(根据ID 批量删除)
int deleteBatchIds ( @Param ( Constants . COLLECTION ) Collection <? extends Serializable > idList );
// 根据 ID 删除
int deleteById ( Serializable id );
// 根据 columnMap 条件,删除记录
int deleteByMap ( @Param ( Constants . COLUMN_MAP ) Map < String , Object > columnMap );
1
2
3
4
5
6
// 根据 whereWrapper 条件,更新记录
int update ( @Param ( Constants . ENTITY ) T updateEntity ,
@Param ( Constants . WRAPPER ) Wrapper < T > whereWrapper );
// 根据 ID 修改 主键属性必须值
int updateById ( @Param ( Constants . ENTITY ) T entity );
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
// 根据 ID 查询
T selectById ( Serializable id );
// 根据 entity 条件,查询一条记录
T selectOne ( @Param ( Constants . WRAPPER ) Wrapper < T > queryWrapper );
// 查询(根据ID 批量查询)
List < T > selectBatchIds ( @Param ( Constants . COLLECTION ) Collection <? extends Serializable > idList );
// 根据 entity 条件,查询全部记录
List < T > selectList ( @Param ( Constants . WRAPPER ) Wrapper < T > queryWrapper );
// 查询(根据 columnMap 条件)
List < T > selectByMap ( @Param ( Constants . COLUMN_MAP ) Map < String , Object > columnMap );
// 根据 Wrapper 条件,查询全部记录
List < Map < String , Object >> selectMaps ( @Param ( Constants . WRAPPER ) Wrapper < T > queryWrapper );
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List < Object > selectObjs ( @Param ( Constants . WRAPPER ) Wrapper < T > queryWrapper );
// 根据 entity 条件,查询全部记录(并翻页)
IPage < T > selectPage ( IPage < T > page , @Param ( Constants . WRAPPER ) Wrapper < T > queryWrapper );
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage < Map < String , Object >> selectMapsPage ( IPage < T > page , @Param ( Constants . WRAPPER ) Wrapper < T > queryWrapper );
// 根据 Wrapper 条件,查询总记录数
Integer selectCount ( @Param ( Constants . WRAPPER ) Wrapper < T > queryWrapper );
3.2 基于Service接口的CRUD
对比Mapper接口CRUD区别:
service添加了批量方法 service层的方法自动添加事务 1
2
3
4
public interface UserService extends IService < User > {
//user为实体类名-->转化为表名
//IService<User>对部分方法提供了实现
}
1
2
3
4
5
6
@Service
public class UserServiceImpl extends ServiceImpl < UserMapper , User > implements UserService {
//ServiceImpl<UserMapper,User>
//UserMapper 底层调用usermapper
// user为类名
}
方法查阅文档:基于Service接口的Crud
3.3 分页查询插件
导入分页插件 1
2
3
4
5
6
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor () {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor ();
interceptor . addInnerInterceptor ( new PaginationInnerInterceptor ( DbType . MYSQL ));
return interceptor ;
}
使用分页查询 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void testPageQuery (){
//设置分页参数
Page < User > page = new Page <> ( 1 , 5 );
userMapper . selectPage ( page , null );
//获取分页数据
List < User > list = page . getRecords ();
list . forEach ( System . out :: println );
System . out . println ( "当前页:" + page . getCurrent ());
System . out . println ( "每页显示的条数:" + page . getSize ());
System . out . println ( "总记录数:" + page . getTotal ());
System . out . println ( "总页数:" + page . getPages ());
System . out . println ( "是否有上一页:" + page . hasPrevious ());
System . out . println ( "是否有下一页:" + page . hasNext ());
}
3.4 条件构造器
示例:
1
2
3
4
5
6
7
8
QueryWrapper < User > queryWrapper = new QueryWrapper <> ();
queryWrapper . eq ( "name" , "John" ); // 添加等于条件
queryWrapper . ne ( "age" , 30 ); // 添加不等于条件
queryWrapper . like ( "email" , "@gmail.com" ); // 添加模糊匹配条件
// 等价于
delete from user where name = "John" and age != 30 and email like "%@gmail.com%"
// 根据 entity 条件,删除记录
int delete ( @Param ( Constants . WRAPPER ) Wrapper < T > wrapper );
结构:
Wrapper : 条件构造抽象类,最顶端父类
AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件QueryWrapper : 查询/删除条件封装 UpdateWrapper : 修改条件封装 AbstractLambdaWrapper : 使用Lambda 语法LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper LambdaUpdateWrapper : Lambda 更新封装Wrapper 具体参数查阅文档:条件构造器手册
3.5 数据库与实体类映射注解
@TableName注解
描述:表名注解,标识实体类对应的表 使用位置:实体类 @TableId 注解
@TableId 注解
4 拓展功能4.1 逻辑删除
表添加逻辑删除字段 1
ALTER TABLE USER ADD deleted INT DEFAULT 0 ; # int 类型 1 逻辑删除 0 未逻辑删除
实体类添加逻辑删除字段 1
2
3
4
5
6
7
8
9
10
@Data
public class User {
// @TableId
private Integer id ;
private String name ;
private Integer age ;
private String email ;
private Integer deleted ;
}
指定逻辑删除字段和属性值 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/**
*注解方式
*/
@Data
public class User {
// @TableId
private Integer id ;
private String name ;
private Integer age ;
private String email ;
@TableLogic
//逻辑删除字段 int mybatis-plus下,默认 逻辑删除值为1 未逻辑删除 1
private Integer deleted ;
}
1
2
3
4
5
6
7
# 全局方式
mybatis-plus :
global-config :
db-config :
logic-delete-field : deleted # 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-value : 1 # 逻辑已删除值(默认为 1)
logic-not-delete-value : 0 # 逻辑未删除值(默认为 0)
4.2 乐观锁
添加版本号更新插件 1
2
3
4
5
6
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor () {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor ();
interceptor . addInnerInterceptor ( new OptimisticLockerInnerInterceptor ());
return interceptor ;
}
乐观锁字段添加@Version注解 1
ALTER TABLE USER ADD VERSION INT DEFAULT 1 ; # int 类型 乐观锁字段
1
2
@Version
private Integer version ;
测试 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//演示乐观锁生效场景
@Test
public void testQuick7 (){
//步骤1: 先查询,在更新 获取version数据
//同时查询两条,但是version唯一,最后更新的失败
User user = userMapper . selectById ( 5 );
User user1 = userMapper . selectById ( 5 );
user . setAge ( 20 );
user1 . setAge ( 30 );
userMapper . updateById ( user );
//乐观锁生效,失败!
userMapper . updateById ( user1 );
}
4.3 防全表更新和删除
1
2
3
4
5
6
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor () {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor ();
interceptor . addInnerInterceptor ( new BlockAttackInnerInterceptor ());
return interceptor ;
}