Mybatis-Plus使用手册
本文最后更新于:2021年6月23日 晚上
🌟 HelloWorld
(1)初始化SpringBoot工程
(2)导入依赖
<!--mybatis-plus-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
<!--mysql依赖-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
(3)在application中配置数据库信息
# 应用名称
spring.application.name=mybatis_plus_demo
# 数据库配置信息
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root
# 日志实现方式
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
# 主键自增
#mybatis-plus.global-config.db-config.id-type=auto
(4)在主引导类上添加扫描包注解@MapperScan("com.gaowl.mybatis_plus_demo.mapper")
(5)创建包entity
及实体类User.java
(6)创建包mapper
及接口UserMapper.java
// 在接口上通过注释@Repository 避免无法自动装配
// Mapper 继承 BaseMapper接口后,无需编写 mapper.xml 文件,即可获得CRUD功能
@Repository
public interface UserMapper extends BaseMapper<User> {
}
(7)测试即可
@SpringBootTest
class MybatisPlusDemoApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
void contextLoads() {
List<User> users = userMapper.selectList(null);
System.out.println(users);
}
@Test
public void testAdd(){
User user = new User();
user.setId(6L);
user.setName("李四");
user.setAge(20);
user.setEmail("11111@qq.com");
int insert = userMapper.insert(user);
System.out.println(insert);
}
@Test
public void testUpdate(){
User user = new User();
user.setId(1372867719975714818L);
user.setName("lucymary233");
int count = userMapper.updateById(user);
System.out.println(count);
}
@Test
public void testOptimisticLocker(){
User user = userMapper.selectById(6L);
user.setName("张三");
userMapper.updateById(user);
}
}
🌟 主键策略
MyBatis Plus默认的主键策略是:ASSIGN_ID
(使用了雪花算法,分布式ID生成器)
雪花算法:由Twitter公布的分布式主键生成算法,它能够保证不同表的主键的不重复性,以及相同表的主键的有序性。长度共64bit(一个long型) 19位数字
整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞,并且效率较高,用的也比较多。
MyBatis Plus支持的主键策略还有AUTO
自增
实体字段中配置 @TableId(type = IdType.AUTO)
@TableId(type = IdType.AUTO)
private Long id;
要想影响所有实体的配置,可以设置全局主键配置
#全局设置主键生成策略
mybatis-plus.global-config.db-config.id-type=auto
🌟 自动填充与乐观锁
项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。我们可以使用MyBatis Plus
的自动填充功能,完成这些字段的赋值工作
(1)修改数据库
在User表中添加datetime
类型的新的字段 create_time
、update_time
(2)修改实体类
实体类上增加字段并添加自动填充注解
// 添加元素的时候自动赋值
@TableField(fill = FieldFill.INSERT)
private Date createTime;
// 添加和更新元素时均自动赋值
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
(3)实现元对象处理器接口
package com.gaowl.mybatis_plus_demo.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
import java.util.Date;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
//mp执行添加操作,这个方法执行
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
this.setFieldValByName("version",1,metaObject);
}
//mp执行修改操作,这个方法执行
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
(4)测试即可,每次创建对象时自动对create_time
、update_time
字段赋值,更新对象时对update_time
赋值
乐观锁主要用于实现线程安全的数据更新,当要更新一条记录的时候,希望这条记录没有被别人更新。
取出记录时,获取当前version
更新时,带上这个version
执行更新时, set version = newVersion where version = oldVersion
如果version不对,就更新失败
Mybatis-Plus中的乐观锁使用:
(1)修改实体类
新建version
字段,并添加@Version
注解
@Version
private Integer version;
(2)创建配置文件,并注册乐观锁插件
创建包config及文件MybatisPlusConfig.java
@Configuration
@MapperScan("com.atguigu.demomptest.mapper")
public class MpConfig {
/**
* 注册乐观锁插件
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
(3)测试即可
🌟 查询
(1)多个id批量查询
使用selectBatchIds
命令实现多个id的批量查询
@Test
public void testSelect1() {
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
System.out.println(users);
}
(2)条件查询
selectByMap
命令,通过map封装查询条件;注意:map中的key对应数据库中的列名。如:数据库user_id
,实体类是userId
,这时map的key需要填写user_id
@Test
public void testSelect2() {
Map<String, Object> columnMap = new HashMap<>();
columnMap.put("name","Jack");
columnMap.put("age",20);
List<User> users = userMapper.selectByMap(columnMap);
System.out.println(users);
}
(3)分页查询
需先在配置类中添加分页插件
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
之后采用selectPage
命令进行分页查询
@Test
public void testSelectPage() {
Page<User> page = new Page(1,3);
Page<User> userPage = userMapper.selectPage(page, null);
//返回对象得到分页所有数据
long pages = userPage.getPages(); //总页数
long current = userPage.getCurrent(); //当前页
List<User> records = userPage.getRecords(); //查询数据集合
long total = userPage.getTotal(); //总记录数
boolean hasNext = userPage.hasNext(); //下一页
boolean hasPrevious = userPage.hasPrevious(); //上一页
System.out.println(pages);
System.out.println(current);
System.out.println(records);
System.out.println(total);
System.out.println(hasNext);
System.out.println(hasPrevious);
}
🌟 删除
(1)根据id删除数据 deleteById
@Test
public void testDeleteById(){
int result = userMapper.deleteById(5L);
system.out.println(result);
}
(2)批量删除数据 deleteBatchIds
@Test
public void testDeleteBatchIds() {
int result = userMapper.deleteBatchIds(Arrays.asList(8, 9, 10));
system.out.println(result);
}
(3)条件删除 deleteByMap
@Test
public void testDeleteByMap() {
HashMap<String, Object> map = new HashMap<>();
map.put("name", "Helen");
map.put("age", 18);
int result = userMapper.deleteByMap(map);
system.out.println(result);
}
(4)逻辑删除
概念
物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
逻辑删除的使用场景:
可以进行数据恢复
有关联数据,不便删除
实现流程:
数据库中添加delete字段:
ALTERTABLE user ADD COLUMN deleted boolean DEFAULT false
实体类中添加deleted字段,并加上
@TableLogic
注解application.yml中添加默认值配置
mybatis-plus.global-config.db-config.logic-delete-value=1 mybatis-plus.global-config.db-config.logic-not-delete-value=0
测试
@Test public void testLogicDelete() { int result = userMapper.deleteById(1L); system.out.println(result); }
测试后发现,数据并没有被删除,deleted字段的值由0变成了1;测试后分析打印的sql语句,是一条update。
注意:被删除前,数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作
🌟 条件构造器wrapper实现复杂查询
查询方式 | 说明 |
---|---|
setSqlSelect | 设置 SELECT 查询字段 |
where | WHERE 语句,拼接 + WHERE 条件 |
and | AND 语句,拼接 + AND 字段=值 |
andNew | AND 语句,拼接 + AND (字段=值) |
or | OR 语句,拼接 + OR 字段=值 |
orNew | OR 语句,拼接 + OR (字段=值) |
eq | 等于= |
allEq | 基于 map 内容等于= |
ne | 不等于<> |
gt | 大于> |
ge | 大于等于>= |
lt | 小于< |
le | 小于等于<= |
like | 模糊查询 LIKE |
notLike | 模糊查询 NOT LIKE |
in | IN 查询 |
notIn | NOT IN 查询 |
isNull | 是否为空 |
isNotNull | 非空 |
groupBy | 分组 GROUP BY |
having | HAVING 关键词 |
orderBy | 排序 ORDER BY |
orderAsc | ASC 排序 ORDER BY |
orderDesc | DESC 排序 ORDER BY |
exists | EXISTS 条件语句 |
notExists | NOT EXISTS 条件语句 |
between | BETWEEN 条件语句 |
notBetween | NOT BETWEEN 条件语句 |
addFilter | 自由拼接 SQL |
last | 拼接在最后,例如:last(“LIMIT 1”) |
(1)ge、gt、le、lt、isNull、isNotNull
@Test
public void testQuery() {
// 新建QueryWrapper实例,并传入实体类类型
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
.isNull("name")
.ge("age", 12)
.isNotNull("email");
// 删除符合此查询条件(name为空,年龄大于等于12且邮箱非空)的数据
int result = userMapper.delete(queryWrapper);
System.out.println("delete return count = " + result);
}
(2)eq、ne
@Test
public void testSelectOne() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "Tom");
Useruser = userMapper.selectOne(queryWrapper);//只能返回一条记录,多于一条则抛出异常
System.out.println(user);
}
(3)between、notBetween
@Test
public void testSelectCount() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.between("age", 20, 30);
Integer count = userMapper.selectCount(queryWrapper); //返回数据数量
System.out.println(count);
}
(4)like、notLike、likeLeft、likeRight
selectMaps()
返回Map集合列表,通常配合select()
使用
@Test
public void testSelectMaps() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
.select("name", "age")
.like("name", "e") // name中包含e
.likeRight("email", "5"); //
List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表
maps.forEach(System.out::println);
}
(5)orderBy、orderByDesc、orderByAsc
@Test
public void testSelectListOrderBy() {
QueryWrapper<User>queryWrapper = newQueryWrapper<>();
queryWrapper.orderByDesc("age", "id");
List<User>users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!