扩展功能
P12 扩展功能-代码生成器
- 方法一:mybatisplus官方文档中的代码生成配置
- 方法二:插件mybatsx
- 方法三:插件mybatisplus
P13 DB静态工具
iservice中的方法是非静态的,db方法是静态的。
静态方法无法读取到类的泛型的,也就无法知道实体类类型、表信息,可以看到方法中都需要传额外参数,即实体类的字节码,以得到相关信息。
例如:可能会存在两个service相互注入的情况,即循环依赖,如何解决?
使用静态工具进行解决,(静态工具和iservice用法差不多,就是额外传入字节码),但是这样能够避免注入service,避免了循环依赖。(当然也可以不适用iservice中的方法,也可以使用mapper中的方法)
示例:根据用户id查询用户信息,以及用户地址信息并返回;
@Override public UserVO queryUserAndAddressById(Long id){ // 查询用户信息 User user = getById(id); if (user == null || user.getStatus() == UserStatus.FROZEN){ throw new RuntimeException("用户状态异常"); } UserVO userVO = BeanUtil.copyProperties(user, UserVO.class); // 查询用户地址,地址表一个用户多个地址 // 使用lambdaquery,避免相互依赖,使用DB静态方法 List<Address> addresses = Db.lambdaQuery(Address.class) .eq(Address::getUserId, id) .list(); if (CollUtil.isNotEmpty(addresses)){ userVO.setAddresses(BeanUtil.copyToList(addresses, AddressVO.class)); } return userVO; // 没有自己写sql就实现了业务操作 }
讯享网
P14 扩展功能-DB静态工具2
例如:实现批量查询用户,同时查询出用户地址信息。
注意查询地址信息,需要先获取用户的id集合,参数ids就是一个集合,如果以后再遇到这种,可以使用stream流从用户对象从获取到用户id的结合,例如:
List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
讯享网@Override public List<UserVO> queryUserAndAddressByIds(List<Long> ids){ // 查询用户 List<User> users = listByIds(ids); if (CollUtil.isEmpty(users)){ return Collections.emptyList(); } // 方法参数传入的ids可能为空 List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList()); // 查询地址 List<Address> addresses = Db.lambdaQuery(Address.class) .in(Address::getUserId, userIds) .list(); // 转换地址VO List<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class); // 将用户地址分组, Map<Long, List<AddressVO>> addressMap = new HashMap<>(0); if (CollUtil.isNotEmpty(addressVOList)){ addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId)); // 依据用户id进行分组 } // 转为VO返回 List<UserVO> list = new ArrayList<>(users.size()); for (User user : users){ UserVO userVO = BeanUtil.copyProperties(user, UserVO.class); list.add(userVO); userVO.setAddresses(addressMap.get(user.getId())); } return list; }
P15 扩展功能-逻辑删除
逻辑删除就是基于代码逻辑模拟删除效果,但并不会真正删除数据
- 在表中添加一个字段标记数据是否被删除
- 当删除数据时置该字段为1
- 查询时只查询标记为0的数据
这种功能mybatisplus已经提供了,直接帮我们在底层自动修改CRUD语句,在application.yaml中配置逻辑删除的字段名和值即可。
例如:
mybatis-plus: type-aliases-package: com.itheima.mp.domain.po # 别名扫描包 global-config: db-config: id-type: auto # 配置id生成的策略,如果是雪花算法就是assign_id logic-delete-field: deleted # 配置逻辑删除字段 update-strategy: not_null # 更新策略,只更新非空字段
逻辑删除也会存在问题:
- 垃圾数据越来越多
- sql中全都需要对逻辑删除字段进行判断,影响查询效率
替代方案,采用数据迁移的方式
P16 扩展功能-枚举处理器
使用枚举类型。
问题:java中的枚举类型与数据库中的int类型相互转换问题。这个问题是mybatis实现的。
mybatisplus加入了几个类型处理器,就有MybatisEnumTypeHandler。
先配置:
讯享网mybatis-plus: configuration: default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler
加注解:
@EnumValue private final int value; // 对应数据库中的值
我们定义的枚举类是UserStatus,修改用户实体类中的status的类型为这个枚举类型而不是int类型。
讯享网 / * 使用状态(1正常 2冻结) */ private UserStatus status;
枚举返回前端默认是枚举项的名字,返回给前端的显示值,使用注解jsonvalue,可以自定义返回
@JsonValue private final String desc;
P17 扩展功能-JSON处理器
mybatis plus还提供了AbstractJsonTypeHandler转换器,实现java和json的转换
例如数据库中info字段存储的json类型,如下图:

在java中使用这类数据,如果读取到再将字符串转换为可用的数据比较麻烦,可以考虑定义一个这种json格式的实体,然后使其变成这个对象,mybatis没有提供这个类型处理器,mybatis plus提供了。

例如:
讯享网 / * 详细信息 */ @TableField(typeHandler = JacksonTypeHandler.class) // 定义类型处理器 private UserInfo info;
还要开启自动的结果映射
@Data @TableName(value = "user", autoResultMap = true) // 自动结果映射 public class User {
插件功能
mybatis plus提供的内置拦截器有:

P18 分页插件
之间使用了PageHelper,
使用mybatis plus中的分页插件,首先配置,
讯享网@Configuration public class MyBatisConfig { @Bean // 声明一个bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 创建核心插件 ,可以往里面加插件 // 1.创建分页插件 PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);// 分页内置拦截器 paginationInnerInterceptor.setMaxLimit(1000L);// 最多1000条 // 2.添加分页插件 interceptor.addInnerInterceptor(paginationInnerInterceptor); // 可以添加插件 return interceptor; } }
使用分页的API,返回page结果

使用示例:
@Test void testPageQuery() { int pageNo = 1, pageSize = 2; // 1.准备分页条件 // 1.1.分页条件 Page<User> page = Page.of(pageNo, pageSize); // 创建page对象 // 1.2.排序条件 page.addOrder(new OrderItem("balance", true)); page.addOrder(new OrderItem("id", true)); // 2.分页查询 Page<User> p = userService.page(page); // 3.解析 long total = p.getTotal(); System.out.println("total = " + total); long pages = p.getPages(); System.out.println("pages = " + pages); List<User> users = p.getRecords(); users.forEach(System.out::println); }
P19 通用分页实体
例如:

从接收处理到业务逻辑实现到返回。
如果单独在UserDTO中实现,加入AddressDTO中也有分页需求,又要写。所以可以设计统一的分页查询请求,即公共分页类。
讯享网@Data @ApiModel(description = "分页查询实体") public class PageQuery { @ApiModelProperty("页码") private Integer pageNo = 1; @ApiModelProperty("页码") private Integer pageSize = 5; @ApiModelProperty("排序字段") private String sortBy; @ApiModelProperty("是否升序") private Boolean isAsc = true; public <T> Page<T> toMpPage(OrderItem ... items){ // 1.分页条件 Page<T> page = Page.of(pageNo, pageSize); // 2.排序条件 if(StrUtil.isNotBlank(sortBy)){ // 不为空 page.addOrder(new OrderItem(sortBy, isAsc)); }else if(items != null){ // 为空,默认排序 page.addOrder(items); } return page; } public <T> Page<T> toMpPage(String defaultSortBy, Boolean defaultAsc){ return toMpPage(new OrderItem(defaultSortBy, defaultAsc)); } public <T> Page<T> toMpPageDefaultSortByCreateTime(){ return toMpPage(new OrderItem("create_time", false)); } public <T> Page<T> toMpPageDefaultSortByUpdateTime(){ return toMpPage(new OrderItem("update_time", false)); } }
userquery继承这个分页查询实体即可。
可以定义pageDTO,
@Data @ApiModel(description = "分页结果") public class PageDTO<T> { @ApiModelProperty("总条数") private Long total; @ApiModelProperty("总页数") private Long pages; @ApiModelProperty("集合") private List<T> list; // 泛型T,不知道具体哪种类型 public static <PO, VO> PageDTO<VO> of(Page<PO> p, Class<VO> clazz){ PageDTO<VO> dto = new PageDTO<>(); // 1.总条数 dto.setTotal(p.getTotal()); // 2.总页数 dto.setPages(p.getPages()); // 3.当前页数据 List<PO> records = p.getRecords(); if (CollUtil.isEmpty(records)) { dto.setList(Collections.emptyList()); return dto; } // 4.拷贝user的VO dto.setList(BeanUtil.copyToList(records, clazz)); // 5.返回 return dto; } public static <PO, VO> PageDTO<VO> of(Page<PO> p, Function<PO, VO> convertor){ PageDTO<VO> dto = new PageDTO<>(); // 1.总条数 dto.setTotal(p.getTotal()); // 2.总页数 dto.setPages(p.getPages()); // 3.当前页数据 List<PO> records = p.getRecords(); if (CollUtil.isEmpty(records)) { dto.setList(Collections.emptyList()); return dto; } // 4.拷贝user的VO dto.setList(records.stream().map(convertor).collect(Collectors.toList())); // 5.返回 return dto; } }

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/38403.html