4 Mybatis-Plus通用CRUD
通过前面的学习,我们了解到通过继承BaseMapper就可以获取到各种各样的单表操作,接下来我们将详细讲解这 些操作,下图是BaseMapper的各各方法:
4.1 插入操作
4.1.1 方法定义
/**
* 插入一条记录
* @param entity 实体对象
*/
int insert(T entity);
4.1.2 测试用例
package cn.yh.mp;
import cn.yh.mp.mapper.UserMapper;
import cn.yh.mp.pojo.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
public class UserMapperTest {
@Autowired
private UserMapper userMapper;
@Test
public void testInsert() {
User user = new User();
user.setAge(20);
user.setEmail("test@yh.cn");
user.setName("曹操");
user.setUserName("caocao");
user.setPassword("123456");
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime localDateTime = LocalDateTime.parse("1990-01-01 00:00:00", df);
user.setBirthday(localDateTime);
int result = this.userMapper.insert(user); //返回的result是受影响的行数,并不是自增后的id
System.out.println("result = " + result);
System.out.println(user.getId()); //自增后的id会回填到对象中
}
}
4.1.3 MP主键生成策略
上例中Mybatis-plus自动生成ID,如何设置id的生成策略呢?
MP支持的id策略如下:
package com.baomidou.mybatisplus.annotation;
import lombok.Getter;
/**
* 生成ID类型枚举类
*
* @author hubin
* @since 2015-11-10
*/
@Getter
public enum IdType {
/**
* 数据库ID自增
*/
AUTO(0),
/**
* 该类型为未设置主键类型
*/
NONE(1),
/**
* 用户输入ID
* <p>该类型可以通过自己注册自动填充插件进行填充</p>
*/
INPUT(2),
/**
* 全局唯一ID (idWorker)
*/
ID_WORKER(3),
/**
* 全局唯一ID (UUID)
*/
UUID(4),
/**
* 字符串全局唯一ID (idWorker 的字符串表示)
*/
ID_WORKER_STR(5);
private final int key;
IdType(int key) {
this.key = key;
}
}
1 自增主键:
完全采用数据库自增主键方式。
1)设置mysql数据库主键为自增
2)修改User对象:
@TableId(value = "ID", type = IdType.AUTO)
private Long id;
或:
@TableId(value = "ID")
private Long id;
3)程序中不用设置主键
2 输入主键:
手动设置主键值。
1)mysql数据库主键为自增或不是自增都可以
2)修改User对象:
@TableId(value = "ID",type = IdType.INPUT)
private Long id;
3)程序中需要设置主键
3 UUID:
生成全局唯一ID。
1)mysql数据库主键为字符串类型,不是自增类型。
2)修改User对象。
@TableId(value = "ID",type = IdType.UUID)
private String id;
3)程序中不用设置主键
4 ID_WORKER_STR:
采用雪花算法(雪花算法生成的ID是纯数字且具有时间顺序,适合分布式场景)生成全局唯一ID,字符串类型。
1)mysql数据库主键为字符串类型,不是自增类型。
2)修改User对象。
@TableId(value = "ID",type = IdType.ID_WORKER_STR)
private String id;
3)程序中不用设置主键
5 ID_WORKER:
采用雪花算法生成全局唯一ID,数值类型。
1)mysql数据库主键为数值类型,不是自增类型。
2)修改User对象。
@TableId(value = "ID",type = IdType.ID_WORKER)
private Long id;
3)程序中不用设置主键
4.2 更新操作
4.2.1 根据id更新
方法定义:
/**
* 根据 ID 修改
* @param entity 实体对象
*/
int updateById(@Param(Constants.ENTITY) T entity);
根据id更新操作步骤:
1 首先需要设置对象的主键属性值。
2 再设置要更新的属性值。
3 根据主键找到对象,更新设置属性值。
4 返回影响的记录数。
注意:只能将对象中不为NULL的属性更新到表中。测试:
// 根据id 更新
@Test
public void testUpdateById() {
User user = new User();
user.setId(7L); //主键
user.setAge(21); //更新的字段
//根据id更新,更新不为null的字段
this.userMapper.updateById(user);
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.updateById]-[DEBUG] ==> Preparing: UPDATE tb_user SET
age=? WHERE id=?
[main] [cn.yh.mp.mapper.UserMapper.updateById]-[DEBUG] ==> Parameters: 21(Integer), 6(Long)
[main] [cn.yh.mp.mapper.UserMapper.updateById]-[DEBUG] <== Updates: 1
4.2.2 根据条件更新
方法定义:
/**
* 根据 whereEntity 条件,更新记录
* @param entity 实体对象 (set 条件值,可以为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)
*/
int update(@Param(Constants.ENTITY) T entity,
@Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
根据ID更新 一次只能更新一条记录,根据条件更新可实现批量更新。
根据条件更新步骤:
1 在对象中设置要更新的属性值。
2 设置QueryWrapper,设置更新条件,可以设置多个。
3 返回影响的记录数。
注意:只能将对象中不为NULL的属性更新到表中。
测试用例:
将name等于“曹操”的记录全部更新。
@Test
public void testUpdate() {
User user = new User();
user.setAge(22); //更新的字段
//更新的条件
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", "曹操");
//可以设置多个条件...
//执行更新操作 UPDATE tb_user SET age=22 WHERE name = '曹操'
int result = this.userMapper.update(user,wrapper);
System.out.println("result = " + result);
}
上边根据id更新 根据条件更新的方法只能将对象中不为NULL的属性更新到表中,
下边通过UpdateWrapper进行更新,将birthday字段更新为NULL.
@Test
public void testUpdate2() {
//更新的条件以及字段
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.eq("id", 7).set("age", 23).set("birthday",null);
//执行更新操作 UPDATE tb_user SET age=23,birthday=null WHERE id = 7
int result = this.userMapper.update(null, wrapper);
System.out.println("result = " + result);
}
MybatisPlus的UpdateWrapper和QueryWrapper的区别:
对于查询来说,两者基本没啥区别,一般查询都是QueryWrapper;
QueryWrapper可以根据id修改,也可以根据QueryWrapper构建的推荐查询进行修改,后者修改传入一个映射实体,而且默认不会把映射实体的控制映射到数据库中;
如果想将数据库某个属性设置为null,使用UpdateWrapper
4.3 删除操作
4.3.1 deleteById
方法定义:
/**
* 根据 ID 删除
* @param id 主键ID
*/
int deleteById(Serializable id);
操作步骤:
1 指定要删除记录的主键值。
2 调用deleteById方法执行删除。
测试用例:
@Test
public void testDeleteById() {
//执行删除操作
int result = this.userMapper.deleteById(7L);
System.out.println("result = " + result);
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.deleteById]-[DEBUG] ==> Preparing: DELETE FROM tb_user WHERE id=?
[main] [cn.yh.mp.mapper.UserMapper.deleteById]-[DEBUG] ==> Parameters: 6(Long) [main] [cn.yh.mp.mapper.UserMapper.deleteById]-[DEBUG] <== Updates: 1
4.3.2 delete
方法定义:
/**
* 根据 entity 条件,删除记录
* @param wrapper 实体对象封装操作类(可以为 null)
*/
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
根据条件删除步骤:
1 定义对象,设置属性值,指定删除条件 ,可指定多个删除条件
注意:删除条件只匹配对象中不为NULL的属性值
2 设置QueryWrapper
3 执行删除
测试用例:
// 根据条件删除
@Test
public void testDeleteByMap() {
User user = new User();
user.setAge(20);
user.setName("刘备");
//将实体对象进行包装,包装为操作条件
QueryWrapper<User> wrapper = new QueryWrapper<>(user);
int result = this.userMapper.delete(wrapper);
System.out.println("result = " + result);
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.delete]-[DEBUG] ==> Preparing: DELETE FROM tb_user WHERE name=? AND age=?
[main] [cn.yh.mp.mapper.UserMapper.delete]-[DEBUG] ==> Parameters: 张三(String), 20(Integer)
[main] [cn.yh.mp.mapper.UserMapper.delete]-[DEBUG] <== Updates: 0
注意:
定义QueryWrapper可以不包装模型对象,手动设置条件,如下:
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("age",20);
wrapper.eq("name","张三");
4.3.3 deleteBatchIds
方法定义:
/**
* 删除(根据ID批量删除)
* @param idList 主键ID列表(不能为null以及empty)
*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
批量删除操作步骤:
1 指定 id列表
2 执行删除
测试用例:
// 根据id 批量删除
@Test
public void testDeleteByIds() {
//根据id集合批量删除 DELETE FROM tb_user WHERE ID IN ( ? , ? , ? )
int result = this.userMapper.deleteBatchIds(Arrays.asList(1L,10L,20L));
System.out.println("result = "+ result);
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.deleteBatchIds]-[DEBUG] ==> Preparing: DELETE FROM tb_user WHERE id IN ( ? , ? , ? )
[main] [cn.yh.mp.mapper.UserMapper.deleteBatchIds]-[DEBUG] ==> Parameters: 1(Long), 10(Long), 20(Long)
[main] [cn.yh.mp.mapper.UserMapper.deleteBatchIds]-[DEBUG] <== Updates: 1
4.4 查询操作
MP提供了多种查询操作,包括根据id查询 批量查询 查询单条数据 查询列表 分页查询等操作。
4.4.1 selectById
方法定义:
/**
* 根据 ID 查询
* @param id 主键ID
*/
T selectById(Serializable id);
根据id查询步骤:
1 设置查询记录的主键值。
2 执行查询。
3 查询结果返回一个对象。
测试用例:
// 根据id 查询
@Test
public void testSelectById() {
//根据id查询数据
User user = this.userMapper.selectById(2L);
System.out.println("result = " + user);
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.selectById]-[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email FROM tb_user WHERE id=?
[main] [cn.yh.mp.mapper.UserMapper.selectById]-[DEBUG] ==> Parameters: 2(Long) [main] [cn.yh.mp.mapper.UserMapper.selectById]-[DEBUG] <== Total: 1
result = User(id=2, userName=lisi, password=123456, name=李四, age=20, email=test2@yh.cn, address=null)
4.4.2 selectBatchIds
方法定义:
/**
* 查询(根据ID批量查询)
* @param idList 主键ID列表(不能为null以及empty)
*/
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
根据id列表查询:
1 设置id列表
2 执行查询
3 查询对象返回List
测试用例:
// 根据多个id 查询
@Test
public void testSelectBatchIds() {
//根据id集合批量查询
List<User> users = this.userMapper
.selectBatchIds(Arrays.asList(2L, 3L, 10L));
for (User user : users) {
System.out.println(user);
}
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.selectBatchIds]-[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email FROM tb_user WHERE id IN ( ? , ? , ? )
[main] [cn.yh.mp.mapper.UserMapper.selectBatchIds]-[DEBUG] ==> Parameters: 2(Long), 3(Long), 10(Long)
[main] [cn.yh.mp.mapper.UserMapper.selectBatchIds]-[DEBUG] <== Total: 2
User(id=2, userName=lisi, password=123456, name=李四, age=20, email=test2@yh.cn, address=null)
User(id=3, userName=wangwu, password=123456, name=王五, age=28, email=test3@yh.cn,
address=null)
4.4.3 selectOne
方法定义:
/**
* 根据 entity 条件,查询一条记录
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
查询步骤:
1 设置QueryWrapper对象,设置查询条件,可以设置多个条件
2 执行查询
注意:如果查询结果为多条记录则报错(TooManyResultsException)。
测试用例:
// 查询 返回一条结果
@Test
public void testSelectOne() {
QueryWrapper<User> wrapper = new QueryWrapper<User>();
wrapper.eq("name", "李四");
//根据条件查询一条数据,如果结果超过一条会报错
User user = this.userMapper.selectOne(wrapper);
System.out.println(user);
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.selectOne]-[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email FROM tb_user WHERE name = ?
[main] [cn.yh.mp.mapper.UserMapper.selectOne]-[DEBUG] ==> Parameters: 李四(String)
[main] [cn.yh.mp.mapper.UserMapper.selectOne]-[DEBUG] <== Total: 1
User(id=2, userName=lisi, password=123456, name=李四, age=20, email=test2@yh.cn, address=null)
4.4.4 selectCount
方法定义:
/**
* 根据 Wrapper 条件,查询总记录数
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
测试用例:
// 查询记录数
@Test
public void testSelectCount() {
QueryWrapper<User> wrapper = new QueryWrapper<User>();
wrapper.gt("age", 23); //年龄大于23岁
//根据条件查询数据条数
Integer count = this.userMapper.selectCount(wrapper);
System.out.println("count = " + count);
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.selectCount]-[DEBUG] ==> Preparing: SELECT COUNT( 1 ) FROM tb_user WHERE age > ?
[main] [cn.yh.mp.mapper.UserMapper.selectCount]-[DEBUG] ==> Parameters: 23(Integer) [main] [cn.yh.mp.mapper.UserMapper.selectCount]-[DEBUG] <== Total: 1
count = 2
4.4.5 selectList
方法定义:
/**
* 根据 entity 条件,查询全部记录
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
测试用例
@Test
public void testSelectList() {
QueryWrapper<User> wrapper = new QueryWrapper<User>();
wrapper.gt("age", 23); //年龄大于23岁
//根据条件查询数据
List<User> users = this.userMapper.selectList(wrapper);
for (User user : users) {
System.out.println("user = " + user);
}
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.selectList]-[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email FROM tb_user WHERE age > ?
[main] [cn.yh.mp.mapper.UserMapper.selectList]-[DEBUG] ==> Parameters: 23(Integer) [main] [cn.yh.mp.mapper.UserMapper.selectList]-[DEBUG] <== Total: 2
user = User(id=3, userName=wangwu, password=123456, name=王五, age=28, email=test3@yh.cn, address=null)
user = User(id=5, userName=sunqi, password=123456, name=孙七, age=24, email=test5@yh.cn, address=null)
4.4.6 selectPage
方法定义:
/**
* 根据 entity 条件,查询全部记录(并翻页)
*
* @param page 分页查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
配置分页插件:
package com.laojun.mp.config;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @ClassName : MybatisPlusConfig
* @Author : glls
* @Date: 2021/2/23 11:45
* @Description : 配置
*/
@Configuration
public class MybatisPlusConfig {
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
测试用例:
// 测试分页
@Test
public void testSelectPage() {
QueryWrapper<User> wrapper = new QueryWrapper<User>();
wrapper.gt("age", 20); //年龄大于20岁
//参数1:当前页码,小于1的按1算
//参数2:每页记录数
Page<User> page = new Page<>(1,2);
//根据条件查询数据
IPage<User> iPage = this.userMapper.selectPage(page, wrapper);
System.out.println("数据总条数:" + iPage.getTotal());
System.out.println("总页数:" + iPage.getPages());
//取出分页记录
List<User> users = iPage.getRecords();
for (User user : users) {
System.out.println("user = " + user);
}
}
结果:
[main] [cn.yh.mp.mapper.UserMapper.selectPage]-[DEBUG] ==> Preparing: SELECT COUNT(1) FROM tb_user WHERE age > ?
[main] [cn.yh.mp.mapper.UserMapper.selectPage]-[DEBUG] ==> Parameters: 20(Integer) [main] [cn.yh.mp.mapper.UserMapper.selectPage]-[DEBUG] ==> Preparing: SELECT id,user_name,password,name,age,email FROM tb_user WHERE age > ? LIMIT ?,?
[main] [cn.yh.mp.mapper.UserMapper.selectPage]-[DEBUG] ==> Parameters: 20(Integer), 0(Long), 1(Long)
[main] [cn.yh.mp.mapper.UserMapper.selectPage]-[DEBUG] <== Total: 1
[main] [org.mybatis.spring.SqlSessionUtils]-[DEBUG] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6ecd665]
数据总条数:3
总页数:3
user = User(id=3, userName=wangwu, password=123456, name=王五, age=28, email=test3@yh.cn,
birthday=2019-10-02T11:42:14, address=null)