导入依赖;
com.baomidou
mybatis-plus-boot-starter
3.3.1
正常连接数据库:
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=root
编写mapper接口,并继承baseMapper接口(指定泛型)
@Repository
public interface UserMapper extends BaseMapper {
}
启动类接口包扫描:
@MapperScan("com.sen.demomptest.mapper")
Mybatis plus有查看SQL输出日志:在配置文件中配置:
#mybatis日志
mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
数据插入操作:
指定主键策略:
自动填充:
需求描述:
项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。
1、在实体类中添加注解,表示自动填充:
@TableField(fill = FieldFill.INSERT)
private Date createTime; //create_time
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime; //update_time
2、实现元素对象处理接口:
@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);//新建数据的时候,乐观锁版本值设置为1
}
//mp执行修改操作,这个方法执行
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
乐观锁:(通过添加一个版本号进行控制,事务版本号一致,可以提交,不一致则放弃提交)
主要适用场景:当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新
乐观锁实现方式:
取出记录时,获取当前version
更新时,带上这个version
执行更新时, set version = newVersion where version = oldVersion
如果version不对,就更新失败
1、数据表添加一个版本的字段,
2、实体类添加相应的属性并在实体类中的属性中添加一个version注解
3、在配置类中注册乐观锁插件
/**
* 乐观锁插件
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
完成了动态sql的foreach的功能
//多个id批量查询
@Test
public void testSelect1() {
List users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
System.out.println(users);
}
通过map封装查询条件
注意:map中的key对应数据库中的列名。如:数据库user_id,实体类是userId,这时map的key需要填写user_id
//简单条件查询
@Test
public void testSelect2() {
Map columnMap = new HashMap<>();
columnMap.put("name","Jack");
columnMap.put("age",20);
List users = userMapper.selectByMap(columnMap);
}
分页查询:
1、分页插件
MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能
在配置类中添加分页插件:
/**
* 分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
编写分页的查询:
Page page = new Page(1,3);
Page userPage = userMapper.selectPage(page, null);
//返回对象得到分页所有数据
long pages = userPage.getPages(); //总页数
long current = userPage.getCurrent(); //当前页
List records = userPage.getRecords(); //查询数据集合
long total = userPage.getTotal(); //总记录数
boolean hasNext = userPage.hasNext(); //下一页
boolean hasPrevious = userPage.hasPrevious(); //上一页
其中提供了类似的分页查询方法,selectMapsPage。
//Page不需要泛型
Page
删除:
deleteById | 根据ID删除数据 |
deleteBatchIds | 根据多个ID批量删除数据 |
deleteByMap | 根据map集合条件删除相应数据 |
逻辑删除:
物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
逻辑删除的实现:
在数据表中添加一个表示删除状态的字段:
ALTERTABLE `user` ADD COLUMN `deleted` boolean DEFAULT false
在实体类中添加相应的属性,并加上@TableLogic注解
@TableLogic
private Integer deleted;
application.properties 加入以下配置,此为默认值,如果你的默认值和mp默认的一样,该配置可无
mybatis-plus.global-config.db-config.logic-delete-value=1 mybatis-plus.global-config.db-config.logic-not-delete-value=0 |
此时,再删除带删除字段的数据,就是逻辑删除,,默认修改状态值,相应的查询数据也是一样,只能查询出未删除的数据,即运行的SQL语句逻辑后面加上where deleted=0
wapper介绍
Wrapper : 条件构造抽象类,最顶端父类
AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
QueryWrapper : 查询条件封装
UpdateWrapper : Update 条件封装
AbstractLambdaWrapper : 使用Lambda 语法
LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper : Lambda 更新封装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 等同 LIKE ‘%值%’ |
notLike |
模糊查询 NOT LIKE |
likeLeft | 模糊查询 LIKE ‘%值’ |
likeRight | 模糊查询 LIKE ‘值%’ |
in |
IN 查询 |
notIn |
NOT IN 查询 |
isNull |
NULL 值查询 |
isNotNull |
IS NOT NULL |
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”) |
2.3 Service CRUD接口
另外一套CRUD是Service层的,只需要编写一个接口,继承IService,并创建一个接口实现类,即可食用。(这个接口提供的CRUD方法,和Mapper接口提供的功能大同小异,比较明显的区别在于IService支持了更多的批量化操作,如saveBatch,saveOrUpdateBatch等方法。
package com.example.mp.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.example.mp.po.User;
public interface UserService extends IService {
}
package com.example.mp.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mp.mappers.UserMapper;
import com.example.mp.po.User;
import com.example.mp.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends ServiceImpl implements UserService { }
IService也支持链式调用,代码写起来非常简洁,查询示例如下:
@Test
public void testChain() {
userService.lambdaUpdate()
.gt(User::getAge, 39)
.likeRight(User::getName, "王")
.set(User::getEmail, "[email protected]")
.update();
}
mybatis-plus
也可以使用mp提供的Wrapper条件构造器,来自定义SQL
注解方式:
public interface UserMapper extends BaseMapper {
// SQL中不写WHERE关键字,且固定使用${ew.customSqlSegment}
@Select("select * from user ${ew.customSqlSegment}")
List findAll(@Param(Constants.WRAPPER)Wrapper wrapper);
}