Mybatis plue(二) 扩展功能、插件功能

扩展功能

P12 扩展功能-代码生成器

  • 方法一:mybatisplus官方文档中的代码生成配置

  • 方法二:插件mybatsx

  • 方法三:插件mybatisplus

P13 DB静态工具

iservice中的方法是非静态的,db方法是静态的。

静态方法无法读取到类的泛型的,也就无法知道实体类类型、表信息,可以看到方法中都需要传额外参数,即实体类的字节码,以得到相关信息。

例如:可能会存在两个service相互注入的情况,即循环依赖,如何解决?

使用静态工具进行解决,(静态工具和iservice用法差不多,就是额外传入字节码),但是这样能够避免注入service,避免了循环依赖。(当然也可以不适用iservice中的方法,也可以使用mapper中的方法)

示例:根据用户id查询用户信息,以及用户地址信息并返回;

@Overridepublic 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());

@Overridepublic 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();// 转换地址VOList<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_idlogic-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 // 声明一个beanpublic 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结果

在这里插入图片描述

使用示例:

   @Testvoid 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的VOdto.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的VOdto.setList(records.stream().map(convertor).collect(Collectors.toList()));// 5.返回return dto;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/593820.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2024年DeFi的四大主导趋势:Restaking、Layer3、AI和DePin

DeFi&#xff08;去中心化金融&#xff09;行业在2024年将继续呈现快速增长的势头&#xff0c;驱动这一增长的主要因素将是四大主导趋势&#xff1a;Restaking、Layer3、AI和DePin。这些趋势将推动DeFi生态系统的发展&#xff0c;为用户提供更多的机会和创新。 趋势1&#xff…

【Linux】第二个小程序--简易shell

请看上面的shell&#xff0c;其本质就是一个字符串&#xff0c;我们知道bash本质上就是一个进程&#xff0c;只不过命令行就是一个输出的字符串&#xff0c; 我们输入的命令“ls -a -l”实际上是我们在输入行输入的字符串&#xff0c;所以&#xff0c;如果我们想要做一个简易的…

Redis从入门到精通(五)Redis实战(二)商户查询缓存

↑↑↑请在文章头部下载测试项目原代码↑↑↑ 文章目录 前言4.2 商户查询缓存4.2.1 缓存介绍4.2.2 查询商户信息的传统做法4.2.2.1 接口文档4.2.2.2 代码实现4.2.2.3 功能测试 4.2.3 查询商户信息添加Redis缓存4.2.3.1 逻辑分析4.2.3.2 代码实现4.2.3.3 功能测试 4.2.3 数据一致…

MySQL基础【语句执行顺序】

一个SQL语句它的执行顺序对于我们思考题意有着很重要的关系 题意就是&#xff1a;找出哪些只逛超市不买单的人&#xff08;买单0元也算哦&#xff0c;可能是使用的是代金券吧&#xff09; 看到此题关键找出两个数据 参观过的人 和 买单的人 他们的差就是白嫖的人&#xff08;支…

H.264 压缩与编解码原理

H.264 压缩与编解码原理 H.264 压缩与编解码原理H.264 简介视频编码的总体思路H.264 压缩技术帧内预测压缩什么是空间冗余&#xff1f;具体预测方法 帧间预测压缩什么是时间冗余&#xff1f;具体预测方法&#xff1a;运动估计 概念&#xff1a;Group of Pictures&#xff08;GO…

LC 96.不同的二叉搜索树

96.不同的二叉搜索树 给你一个整数 n &#xff0c;求恰由 n 个节点组成且节点值从 1 到 n 互不相同的 二叉搜索树 有多少种&#xff1f;返回满足题意的二叉搜索树的种数。 示例 1&#xff1a; 输入&#xff1a; n 3 输出&#xff1a; 5 示例 2&#xff1a; 输入&#xff1a;…

【JavaSE】接口 详解(上)

前言 本篇会讲到Java中接口内容&#xff0c;概念和注意点可能比较多&#xff0c;需要耐心多看几遍&#xff0c;我尽可能的使用经典的例子帮助大家理解~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 接口 语法…

SQL Server详细安装使用教程

1.安装环境 现阶段基本不用SQL Server数据库了&#xff0c;看到有这样的分析话题&#xff0c;就把多年前的存货发一下&#xff0c;大家也可以讨论看看&#xff0c;思路上希望还有价值。 SQL Server 2008 R2有32位版本和64位版本&#xff0c;32位版本可以安装在Windows XP及以上…

函数式编程(一)

函数式编程总体介绍 函数式编程(functional programming)其实是个很古老的概念&#xff0c;诞生距今快60年啦&#xff01; 最古老的函数式编程语言Lisp 新出现的函数式编程语言&#xff1a;比如Erlang、Scala、clojure等 热门语言&#xff1a;Python、java、JavaScript、C等…

【洛谷 P8655】[蓝桥杯 2017 国 B] 发现环 题解(邻接表+并查集+路径压缩)

[蓝桥杯 2017 国 B] 发现环 题目描述 小明的实验室有 N N N 台电脑&#xff0c;编号 1 ∼ N 1 \sim N 1∼N。原本这 N N N 台电脑之间有 N − 1 N-1 N−1 条数据链接相连&#xff0c;恰好构成一个树形网络。在树形网络上&#xff0c;任意两台电脑之间有唯一的路径相连。 …

拓扑排序--有向无环图中一个节点的所有祖先

题目描述 给你一个正整数 n &#xff0c;它表示一个 有向无环图 中节点的数目&#xff0c;节点编号为 0 到 n - 1 &#xff08;包括两者&#xff09;。 给你一个二维整数数组 edges &#xff0c;其中 edges[i] [fromi, toi] 表示图中一条从 fromi 到 toi 的单向边。 请你返…

OAuth 2.0 的四种方式

RFC 6749 OAuth 2.0 的标准是 RFC 6749 文件。该文件先解释了 OAuth 是什么。 OAuth 引入了一个授权层&#xff0c;用来分离两种不同的角色&#xff1a;客户端和资源所有者。…资源所有者同意以后&#xff0c;资源服务器可以向客户端颁发令牌。客户端通过令牌&#xff0c;去请…