title: mybatis_plus
date: 2023-09-03 21:06:27
tags:
mybatis_plusreviews
约定大于配置
默认
当我们要使用mybatisplus的时候 我们需要去集成mp提供的BaseMapper
public interface UserMapper extends BaseMapper
关于mybatisplus常用注解
注解到类上
@TableName(“表名”) 用来解决 数据库表对应到java实体 符合驼峰命名
注解到字段
@TableId 默认是id为映射字段 可以自己指定 注意(一个实体对应一个表只有一个主键)
mybatisplus不支持联合主键
private Long id;
1.0@TableField(“isMarried”)
作用 解决实体属性与数据库字段不一致情况
作用二、
@TableField(“isMarried”)
private Boolean isMarried 在对应到mybatisplus 查询语句时会自动去掉is 对应数据库 的Married字段
作用三、
@TableField(“order”)
private Stringi order;
实体名字与mysql的保留关键字冲突
@exist()
是否是数据库字段
mybatisplus的配置可以替代mybatis的配置
mybatis-plus:
type-aliases-package: com.itheima.mp.domain.po
global-config:
db-config:
id-type: *auto
* logic-delete-field: deleted # *逻辑删除字段
* configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
mybatis支持各种复杂的where条件
demo
@Test
public void test(){
List<User> users = userMapper.queryUserByIds(List.of(1L, 2L, 3L));
users.forEach(System.out::println);
}
@Test
public void testdemo01(){
//1.构建查询条件
QueryWrapper<User> objectQueryWrapper = new QueryWrapper<User>()
.select("id", "username","info","balance")
.like("username","o")
.ge("balance",1000);
List<User> users = userMapper.selectList(objectQueryWrapper);
for (User user : users) {
System.out.println(user.toString());
}
}
@Test
public void testqueryWrapper(){
User user = new User();
user.setBalance(2000);
//1.构建查询条件
QueryWrapper<User> objectQueryWrapper = new QueryWrapper<User>()
.eq("username","jack");
userMapper.update(user,objectQueryWrapper);
}
@Test
public void testUpdateWrapper(){
UpdateWrapper<User> in = new UpdateWrapper<User>().setSql("balance=balance-200")
.in("id",List.of(1L, 2L, 4L));
userMapper.update(null,in);
}
@Test
public void testLamdaQueryWrapper(){
//1.构建条件
QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();
LambdaQueryWrapper<User> userLambdaQueryWrapper = objectQueryWrapper.lambda().select(User::getId, User::getUsername, User::getBalance
, User::getInfo).like(User::getUsername, "0")
.ge(User::getBalance, 1000);
List<User> users = userMapper.selectList(userLambdaQueryWrapper);
}
}
lamdaQueryWrapper
示例
LambdaQueryWrapper<User> userLambdaQueryWrapper = lamdQueryWrapper.lambda().select(User::getId, User::getUsername, User::getBalance
, User::getInfo).like(User::getUsername, "0")
.ge(User::getBalance, 1000);
自定义sql
思想就是 我们where之后的判断条件采用mtbatis构建的并且采用${} 拼接到我们自己的
示例
首先定义一个queryWrapper传给自己的方法 也就是定义在mapper中的方法
//定义条件
QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();
objectQueryWrapper.lambda().in(User::getId,longs);
//2.执行更新
userMapper.updateBalanceByWrapper(200,objectQueryWrapper);
mapper 注意mapper中只能用@Param(“ew”) 来接收自定义的条件 这是规定
@Update("UPDATE user SET balance = balance - #{amount} ${ew.customSqlSegment}")
void updateBalanceByWrapper(@Param("amount") int amount, @Param("ew") QueryWrapper<User> wrapper);
该方法对应到Mapper.xml
<select id="queryUsersByWrapper" resultType="com.itheima.mp.domain.po.User">
SELECT u.*
FROM user u
INNER JOIN address a on u.id = a.user_id
${ew.customSqlSegment}
</select>
因为mybatisplus没办法做多表查询 我们可以使用自定义sql来实现都多表查询
List<Long> longs = List.of(1L, 2L, 3L);
//定义条件
QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();
new QueryWrapper<User>().in("u.id",longs)
.eq("a.city","中国");
//2.执行更新
List<User> users = userMapper.queryUsersByWrapper(objectQueryWrapper);
xml文件
<select id="queryUsersByWrapper" resultType="com.itheima.mp.domain.po.User">
SELECT u.*
FROM user u
INNER JOIN address a on u.id = a.user_id
${ew.customSqlSegment}
</select>
UPDATE user SET balance = balance - #{amount} ${ew.customSqlSegment}
@Test
public void testCustomSql(){
List<Long> longs = List.of(1L, 2L, 3L);
//定义条件
QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();
objectQueryWrapper.lambda().in(User::getId,longs);
//2.执行更新
userMapper.updateBalanceByWrapper(200,objectQueryWrapper);
}
在UserMapper接口
@Update("UPDATE user SET balance = balance - #{amount} ${ew.customSqlSegment}")
void updateBalanceByWrapper(@Param("amount") int amount, @Param("ew") QueryWrapper<User> wrapper);
@Test
public void testJoinCustomSql(){
List<Long> longs = List.of(1L, 2L, 3L);
//定义条件
QueryWrapper<User> objectQueryWrapper = new QueryWrapper<>();
new QueryWrapper<User>().in("u.id",longs)
.eq("a.city","中国");
//2.执行更新
List<User> users = userMapper.queryUsersByWrapper(objectQueryWrapper);
}
mapper接口
List<User> queryUsersByWrapper(@Param("ew") QueryWrapper<User> wrapper);
该方法对应到Mapper.xml
<select id="queryUsersByWrapper" resultType="com.itheima.mp.domain.po.User">
SELECT u.*
FROM user u
INNER JOIN address a on u.id = a.user_id
${ew.customSqlSegment}
</select>
Service接口
批处理记得开启mysql的 rewriteBatchedStatements=true 重写批处理方案 oracle默认开启
如果不开启则是每次追加追加sql语句 即
insetinto tablename values(?????)
每次insert都是把我们的数据填充到问号中 而不是 直接拼接后values(1,2,3,4,5),(1,2,3,4,5)
开启之后就是 values(1,2,3,4,5),(1,2,3,4,5)这种拼接 就是只执行一次sql
url: jdbc:mysql://127.0.0.1:3306/mp?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true
service层面 的lamdaQuery()
示例 注意在service层面写的lamdaQuery()
或者lamdaUpdate 条件的最后要追加执行的动作
例如
.one();
.list();
.update(); // 执行update
userService.lambdaQuery().
eq(User::getUsername,"jack")
.one();
User user = userService.lambdaQuery()
.eq(User::getUsername, "Rose")
.one();
System.out.println("user = " + user);
List<User> list = userService.lambdaQuery()
.like(User::getUsername, "o")
.list();
list.forEach(System.out::println);
Long count = userService.lambdaQuery()
.like(User::getUsername, "o")
.count();
System.out.println("count = " + count);
动态sql查询示例
return userService.lambdaQuery()
.like(username != null, User::getUsername, username)
.eq(status != null, User::getStatus, status)
.gt(min != null, User::getBalance, min)
.lt(max != null, User::getBalance, max)
.list();
userService.lambdaUpdate()
.set(User::getBalance, balance)
.set(balance == 0, User::getStatus, 2)
.eq(id != null, User::getId, id)
.eq(username != null, User::getUsername, username)
.update(); // 执行update
问题 为了解决循环依赖问题 mybatisplus 提供了静态工具类 DB
循环依赖
举例
usersevice 需要adreeservice
adreevice又需要 uservice
我们在userservice注入addressservice
在addressvice 注入uservice 就会出现循环依赖问题
DB 类
Db.save(user);
List<User> list = Db.list(new QueryWrapper<User>().like("username", "o"));
User user = Db.lambdaQuery(User.class)
.eq(User::getUsername, "Rose")
.one();
Long count = Db.lambdaQuery(User.class)
.like(User::getUsername, "o")
.count();
Db.lambdaQuery(User.class)
.like(username != null, User::getUsername, username)
.eq(status != null, User::getStatus, status)
.gt(min != null, User::getBalance, min)
.lt(max != null, User::getBalance, max)
.list();
Db.lambdaUpdate(User.class)
.set(User::getBalance, balance)
.set(balance == 0, User::getStatus, 2)
.eq(id != null, User::getId, id)
.eq(username != null, User::getUsername, username)
.update(); // 执行update
mybatisplus设置逻辑删除字段
mybatis会自动检测我们的删除字段
在我们执行删除操作的时候会替代成逻辑删除
mybatis-plus:
type-aliases-package: com.itheima.mp.domain.po
global-config:
db-config:
id-type: auto
logic-delete-field: deleted # 逻辑删除字段
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
枚举转换器 JSON处理器 不实用
需要配置mybatis的配置设置一个美剧转换器
并且在枚举类加上注解
@EnumValue
@Getter
public enum UserStatus {
NORMAL(1, "正常"),
FREEZE(2, "冻结"),
;
@EnumValue
private final int value;
@JsonValue
private final String desc;
UserStatus(int value, String desc) {
this.value = value;
this.desc = desc;
}
}
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
JSON
@TableField(typeHandler = JacksonTypeHandler.class)
private UserInfo info;
myabatisplus分页插件
CV 大法好
首先 mybatisplus的分页插件基于 mybatis的 interceptor
先注册好核心拦截器 配置好mp的拦截器配置
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor(){
// 1.创建核心拦截器
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 2.创建插件
PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
paginationInnerInterceptor.setMaxLimit(1000L);
interceptor.addInnerInterceptor(paginationInnerInterceptor);
// 返回
return interceptor;
}
注意mybatis的分页插件条件时page对象
返回的数据也是page对象
@Test
void testPageQuery() {
int pageNo = 1, pageSize = 5;
// 1.分页条件
Page<User> p = Page.of(pageNo, pageSize);
// 2.排序条件
p.addOrder(new OrderItem("balance", false));
// 3.查询
Page<User> page = userService.page(p);
// 4.分页结果
long total = page.getTotal();
System.out.println("total = " + total);
long pages = page.getPages();
System.out.println("pages = " + pages);
List<User> records = page.getRecords();
for (User record : records) {
System.out.println("record = " + record);
}
}
工具
List users=p.getRecords();
UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
加粗样式