左璞凡的博客

日出之美便在于它脱胎于最深的黑暗

0%

MyBatis-Plus

[MyBatis-Plus]

简称MP,是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率。

标准数据层开发

image-20231015201356792

lombok

可简化POJO是实体类开发

MP分页查询功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//1 设置分页拦截器作为bean
public class Mpcongfig {
@Bean
publice MybatisPlusInterceptor pageInterceptor() {
MybatisPlusIntercepter interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor());
return interceptor
}
}

//2 执行分页查询
IPage page = new Page(2,3);
userDao.selectPage(page, null);
....

//开启日志
//在配置文件中
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

条件查询

格式

常规格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@SpringBootTest
class Mybatisplus02DqlApplicationTests {

@Autowired
private UserDao userDao;

@Test
void testGetAll(){
QueryWrapper qw = new QueryWrapper();
qw.lt("age",65);
qw.ge("age",18);
List<User> userList = userDao.selectList(qw);
System.out.println(userList);
}
}

链式编程格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@SpringBootTest
class Mybatisplus02DqlApplicationTests {

@Autowired
private UserDao userDao;
@Test
void testGetAll(){
QueryWrapper qw = new QueryWrapper();
qw.lt("age",65).or().ge("age",18);
//or()就相当于我们sql语句中的or关键字,不加默认是and
List<User> userList = userDao.selectList(qw);
System.out.println(userList);
}
}

