MyBatisPlus概述

需要的基础:把我的MyBatis、Spring、SpringMVC就可以学习这个了! 为什么要学习它呢?MyBatisPlus可以节省我们大量工作时间,所有的CRUD代码它都可以自动化完成! JPA 、 tk-mapper、MyBatisPlus
偷懒的!

简介

是什么? MyBatis 本来就是简化 JDBC 操作的! 官网:https://mp.baomidou.com/ MyBatis Plus,简化 MyBatis !
在这里插入图片描述

快速搭建

导入依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<!-- mybatis-plus -->
<!-- mybatis-plus 是自己开发,并非官方的! -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</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>

mapper继承BaseMapper

之前的Mybatis,需要写mapper接口,还需要写它的实现类,实现类中药写所有的CRUD方法,以下为Mybatis:
在这里插入图片描述
在这里插入图片描述

现在的Mybatis-plus,无须繁琐的CRUD方法,继承了BaseMapper,就已经完成了简单增删改查的方法
在这里插入图片描述
下面进行CRUD测试:

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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package com.mybatisplus.example;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mybatisplus.example.mapper.UserMapper;
import com.mybatisplus.example.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

@SpringBootTest
class ExampleApplicationTests {
@Autowired
UserMapper userMapper;

@Test
void contextLoads() {
List<User> userList = userMapper.selectList(null);
userList.forEach(System.out::println);
}

@Test
public void testInsert() throws ParseException {
User user = new User();
user.setBirth("1997-10-14");
user.setGender("男");
user.setName("小马先生");
user.setRole("admin");
user.setSuggestion("所有的不平凡都来自平凡");
System.out.println(user);
int insert = userMapper.insert(user);
System.out.println(insert);
}

@Test
public void testUpdate() throws ParseException {
User user = userMapper.selectById(28);
// user.setBirth("1996-10-1");
user.setSuggestion("所有的不平凡都来自平凡");
userMapper.updateById(user);
}

@Test // 测试乐观锁 成功案例
public void testOptimisticLocker(){
//1、查询用户信息
User user = userMapper.selectById(1);
//2、修改用户信息
user.setName("刘邦");
user.setGender("女");
//3、执行更新操作
userMapper.updateById(user);
}

@Test // 测试乐观锁 失败案例---多线程下
public void testOptimisticLocker2(){

// 线程1

User user = userMapper.selectById(1);
user.setName("刘邦");
user.setGender("女");
//模拟另一个线程执行了插队操作
User user2 = userMapper.selectById(1);
user2.setName("刘备");
user2.setGender("男");
userMapper.updateById(user2);

//自旋锁来多次尝试提交
userMapper.updateById(user);// 如果没有乐观锁就会覆盖插队线程的值!
}


@Test
public void testSelectByid(){
User user = userMapper.selectById(1);
System.out.println(user);
}

@Test //批量查询固定id 集合传入
public void testSelectBuBatchId(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2));
users.forEach(System.out::println);
System.out.println("-------------");
// System.out.println(users.get(1).getName());

}

@Test //用map来指定字段查询
public void testSelectBuBatchId2(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","徐淑高");
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);

}

@Test //测试分页查询
public void testPage(){
Page<User> page = new Page<>(1,5); //current当前页 size大小
userMapper.selectPage(page,null); //wrapper是高级查询

page.getRecords().forEach(System.out::println);

}

@Test
public void testDeleteById(){
userMapper.deleteById(28);
}

@Test
public void testDeleteMap(){
HashMap<String, Object> map = new HashMap<>();
map.put("name","小马先生");
userMapper.deleteByMap(map);
}




}

注意:

  • 实体类User中,可以对该实体类进行表名绑定(如果表名和实体类名不一致时)

  • 对于类建立的Getter、Setter、有参无参可以通过lombok注解来简化
    在这里插入图片描述
    在这里插入图片描述

  • 阿里的数据库构建规范中,需要给每个表至少拥有create_time、update_time字段,这个可以通过写一个MyMetaObjectHandler类来实现官方给的MetaObjectHandler接口,覆盖重写插入时候的填充策略、更新时候的填充策略,记得用@Component丢进spring中,即可保证在插入时候、更新时候,create_time、update_time字段同步更新,无须手动写时间
    在这里插入图片描述

  • 乐观锁和分页,按照官网进行配置即可,乐观锁需要加一个version字段,在操作数据库时会判断version版本

乐观锁 : 故名思意十分乐观,它总是认为不会出现问题,无论干什么不去上锁!如果出现了问题, 再次更新值测试
悲观锁:故名思意十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!

我们这里主要讲解 乐观锁机制! 乐观锁实现方式:

  1. 取出记录时,获取当前 version
  2. 更新时,带上这个version
  3. 执行更新时, set version = newVersion where version = oldVersion 如果version不对,就更新失败

乐观锁和分页插件对应的config:

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
package com.mybatisplus.example.config;

import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@MapperScan("com.mybatisplus.example.mapper")
@EnableTransactionManagement
@Configuration
public class MyBatisPlusConfig {

//------------注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}

//----------分页插件
// 分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}