MyBatisPlus

yql

MyBatisPlus使用

MyBatis的增强版,只做增强不做改变:简单配置、代码生成、自动分页

1.导入MyBatisPlus依赖

1
2
3
4
5
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.1</version>
</dependency>
  1. 定义Mapper接口并继承BaseMapper接口
1
2
3
4
5
6
7
8
9
10
11
12
package com.itheima.mp.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.itheima.mp.domain.po.User;
import org.apache.ibatis.annotations.Param;

import java.util.List;

public interface UserMapper extends BaseMapper<User> {

}

  1. 在实体类上添加注解声明 表信息
  2. 在application.yml中根据需要添加配置
  3. 编写单元测试类
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
package com.itheima.mp.mapper;

import com.itheima.mp.domain.po.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

import java.time.LocalDateTime;
import java.util.List;

@SpringBootTest
class UserMapperTest {

@Autowired
private UserMapper userMapper;

@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(5L);
System.out.println("user = " + user);
}


@Test
void testQueryByIds() {
List<User> users = userMapper.selectBatchIds(List.of(1L, 2L, 3L, 4L));
users.forEach(System.out::println);
}

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

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

MyBatisPlus原理

MyBatisPlus通过扫描实体类,并基于反射获取实体类信息作为数据库表信息

约定大于配置

  • 类名驼峰转下划线
  • 名为id的字段作为主键
  • 变量名驼峰转下划线作为表的字段名
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;
}

常用注解:

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

id Type枚举

@TableField(value = "id", type = IdType.Auto)

  • Auto:数据库自增长
  • Input:通过set方法自行输入
  • ASSIGN_ID:默认由雪花算法生成id

使用TableField场景

  • 成员变量名与数据库不一致
  • 成员变量名是布尔类型,并且以is开头
  • 成员变量名是数据库关键字
  • 成员变量不是数据库字段 @TableField(exist = false)
1
2
3
4
5
6
7
8
9
10
11
@TableName("user")
public class User {
@TableId
private Long id;
private String name;
private Integer age;
@TableField("isMarried")
private Boolean isMarried;
@TableField("concat")
private String concat;
}

条件构造器

  • QueryWrapper和LambdaQueryWrapper通常用来构建select、delete、update的where条件部分

  • UpdateWrapper和LambdaUpdateWrapper通常只有在set语句比较特殊时才使用

  • 尽量使用Lambda,避免硬编码

案例1:查询出名字中带o,存款大于等于1000的人的id,username,info,balance字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Test
void testQueryWrapper(){
//1.构造查询条件
QueryWrapper<User> wrapper = new QueryWrapper<User>()
.select("id", "username", "info", "balance")
.like("username", "o")
.ge("balance", 1000);
//2.查询
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}
@Test
void testLambdaQueryWrapper(){
//1.构造查询条件
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
.select(User::getId, User::getUsername, User::getInfo, User::getBalance)
.like(User::getUsername, "o")
.ge(User::getBalance, 1000);
//2.查询
List<User> users = userMapper.selectList(wrapper);
users.forEach(System.out::println);
}

案例2: 扣减库存

1
2
3
4
5
6
7
8
@Test
void testUpdateWrapper(){
List<Long> ids = List.of(1L, 2L, 4L);
UpdateWrapper<User> wrapper = new UpdateWrapper<User>()
.setSql("balance = balance - 200")
.in("id", ids);
userMapper.update(null, wrapper);
}

自定义sql

利用MyBatisPlus的Wrapper来构建复杂的where条件,然后自定义SQL语句剩下的部分

  1. 基于Wrapper构建where条件
1
2
3
4
5
6
7
8
@Test
void testCustomSqlUpdate(){
int amount = 200;
List<Long> ids = List.of(1L, 2L, 4L);
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<User>()
.in(User::getId, ids);
userMapper.updateBalanceByIds(wrapper, 200);
}
  1. 在wrapper方法参数中用Param注解声明wrapper变量名称,必须是ew
1
void updateBalanceByIds(@Param("ew") LambdaQueryWrapper<User> wrapper, @Param("amount") int amount);
  1. 自定义sql,并使用Wrapper条件
1
2
3
<update id="updateBalanceByIds">
UPDATE tb_user SET balance = balance - #{amount} ${ew.customSqlSegment}
</update>

Service 接口

Comments