lambda格式(推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@SpringBootTest
class Mybatisplus02DqlApplicationTests {

@Autowired
private UserDao userDao;

@Test
void testGetAll(){
QueryWrapper<User> qw = new QueryWrapper<User>();
qw.lambda().lt(User::getAge, 10);//添加条件
List<User> userList = userDao.selectList(qw);
System.out.println(userList);
}
}

lambda格式2(强烈推荐)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@SpringBootTest
class Mybatisplus02DqlApplicationTests {

@Autowired
private UserDao userDao;

@Test
void testGetAll(){
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(User::getAge, 10);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
}

null判定

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@SpringBootTest
class Mybatisplus02DqlApplicationTests {

@Autowired
private UserDao userDao;

@Test
void testGetAll(){
//模拟页面传递过来的查询数据
UserQuery uq = new UserQuery();
uq.setAge(10);
uq.setAge2(30);
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.lt(null!=uq.getAge2(),User::getAge, uq.getAge2());
lqw.gt(null!=uq.getAge(),User::getAge, uq.getAge());
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
}

查询投影

查询指定字段

  • 查询投影即不查询所有字段,只查询出指定内容的数据。
  • 具体实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@SpringBootTest
class Mybatisplus02DqlApplicationTests {

@Autowired
private UserDao userDao;

@Test
void testGetAll(){
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();
lqw.select(User::getId,User::getName,User::getAge);
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
}
  • select(…)方法用来设置查询的字段列,可以设置多个,最终的sql语句为:
1
SELECT id,name,age FROM user
  • 如果使用的不是lambda,就需要手动指定字段
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@SpringBootTest
class Mybatisplus02DqlApplicationTests {

@Autowired
private UserDao userDao;

@Test
void testGetAll(){
QueryWrapper<User> lqw = new QueryWrapper<User>();
lqw.select("id","name","age","tel");
List<User> userList = userDao.selectList(lqw);
System.out.println(userList);
}
}
  • 最终的sql语句为:SELECT id,name,age,tel FROM user

聚合查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@SpringBootTest
class Mybatisplus02DqlApplicationTests {

@Autowired
private UserDao userDao;

@Test
void testGetAll(){
QueryWrapper<User> lqw = new QueryWrapper<User>();
//lqw.select("count(*) as count");
//SELECT count(*) as count FROM user
//lqw.select("max(age) as maxAge");
//SELECT max(age) as maxAge FROM user
//lqw.select("min(age) as minAge");
//SELECT min(age) as minAge FROM user
//lqw.select("sum(age) as sumAge");
//SELECT sum(age) as sumAge FROM user
lqw.select("avg(age) as avgAge");
//SELECT avg(age) as avgAge FROM user
List<Map<String, Object>> userList = userDao.selectMaps(lqw);
System.out.println(userList);
}
}

分组查询

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@SpringBootTest
class Mybatisplus02DqlApplicationTests {

@Autowired
private UserDao userDao;

@Test
void testGetAll(){
QueryWrapper<User> lqw = new QueryWrapper<User>();
lqw.select("count(*) as count,tel");
lqw.groupBy("tel");
List<Map<String, Object>> list = userDao.selectMaps(lqw);
System.out.println(list);
}
}
  • groupBy为分组,最终的sql语句为SELECT count(*) as count,tel FROM user GROUP BY tel
  • 聚合与分组查询,无法使用lambda表达式来完成

字段映射与表名映射

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
名称:@TableField

类型:属性注解

位置:模型类属性定义上方

作用:设置当前属性对应数据表中的字段关系

Value:设置数据库表字段名称

exist:设置属性在数据库表字段中是否存在


名称:@TableName

类型:类注解

位置:模型类定义上方

作用:设置当前类对应数据表中的表关系

Value:设置数据库表名称

多记录操作

1
2
3
4
5
6
7
//按照主键删除多条记录
List<Long> ids = Arrays.aList(new Long[]{2,3});
userDao.deleteBatchIds(ids);

//根据主键查询多条记录
List<Long> ids = Arrays.asList(new Long[]{2,3});
List<User> userList = userDao.selectBatchIds(ids);

逻辑删除

  1. 数据库表中添加逻辑删除标记字段
  2. 实体类中添加对应字段,并设定当前字段为逻辑删除标记字段
1
2
3
4
5
public class User {
private Long id;
@TableLogic
private Integer deleted;
}
  1. 配置逻辑删除字面值

乐观锁

  1. 数据库表中添加锁标记字段
  2. 实体类中添加对应字段,并设定当前字段为逻辑删除标记字段
1
2
3
4
5
public class User {
private Long id;
@Version
private Integer version
}
  1. 配置乐观锁拦截器
  2. 使用乐观锁机制在修改前必须先获取到对应数据的Version方可正常进行

MP_5代码生成器

提供模板,加速开发

  1. pom.xml文件中添加依赖
1
2
3
4
5
6
7
8
9
10
11
12
13
<!--代码生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.4.1</version>
</dependency>

<!--velocity模板引擎-->
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-engine-core</artifactId>
<version>2.3</version>
</dependency>
  1. 创建代码生成类
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
public class CodeGenerator {
public static void main(String[] args) {
//1.获取代码生成器的对象
AutoGenerator autoGenerator = new AutoGenerator();

//设置数据库相关配置
DataSourceConfig dataSource = new DataSourceConfig();
dataSource.setDriverName("com.mysql.cj.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTC");
dataSource.setUsername("root");
dataSource.setPassword("root");
autoGenerator.setDataSource(dataSource);

//设置全局配置
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir(System.getProperty("user.dir")+"/mybatisplus_04_generator/src/main/java"); //设置代码生成位置
globalConfig.setOpen(false); //设置生成完毕后是否打开生成代码所在的目录
globalConfig.setAuthor("黑马程序员"); //设置作者
globalConfig.setFileOverride(true); //设置是否覆盖原始生成的文件
globalConfig.setMapperName("%sDao"); //设置数据层接口名,%s为占位符,指代模块名称
globalConfig.setIdType(IdType.ASSIGN_ID); //设置Id生成策略
autoGenerator.setGlobalConfig(globalConfig);

//设置包名相关配置
PackageConfig packageInfo = new PackageConfig();
packageInfo.setParent("com.aaa"); //设置生成的包名,与代码所在位置不冲突,二者叠加组成完整路径
packageInfo.setEntity("domain"); //设置实体类包名
packageInfo.setMapper("dao"); //设置数据层包名
autoGenerator.setPackageInfo(packageInfo);

//策略设置
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setInclude("tbl_user"); //设置当前参与生成的表名,参数为可变参数
strategyConfig.setTablePrefix("tbl_"); //设置数据库表的前缀名称,模块名 = 数据库表名 - 前缀名 例如: User = tbl_user - tbl_
strategyConfig.setRestControllerStyle(true); //设置是否启用Rest风格
strategyConfig.setVersionFieldName("version"); //设置乐观锁字段名
strategyConfig.setLogicDeleteFieldName("deleted"); //设置逻辑删除字段名
strategyConfig.setEntityLombokModel(true); //设置是否启用lombok
autoGenerator.setStrategy(strategyConfig);
//2.执行生成操作
autoGenerator.execute();
}
}

对于代码生成器中的代码内容,我们可以直接从官方文档中获取代码进行修改

  1. 运行程序,运行成功后,会在当前项目中生成很多代码,代码包含controller,servicemapperentity

image-20231015203448462

MP中Service的CRUD

  • 回顾我们之前业务层代码的编写,编写接口和对应的实现类,并声明方法
1
2
3
4
5
6
7
8
9
10
11
12
13
public interface UserService{
public List<User> findAll();
}

@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserDao userDao;

public List<User> findAll(){
return userDao.selectList(null);
}
}
  • MP看到上面的代码以后就说这些方法也是比较固定和通用的,那我来帮你抽取下,所以MP提供了一个Service接口和实现类,分别是:IService和ServiceImpl,后者是对前者的一个具体实现。
  • 以后我们自己写的Service就可以进行修改.
  • 修改以后的好处是,MP已经帮我们把业务层的一些基础的增删改查都已经实现了,可以直接进行使用。
1
2
3
4
5
6
7
public interface UserService extends IService<User>{
}

@Service
public class UserServiceImpl extends ServiceImpl<UserDao, User> implements UserService{

}