步骤:
1:exclutin通过路径或自定义注解定位到方法
2:先拿到方法对象
3:通过方法对象获取:参数,注解,以及注解值
4:判断方法上的注解值,确定操作类型
5:通过反射确定方法并赋值
备注:apply里千万别用别名,不识别!!!!
//一定要先判断,在组装条件,不然条件有问题,数据有问题
if (!EmptyUtil.isNullOrEmpty(storeVo.getStoreName())) {
queryWrapper.lambda().likeRight(Store::getStoreName,storeVo.getStoreName());
}
Mapper层继承BaseMapper<实体类>
Servic层继承IService<实体类>
实现类 继承 ServiceImpl Mapp层,实体类
开头 wrapper.select(" user_name,count(*) user_id ");
结尾 wrapper.last("order by user_id desc limit 10");
拼接SQL wrapper.lambda().apply("mod(id," + numbers + " ) = " + index;
版本Mybatis-PLUS 2.x常用方法:
insert: 保存
updateById: 根据主键更新
deleteById: 根据主键删除
selectById: 根据主键查询
selectList: 查询所有,参数new EntityWrapper().like(“name”,“m”)
selectPage: 分页查询,参数new Page(1,10),new EntityWrapper(new User())
tails/120219250
版本Mybatis-PLUS 3.x常用方法:
save: 保存
saveBath: 批量保存
updateById: 根据主键更新
updateBatchById: 根据主键批量更新
removeById : 根据主键删除
removeByIds: 根据多个id删除
getById : 根据主键查询
getOne: 根据条件返回一个结果
list: 查询所有,参数new QueryWrapper()
listByIds: 根据多个id查询
listMaps: 参数new QueryWrapper(),返回List
listByMap: 参数Map
page: 分页查询,参数new Page(1,10),new QueryWrapper()
pageMaps: 参数new QuweyWrapper(), 返回List
//指定主键自增的生成策略
@TableId(value = "user_id",type = IdType.AUTO)
private Integet userId;
ALTER TABLE table_name AUTO_INCREMENT = value;
1.通过@TableField("表列名") 指定映射关系
备注:名称一样 , 字段使用_分割,开启驼峰映射可忽略
2.忽略某个字段的查询和插入 @TableField(exist = false)
例:
User user =
User.builder()
.userName("itheima")
.name("itcast")
.build();
int insert = userMapper.insert(user);
根据id删除:
int count = userMapper.deleteById(8L);
根据id集合批量删除:
List ids = new ArrayList();
ids.add(6);
ids.add(7);
userMapper.deleteBatchIds(ids);
根据map构造条件,删除:
Map map = new HashMap<>();
map.put("user_name","itcast");
map.put("age","18");
userMapper.deleteByMap(map);
//delete from tb_user where user_name = ? and age = ?
1:判断传进来的数据有么有,对不对
2:根据传进来的数据去库里查。看看要修改的数据有没有。没有报错
/**
*区域删除
*/
@Override
public boolean modifyRegion2(RegionEntity region) {
//判断关键数据
if (Strings.isNullOrEmpty(region.getName())||
Strings.isNullOrEmpty(region.getRemark())||
ObjectUtils.isEmpty(region.getId())
) {
throw new LogicException("关键参数与接口不匹配");
}
//判断业务数据
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.eq(RegionEntity::getId, region.getId());
int count = this.count(wrapper);
if (count < 1) {
throw new LogicException("区域信息不存在");
}
// 3.修改区域数据并返回结果
boolean result = this.removeById(region.getId());
return result;
}
更新:
更新的本质是根据id更新
1:库里id是否存在,id不存在,返回错误信息给前端。也有可能改为新增
// 根据id去库里取数据,返回一个完整的数据
TaskEntity task = this.getById(id);
//修改数据的状态
task.setTaskStatus(VMSystem.TASK_STATUS_FINISH);
// 更新。传入修改后完整的数据
this.updateById(task);
// 1:it里有id,2:要更新的值,3:直接updateById传入实体改
public void ipd(Item it) {
LambdaQueryWrapper- wrapper = new LambdaQueryWrapper<>();
itemMapper.updateById(it);// 也可以 this.updateById(it)
}
updateById:直接丢进去要修改的实体。不要warp
根据实体对象中的id更新数据:
User user = new User();
user.setId(2L);
user.setPassword("1111111");
int count = userMapper.updateById(user);
备注:只更新实体类中存在的数据,如果对应的属性为null,不更新;
——————————————————————————————————————————————————————————————
备注变种: 根据id更新 it是传进来的数据,用实体类接的
public void ipd(Item it) {
LambdaQueryWrapper- wrapper = new LambdaQueryWrapper<>();
itemMapper.updateById(it);// 也可以 this.updateById(it)
}
————————————————————————————————————————————————————————————
根据id,部分修改 update(要修改的实体,根据什么条件修改)
// 参数1: 最新的值
User user = new User();
user.setUserName("张三丰");
// 参数2:更新时条件 //这个好用:LambdaQueryWrapper
- wrapper = new LambdaQueryWrapper<>();
LambdaQueryWrapper
wrapper = Wrappers.lambdaQuery();
wrapper.eq(User::getId, 15);
//开始更新
int update = userMapper.update(user, wrapper);
————————————————————————————————————————————————————————————————
在某个字段原先的基础上修改:
//把num字段加5
LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate()
.eq(User::getId, userId)
.setSql("count = count + 5");//“count = count 字段名=字段名+5”
userService.update(updateWrapper);
链式编程:itemUpdateWrapper.eq("id", id).setSql("stock=stock+" + num);
__________________________________________________________________
UpdateWrapper:
var updateWrapper = new LambdaUpdateWrapper();
updateWrapper.set(TaskEntity::getTaskStatus, VMSystem.TASK_STATUS_PROGRESS);
updateWrapper.set(TaskEntity::getUpdateTime, LocalDateTime.now());
updateWrapper.eq(TaskEntity::getTaskId, task.getTaskId());
return this.update(updateWrapper);
——————————————————————————————————————————————————
_________________________________________________________
@Test
public void testUpdateById() {
User user = new User();
user.setId(2L);
user.setPassword("1111111");
int count = userMapper.updateById(user);
}
——————————————————————————————————————————————————————————————
/**
* UPDATE tb_user SET t_name=? WHERE (id = ?)
*/
// 参数1: 最新的值。这里是set
User user = new User();
user.setUserName("张三丰");
// 参数2:更新时条件 。 这里是where
LambdaQueryWrapper wrapper = Wrappers.lambdaQuery();
wrapper.eq(User::getId, 15);
int update = userMapper.update(user, wrapper);
——————————————————————————————————————————————————————————
其余写法:
/**
* UPDATE tb_user SET t_name=?, user_name=? WHERE (id = ?)
*/
// 参数1: 最新的值
// 参数2:更新时条件
LambdaUpdateWrapper wrapper = Wrappers.lambdaUpdate();
wrapper.eq(User::getId, 15)
.set(User::getUserName, "张三丰666")
.set(User::getName,"zsf666");
int update = userMapper.update(null, wrapper);
1:判断传进来的数据有么有,对不对
2:根据传进来的数据去库里查。看看要修改的数据有没有。没有报错
3:...
4:没问题再修改
@Override
public boolean modifyRegion(RegionEntity region) {
// 判断关键信息
if (Strings.isNullOrEmpty(region.getName())||Strings.isNullOrEmpty(region.getRemark())
|| ObjectUtils.isEmpty(region.getId())) {
throw new LogicException("关键参数与接口不匹配");
}
//判断业务数据
// 区域信息,判断是否存在
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.eq(RegionEntity::getId, region.getId());
int count = this.count(wrapper);
if (count < 1) {
throw new LogicException("区域信息不存在");
}
//修改区域数据并返回结果
this.updateById(region);
return false;
}
update:
//返回库里所有数据
List users = userMapper.selectList(null);
// 穿个wrp拿数据,有没有id都行
LambdaQueryWrapper wrapper2 = new LambdaQueryWrapper<>();
wrapper2.eq(PolicyEntity::getCreateTime, date);
this.getById(wrapper2);
//查询一个
this.getOne(wp);
count:返回的是符合条件的数据有几条
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.eq(RegionEntity::getId, region.getId());
int count = this.count(wrapper);
getCurrent():获取当前页数。 第几页
getRecords() 方法返回的是当前页的数据记录列表 第几页的内容
getTotal():获取总记录数。
getPages():获取总页数。
getSize():获取每页显示的条目数量。
hasNext():判断是否有下一页。
hasPrevious():判断是否有上一页。
牛皮写法: mp下,底层查实现类关联的库,然后分页。 有条件:加个lmdwp,装在this.page里
Page pageEntity = new Page<>(page, paseSize);
this.page(pageEntity); //这一步会返回一个结果集,里面封装了数据,但是看不到
int current = 1;//当前页码
int size = 2;//每页显示条数
写法一:
IPage page = new Page(current,size);
userMapper.selectPage(page,null); // 分页对象,查询条件(条件写wrps)
List records = page.getRecords();//当前页的数据
long pages = page.getPages();//总页数 2
long total = page.getTotal();//总记录数 4
pageEntity.getCurrent(); //当前的页数 这两条另加的
pageEntity.getSize(); //当前的条数
备注:配置类添加分页拦截器
//写法二:
1.创建分页对象(MP)
Page pageEntity = new Page<>(pageIndex,pageSize);
2:构建查询对象
LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
wrapper.like(RegionEntity::getName,name);
3:查询数据并返回
this.page(pageEntity,wrapper); //这一步会返回一个结果集,里面封装了数据,但是看不到
1:看看page,size传没传。校验参数
2:如果page,size没有,看看给个默认值,还是报错
3:然后再查
前置:配置分页拦截器
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
PaginationInnerInterceptor paginationInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
// 设置请求的页面大于最大页后操作, true调回到首页,false 继续请求 默认false
// paginationInterceptor.setOverflow(false);
// 设置最大单页限制数量,-1不受限制
paginationInterceptor.setMaxLimit(-1L);
interceptor.addInnerInterceptor(paginationInterceptor);
return interceptor;
}
}
/**
* @Description 自定义sql分页查询实现
*/
@Test
public void test19(){
IPage page=new Page<>(2,3);
IPage users = userMapper.findGtIdByPage(page, 3l);
System.out.println(users.getRecords());
System.out.println(user.getPages());
System.out.println(user.getTotal());
}
Mapper层
//@Mapper
public interface UserMapper extends BaseMapper {
/**
* 查询大于指定id的用户信息,并分页查询实现
* @param page
* @param id
* @return
*/
IPage findGtIdByPage(IPage page, @Param("id") Long id);
}
XML
eq( ) : 等于 =
ne( ) : 不等于 <>
gt( ) : 大于 >
ge( ) : 大于等于 >=
lt( ) : 小于 <
le( ) : 小于等于 <=
between ( ) : BETWEEN 值1 AND 值2
notBetween ( ) : NOT BETWEEN 值1 AND 值2
in( ) : in
notIn( ) :not in
like() : 模糊查询 '%xxx%'
likeLeft(); 模糊查询 '%xxx'
likeRight(); 模糊查询 'xxx%'
例:查询用户中姓名包含"伤",
密码为"123456",
且年龄为19或者25或者29,
查询结果按照年龄降序排序;
// 1:获取封装器
QueryWrapper wrapper = new QueryWrapper<>();
// 2:封装查询条件
wrapper.like("user_name", "伤")
.eq("password","123456")
.in("age",19,25,29)
.orderByDesc("age","id"); // 降序 升序:asc
//3.查询仍要由Mapper对象完成
List users = userMapper.selectList(wrapper);
System.out.println(users);
通过QueryWrapper调用or()方法时,底层会使用or关键字拼接方法左右的查询条件;
查询:姓名是lisi,或者年龄大于23,姓名是王五,李四其中一个
//1.创建查询条件构建器
QueryWrapper wrapper = new QueryWrapper<>();
//2.设置条件
wrapper.eq("user_name","lisi")
.or()
.lt("age",23)
.in("name","李四","王五");//
//3.查询仍要由Mapper对象完成
List users = userMapper.selectList(wrapper);
select * from tb_user where user_name = ? or age < ? and name in (?,?)
//查询到list集合
List userList = userService.selectById(id);
//结果集
List resultList = new ArrayList<>();
//遍历集合取值
userList .forEach(item->{
resultList.add(item.getYouNeedId());
});
//条件构造器in上手使用
QueryWrapper qw = new QueryWrapper<>();
qw.in("you_need_id", resultList);
//这里有个分页的查询,你也可以不用分页,用mybatisplus里面封装的其他方法
IPage userIPage = userMapper.selectPage(page, qw);
//返回查询结果,getRecords也是mybatisplus里面封装的方法
return contractRecordIPage.getRecords();
基于大于多少,小于多少去做
// 发布时间 >= 开始时间
wrapper.ge(dto.getBeginPubDate() != null,WmNews::getPublishTime, dto.getBeginPubDate());
// 发布时间 <= 开始时间
wrapper.le(dto.getEndPubDate()!=null,WmNews::getPublishTime, dto.getBeginPubDate());
like("表列名","条件值");
作用:查询包含关键字的信息,底层会自动添加匹配关键字,比如:%条件值%
likeLeft("表列名","条件值");
作用:左侧模糊搜索,也就是查询以 指定条件值结尾的数据,比如:%条件值
likeRight("表列名","条件值");
作用:右侧模糊搜索,也就是查询以 指定条件值开头的数据,比如:条件值%
//1.创建查询条件构建器
QueryWrapper wrapper = new QueryWrapper<>();
//2.设置条件
wrapper.likeLeft("user_name","zhang");
/*
SELECT id,user_name,password,name,age,email
from tb_user
where user_name like ?
%zhang
*/
List users = userMapper.selectList(wrapper);
orderByAsc 升序排序
orderByDesc 降序排序
需求:先根据age升序排序,如果年龄相同则按照id降序排序;
//1.创建查询条件构建器
QueryWrapper wrapper = new QueryWrapper<>();
//2.设置条件
wrapper.eq("user_name","lisi")
.or()
.lt("age",23)
.in("name","李四","王五")
//.orderBy(true,true,"age")
.orderByDesc("age");
/*
select * from tb_user where user_name = ? or age < ? and name in (?,?) order by age asc
*/
List users = userMapper.selectList(wrapper);
即: 规定 select 的字段 ,增加查询效率,避免IO浪费
wrapper.select("字段1","字段2",......)
//1.创建查询条件构建器
QueryWrapper wrapper = new QueryWrapper<>();
//2.设置条件
wrapper.eq("user_name","lisi")
.or()
.lt("age",23)
.in("name","李四","王五")
//.orderBy(true,true,"age")
.orderByDesc("age")
.select("id","user_name"); // 这里规定了:只查 id跟username
/*
select id,user_name from tb_user where user_name = ? or age < ? and name in (?,?) order by age asc
*/
List users = userMapper.selectList(wrapper);
System.out.println(users);
getCurrent():获取当前页数。
getRecords() 方法返回的是当前页的数据记录列表
getTotal():获取总记录数。
getPages():获取总页数。
getSize():获取每页显示的条目数量。
hasNext():判断是否有下一页。
hasPrevious():判断是否有上一页。
getRecords:获取查询数据
apmIndexSetMapper.selectPage(page,wrapper).getRecords();
//参数1:分页对象 参数2:查询条件
mapper.selectPage(page,wrapper);
int current = 1;//当前页码
int size = 2;//每页显示条数
//1. 构建分页对象
Page page = new Page<>(current,size);// 第几页,每页几条
//2. 构建条件对象
QueryWrapper wrapper = new QueryWrapper();
wrapper.lt("age",23);
// Mapper对象执行查询
userMapper.selectPage(page,wrapper);// 分页对象,查询条件
List records = page.getRecords();//当前页的数据
long total = page.getTotal();//总页数 2
long pages = page.getPages();//总记录数 4
备注:配置类添加分页拦截器
例:
QueryWrapper wrapper = new QueryWrapper<>();
//2.设置条件
wrapper.likeLeft("user_name","zhang");// QueryWrapper需要手写字段
//类名::字段 ,值 // lmd方式,不需要手写字段了
1.使用QueryWrapper查询数据时需要手写对应表的列名信息,及其容易写错,开发体验不好;
2.使用QueryWrapper查询数据时,表的列名硬编码书写,后期一旦表结构更改,则会带来很大的修改工作量,维护性较差
使用:
更新为例:前置
User user = new User();
user.setUserName("张三丰");
1: 获取 lmd 的 组装器
LambdaQueryWrapper wrapper = Wrappers.lambdaQuery();
2: 组装条件
wrapper.eq(User::getId, 15);
3: Mapper对象执行查询
userMapper.update(user, wrapper);// 要更新进去的值 , 条件
LambdaQueryWrapper wrapper = Wrappers.lambdaQuery().eq(User::getUserName, "武大郎");
int i = userMapper.delete(wrapper);
// 参数1: 最新的值
User user = new User();
user.setUserName("张三丰");
// 参数2:更新时条件
LambdaQueryWrapper wrapper = Wrappers.lambdaQuery();
wrapper.eq(User::getId, 15);
//开始更新
int update = userMapper.update(user, wrapper);
package com.itheima;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.mapper.UserMapper;
import com.itheima.pojo.User;
import com.itheima.service.UserService;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.omg.PortableInterceptor.USER_EXCEPTION;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
/**
* @Description
* @Created by itheima
*/
@SpringBootTest
public class MpTestService {
@Autowired
private UserService userService;
/**
* @Description 测试查询操作 根据id查询
*/
@Test
public void test1(){
User user = userService.getById(3l);
System.out.println(user);
}
/**
* @Description 测试条件查询,且仅返回一个
* getOne:sql查询的结果必须为1条或者没有,否则报错 !!!!
*/
@Test
public void test2(){
LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(User.class);
wrapper.gt(User::getAge,20);
User one = userService.getOne(wrapper);
System.out.println(one);
}
/**
* @Description 根据条件批量查询
*/
@Test
public void test3(){
LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(User.class);
wrapper.gt(User::getAge,20);
List list = userService.list(wrapper);
System.out.println(list);
}
/**
* @Description 根据条件批量查询并分页
*/
@Test
public void test4(){
LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(User.class);
wrapper.gt(User::getAge,20);
//构建分页对象
IPage page=new Page<>(2,3);
userService.page(page,wrapper);
System.out.println(page.getRecords());
System.out.println(page.getPages());
System.out.println(page.getTotal());
}
/**
* @Description 测试服务层save保存单条操作
*/
@Test
public void test5(){
User user1 = User.builder().name("wangwu").userName("laowang4").
email("[email protected]").age(20).password("333").build();
boolean isSuccess = userService.save(user1);
System.out.println(isSuccess?"保存成功":"保存失败");
}
/**
* @Description 测试服务层批量保存
*/
@Test
public void test6(){
User user2 = User.builder().name("wangwu2").userName("laowang2").
email("[email protected]").age(20).password("333").build();
User user3 = User.builder().name("wangwu3").userName("laowang3").
email("[email protected]").age(20).password("333").build();
boolean isSuccess = userService.saveBatch(Arrays.asList(user2, user3));
System.out.println(isSuccess?"保存成功":"保存失败");
}
/**
* @Description 根据id删除操作
*/
@Test
public void test7(){
boolean isSuccess = userService.removeById(17l);
System.out.println(isSuccess?"保存成功":"保存失败");
}
/**
* @Description 根据条件批量删除
*/
@Test
public void test8(){
LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(User.class);
wrapper.gt(User::getId,12)
.gt(User::getAge,20);
boolean remove = userService.remove(wrapper);
System.out.println(remove);
}
/**
* @Description 测试根据id更新数据
*/
@Test
public void test9(){
//UPDATE tb_user SET password=?, t_name=? WHERE id=?
User user2 = User.builder().name("wangwu2").password("333").id(3l).build();
boolean success = userService.updateById(user2);
System.out.println(success);
}
/**
* @Description 测试根据条件批量更新
*/
@Test
public void test10(){
LambdaUpdateWrapper wrapper = Wrappers.lambdaUpdate(User.class);
//UPDATE tb_user SET age=? WHERE (id IN (?,?,?))
wrapper.in(User::getId,Arrays.asList(1l,3l,5l)).set(User::getAge,40);
boolean update = userService.update(wrapper);
System.out.println(userService);
}
}
逻辑删除:表里设置一个删除字段,0表示存在,1表示删除。
后续删除变成更新,删除字段由0变成1,表示已删除。(但数据依然存在)
1:配置文件
# 设置mp运行时行为
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 控制台输出sql
global-config:
db-config:
logic-delete-field: deleted # 约定全局删除字段
logic-delete-value: 1
logic-not-delete-value: 0
2:添加一个字段表示逻辑删除
/**
* 如果变的名称与实体类名称一致,该注解可省略
*/
@TableName("tb_user")
public class User {
//......
@TableLogic//指定逻辑删除字段
private Integer deleted;
}
3:表里添加删除字段
后续执行删除,删除语句变为更新语句
//根据id删除
int count = userMapper.deleteById(15l);
后续执行查询:
底层自动在SQL语句追加删除字段为0.表示查询还存在的
1:实体类设置Fill
@TableName("tb_user")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
//指定插入时自动填充的字段
@TableField(value = "create_time",fill = FieldFill.INSERT)//这里!!!
private Date createTime;
//自定插入或者更新时自动填充的字段
@TableField(value = "update_time",fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
2:配置填充规则
@Component
public class FillDataHandler implements MetaObjectHandler {
/**
* 定义自动填充的方法
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
//设置insert操作时的时间点
metaObject.setValue("createTime",new Date());
//设置update操作时的时间点
metaObject.setValue("updateTime",new Date());
}
/**
* 定义更新时填充的方法
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
//设置update操作时的时间点
metaObject.setValue("updateTime",new Date());
}
}
1:配置Bean
/**
* 注册插件
* @return
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
//构建mp的插件注册器bean,通过该bean可批量注册多个插件
MybatisPlusInterceptor plusInterceptor = new MybatisPlusInterceptor();
//配置乐观锁拦截器
OptimisticLockerInnerInterceptor optimisticLockerInnerInterceptor = new OptimisticLockerInnerInterceptor();
//注册
plusInterceptor.addInnerInterceptor(optimisticLockerInnerInterceptor);
return plusInterceptor;
}
2:表里添加version字段
3:实体类添加version字段,并加version注解
@TableName("tb_user")public class User {
@Version
private Integer version;
}
/**
* @Description 测试乐观锁
*/
@Test
public void testOp(){
//这点要保证update中要设置之前的version
User user = userMapper.selectById(5l);
System.out.println(user);
user.setName("zws777");
userMapper.updateById(user);
}
原理:
每次修改version+1,执行更新,将version作为条件