代码生成器
作用:生成相对固定的PO、Mapper、Service等相关代码
步骤
安装插件

安装好后重启idea
在"工具"一栏里有相关的两个选项


先点击"Config Database"配置数据库

测试连接成功后点击ok
然后点击"Code Generator",弹窗如下

最上方是选择要对那个表生成代码,可以多选
module栏:如果是聚合工程并且当前模块为子模块,需要填写为该子模块的名字(如果不符合则不用填写这一栏)
package栏:填写代码生成的父级包路径
例:
如图

则填写红框框起来的部分,因为PO、Mapper、Service都在该包下
author栏:作者
over file选项:勾选上表示生成代码覆盖原来的代码
Entity:勾选上表示要生成实体类,栏里填写要生成在哪一个包下
Mapper、Controller、Service、ServiceImpl类似Entity
TablePrefix栏:前缀,如果表名有前缀并且生成代码的时候想要忽略这个前缀,则填写
最下方一栏选项是注解,勾选上则生成对应的注解
写完后点击右下角"code generator"即可生成代码,亲测有效~
DB静态工具
作用:避免循环依赖
maven坐标:MyBatis-Plus 的 Starter 依赖已经包含,不用单独再导入
案例
需求:
1.改造根据id查询用户的接口,查询用户的同时,查询出用户对应的所有地址
Controller
java
@GetMapping("{id}")
@ApiOperation("根据id查询用户")
public UserVO queryUserById(@ApiParam("用户ID") @PathVariable Long id){
return userService.queryUserAndAddressById(id);
}
Service实现类
java
@Override
public UserVO queryUserAndAddressById(Long id) {
// 查询用户
User user = getById(id);
if (user == null|| user.getStatus() == 2){
throw new RuntimeException("用户状态异常!");
}
// 查询地址
List<Address> addresses = Db.lambdaQuery(Address.class)
.eq(Address::getUserId, id)
.list();
// 封装VO
// 转User的PO为VO
UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
// 转地址VO
if (CollUtil.isNotEmpty(addresses)){
userVO.setAddresses(BeanUtil.copyToList(addresses, AddressVO.class));
}
return null;
}
2.改造根据id批量查询用户的接口,查询用户的同时,查询出用户对应的所有地址
Controller
java
@GetMapping
@ApiOperation("根据id批量查询用户")
public List<UserVO> queryUserById(@ApiParam("用户ID集合") @RequestParam List<Long> ids){
return userService.queryUserAndAddressByIds(ids);
}
Service实现类
java
@Override
public List<UserVO> queryUserAndAddressByIds(List<Long> ids) {
// 查询用户
List<User> users = listByIds(ids);
if (CollUtil.isEmpty(users)) {
return Collections.emptyList();
}
// 查询地址
// 获取用户id集合
List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
// 根据用户id查询地址
List<Address> addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();
// 转换地址VO
List<AddressVO> addressVOS = BeanUtil.copyToList(addresses, AddressVO.class);
// 用户地址集合分组处理,相同用户的放入一个集合(组)中
Map<Long, List<AddressVO>> addressVOMap = new HashMap<>();
if (CollUtil.isEmpty(addresses)) {
addressVOMap = addressVOS.stream().collect(Collectors.groupingBy(AddressVO::getUserId));
}
// 转VO返回
List<UserVO> list = new ArrayList<>(users.size());
for (User user : users) {
// 转User的PO为VO
UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
// 转地址VO
userVO.setAddresses(addressVOMap.get(user.getId()));
list.add(userVO);
}
return list;
}
逻辑删除
逻辑删除就是基于代码逻辑模拟删除效果,但并不会真正删除数据。思路如下:
- 在表中添加一个字段标记数据是否被删除
- 当删除数据时把标记置为1
- 查询时只查询标记为0的数据
那这样一来,查询语句后面都需要加上deleted=0的条件,但是mp的方法没有这个条件,怎么办?
MybatisPlus提供了逻辑删除功能,无需改变方法调用的方式,而是在底层帮我们自动修改CRUD的语句。我们要做的就是在application.yaml文件中配置逻辑删除的字段名称和值即可:
mybatis-plus:
type-aliases-package: com.itheima.mp.pojo
global-config:
db-config:
logic-delete-field: deleted # 配置逻辑删除字段(自定义,与表中该字段对应)
logic-delete-value: 1 # 逻辑已删除值(默认为1)
logic-not-delete-value: 0 # 逻辑未删除值(默认为0)
配置了之后,删除某条数据实际就是把某条数据的deleted字段设置为1,并不会真的从数据库中删除
枚举处理器
当实体类中某个变量的值的数量比较固定,并且每个值对应某一种描述时,推荐使用枚举
比如:1表示账号正常,2表示账号冻结
这时候就把实体类中的status字段定义为枚举类型,但是数据库怎么根据自定义的枚举类型来判断操作数是什么呢?这时就用到了mp的枚举处理器
使用步骤:
- 加@EnumValue注解
- 配置yaml文件
案例
实体类
java
@Data
public class User {
/**
* 使用状态(1正常 2冻结)
*/
private UserStatus status;
}
枚举类
java
@Getter
public enum UserStatus {
NORMAL(1, "正常"),
FREEZE(2, "冻结");
@EnumValue
private final int value;
private final String desc;
UserStatus(int value, String desc) {
this.value = value;
this.desc = desc;
}
}
@EnumValue是mp提供的注解,表示哪个值是数据库增删改查时实际需要操作的数,比如上述就是value的值是数据库增删改查时实际需要操作的数
yaml文件配置
java
mybatis-plus:
configuration:
default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
搞定!
注意:
- PO对应的DTO和VO如果存在相互拷贝的情况,都需要改成自定义的枚举类型
- 默认返回给前端的值为枚举项的名字,以案例为例,比如"NORMAL",如果需要返回value,则在value上方加上注解 @JsonValue
JSON处理器
实体类中某个字段存储的是json格式的数据,并且想处理里面的某个数据时,需要单独定义一个类,那么这个数据库怎么存储这个类呢?这时就用到了mp的JSON处理器
使用方式:
- 给该字段加上@TableField(typeHandler = JacksonTypeHandler.class)
- 给该实体类加上@TableName(autoResultMap = true)
案例
User类
java
@Data
@TableName(value = "user", autoResultMap = true)
public class User {
/**
* 详细信息
*/
@TableField(typeHandler = JacksonTypeHandler.class)
private UserInfo info;
}
UserInfo类
java
@Data
@AllArgsConstructor(staticName = "of") // UserInfo.of(...) 等同于 new UserInfo(...)
@NoArgsConstructor
public class UserInfo {
private Integer age;
private String intro;
private String gender;
}
搞定!