当前位置: 首页 > news >正文

MyBatisPlus-03-扩展功能

文章目录

  • 【README】
  • 【1】基于MyBatisPlus的代码生成器
  • 【2】MyBatisPlus-DB静态工具
    • 【2.1】使用MyBatisPlus的DB静态工具查询单个及多个用户地址
      • 【查询单个用户的访问效果】
      • 【查询多个用户的访问效果】
  • 【3】逻辑删除
    • 【3.1】代码实现
  • 【4】枚举处理器
    • 【4.1】代码实现
  • 【5】JSON处理器
    • 【5.1】代码实现

【README】

本文代码参见: https://github.com/TomJourney/mybatis-plus-test

本文介绍MyBatisPlus扩展功能,如下;

  • 代码生成;
  • 静态工具;
  • 逻辑删除;
  • 枚举处理器;
  • json处理器;


【1】基于MyBatisPlus的代码生成器

方法1:使用代码生成代码,官方文档:https://baomidou.com/guides/new-code-generator/

或者使用MyBatisGenerator插件:https://www.cnblogs.com/marEstrelado/articles/15930280.html



【2】MyBatisPlus-DB静态工具

1)引入DB静态工具的原因:

  • 原因1:IService仅用于spring单例bean,若是工具类,则无法使用IService或ServiceImpl的接口;
  • 原因2:若存在一个请求需要查询多张表,则可能存在IService实现类的springbean相互引用的问题;

所以引入DB静态工具,使得工具类也可以使用MyBatisPlus提供的增删改查api;

2)业务需求:

  • 需求1:改造根据id查询用户的接口,查询用户的同时,也查询用户对应地址;
  • 需求2:改造根据id批量查询用户的接口,查询用户的同时,查询批量用户对应的地址;


【2.1】使用MyBatisPlus的DB静态工具查询单个及多个用户地址

【UseStaticApiRestfulUserController】

@RestController
@RequestMapping("/staticdb/restful/user")
@RequiredArgsConstructor
public class UseStaticApiRestfulUserController {private final MyBatisPlusUserService myBatisPlusUserService;private final UserConverter userConverter;// 查询单个 @GetMapping(path = "/queryUserById/{id}", consumes = "application/json")public UserVO queryUserById(@PathVariable("id") Long id) {return myBatisPlusUserService.queryUserAndAddrById(id);}// 查询多个 @GetMapping(path = "/queryUserByIds", consumes = "application/json")public List<UserVO> queryUserByIds(@RequestParam("ids") List<Long> ids) {return myBatisPlusUserService.queryUserAndAddrById(ids);}
}

【MyBatisPlusUserService】

@Service
@RequiredArgsConstructor
public class MyBatisPlusUserService extends ServiceImpl<UserMapper, UserPO> {private final UserConverter userConverter;private final UserAddrConverter userAddrConverter;    // 使用MyBatisPlus的DB工具查询单个用户地址public UserVO queryUserAndAddrById(Long id) {// 1 查询用户UserPO userPO = getById(id);// 2 查询地址List<UserAddrPO> userAddrPOList = Db.lambdaQuery(UserAddrPO.class).eq(UserAddrPO::getUserId, id).list();UserVO userVO = userConverter.toUserVO(userPO);// 3 封装地址到用户if (!CollectionUtils.isEmpty(userAddrPOList)) {userVO.setUserAddrVOList(userAddrConverter.toUserAddrVOList(userAddrPOList));}return userVO;}// 使用MyBatisPlus的DB工具查询多个用户地址 public List<UserVO> queryUserAndAddrById(List<Long> ids) {// 1 查询用户列表List<UserVO> userVOList = userConverter.toUserVOList(listByIds(ids));// 2 查询地址列表List<Long> dbUserIdList = userVOList.stream().map(UserVO::getId).collect(Collectors.toList());List<UserAddrPO> userAddrPOList = Db.lambdaQuery(UserAddrPO.class).in(UserAddrPO::getUserId, dbUserIdList).list();// 转为map,其中key为用户id,value为地址vo列表Map<Long, List<UserAddrVO>> userIdToUserAddrVOsMap =userAddrConverter.toUserAddrVOList(userAddrPOList).stream().collect(Collectors.groupingBy(UserAddrVO::getUserId));// 3 封装地址到用户if (!CollectionUtils.isEmpty(userVOList)) {userVOList.forEach(userVO->{userVO.setUserAddrVOList(userIdToUserAddrVOsMap.getOrDefault(userVO.getId(), Collections.emptyList()));});}return userVOList;}
}

【查询单个用户的访问效果】

地址:get localhost:8081/staticdb/restful/user/queryUserById/1

{"id": 1,"name": "user1","mobilePhone": "17612342701","addr": "成都锦城三街101号","balance": 1.00,"userState": "1","userAddrVOList": [{"id": 1,"userId": 1,"addrInfo": "成都高新区大学路1号","addrType": "UNVS"},{"id": 3,"userId": 1,"addrInfo": "成都高新区大学路学府家园","addrType": "HOME"}]
}

【查询多个用户的访问效果】

地址:get localhost:8081/staticdb/restful/user/queryUserByIds?ids=1,2

[{"id": 1,"name": "user1","mobilePhone": "17612342701","addr": "成都锦城三街101号","balance": 1.00,"userState": "1","userAddrVOList": [{"id": 1,"userId": 1,"addrInfo": "成都高新区大学路1号","addrType": "UNVS"},{"id": 3,"userId": 1,"addrInfo": "成都高新区大学路学府家园","addrType": "HOME"}]},{"id": 2,"name": "user2","mobilePhone": "110","addr": "成都锦城四街401号","balance": 2.00,"userState": "0","userAddrVOList": [{"id": 4,"userId": 2,"addrInfo": "成都高新区大学路学府家园201号","addrType": "HOME"},{"id": 5,"userId": 2,"addrInfo": "成都高新区大学路学府家园202号","addrType": "HOME"}]}
]


【3】逻辑删除

使用文档参见: https://baomidou.com/guides/logic-delete/

1)业务背景: 逻辑删除不会真正删除数据,而是用一个字段标记数据的删除状态;实现如下:

  • 在表中添加一个字段deleted标记数据是否被删除;逻辑删除时,deleted=1,否则等于0;
  • 查询时仅查询deleted=0的数据;

2)相关sql:

  • 逻辑删除: update table set deleted=1 where deleted=0 and id = #{id}
  • 查询: select * from table where deleted=0


【3.1】代码实现

1)MyBatisPlus提供了逻辑删除,但需要以下配置。

【application.yml】

mybatis-plus:global-config:db-config:logic-delete-field: deleted # 全局逻辑删除字段名logic-delete-value: 1 # 逻辑已删除值。可选,默认值为 1logic-not-delete-value: 0 # 逻辑未删除值。可选,默认值为 0

步骤1:为user_tbl表新增逻辑删除字段 deleted;

alter table mywarn.user_tbl add column `deleted` varchar(1) default '0' COMMENT '逻辑删除标记(1-已删除,0-未删除)';

【新增字段后的ddl】

CREATE TABLE `user_tbl` (`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键',`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户名称',`mobile_phone` varchar(11) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '移动电话',`addr` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '地址',`user_state` char(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '用户状态/ON-在线/OFF-离线',`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,`last_modify_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,`balance` decimal(18,2) DEFAULT '0.00' COMMENT '余额',`deleted` varchar(1) COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '逻辑删除标记(1-已删除,0-未删除)',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=123003 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户表'

步骤2:为UserPO新增字段 deleted,否则逻辑删除丕生效(非常重要)

@Data
@TableName("user_tbl")
public class UserPO {@TableId("id")private Long id;@TableField("name")private String name;private String mobilePhone;private String addr;private BigDecimal balance;private String userState;private String deleted;
}

步骤3:编写测试用例

@SpringBootTest
public class MyBatisPlusUserServiceTest {@Autowiredprivate MyBatisPlusUserService userService;@Testvoid testLogicDelete() {Long id = 103L;// 删除userService.removeById(id);// 查询UserPO userPO = userService.getById(id);System.out.println(userPO);}
}

【sql执行日志】

==>  Preparing: UPDATE user_tbl SET deleted='1' WHERE id=? AND deleted='0'
==> Parameters: 103(Long)
<==    Updates: 1==>  Preparing: SELECT id,name,mobile_phone,addr,balance,user_state,deleted FROM user_tbl WHERE id=? AND deleted='0'
==> Parameters: 103(Long)
<==      Total: 0


【4】枚举处理器

官方文档参见: https://baomidou.com/guides/auto-convert-enum/

1)业务场景:把user_tbl表中的用户状态user_state字段在po中用枚举类表示;

  • 具体的,MyBatisPlus的属性类型处理器MybatisEnumTypeHandler可以把属性值转为枚举类型,如把varchar转为enum类型;

【MybatisEnumTypeHandler定义】

public final class MybatisEnumTypeHandler<E extends Enum<E>> extends BaseTypeHandler<E> {// ...   
}
// 其中 BaseTypeHandler是 ibatis定义的类型处理器基类


【4.1】代码实现

步骤1:新增用户状态枚举类

【UserStateEnum】

@Getter
@AllArgsConstructor
public enum UserStateEnum {ON("1", "在线"),OFF("0", "离线");@EnumValueprivate final String value;private final String desp;}

步骤2:配置枚举处理器:

【application.yml】

mybatis-plus:global-config:db-config:logic-delete-field: deleted # 全局逻辑删除字段名logic-delete-value: 1 # 逻辑已删除值。可选,默认值为 1logic-not-delete-value: 0 # 逻辑未删除值。可选,默认值为 0configuration:default-enum-type-handler: com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler # 基于枚举常量属性的处理器

步骤3:修改UserPO,把userState类型从string修改为 UserStateEnum;

@Data
@TableName("user_tbl")
public class UserPO {@TableId("id")private Long id;@TableField("name")private String name;private String mobilePhone;private String addr;private BigDecimal balance;//    private String userState;private UserStateEnum userState;private String deleted;
}

【测试案例】

@SpringBootTest
public class MyBatisPlusUserServiceTest {@Autowiredprivate MyBatisPlusUserService userService;@Testvoid testUserStateEnum() {UserPO userPO = userService.getById(104L);if (userPO.getUserState() == UserStateEnum.ON) {System.out.println("用户在线");} else {System.out.println("用户离线");}// 用户在线}
}


【5】JSON处理器

1)业务场景:user_tbl表有一个info字段是json字符串,在查询user时,需要把info转为UserInfo这种Bean;

修改UserPO,为UserInfoPO字段新增注解(表明使用Jackson来做json解析为javabean),且UserPO的@TableName注解新增autoResultMap属性;

在这里插入图片描述

【5.1】代码实现

步骤1:为user_tbl新增info字段,默认值设置为 {“age”:11,“nikeName”:“zhangsan11”}

alter table mywarn.user_tbl add column `info` varchar(512) default '{}' COMMENT '用户信息';

步骤2:新增UserInfoPO类,修改UserPO,新增UserInfoPO属性,并为@TableName注解新增属性autoResultMap=true;

@Data
@TableName(value = "user_tbl", autoResultMap = true)
public class UserPO {@TableId("id")private Long id;@TableField("name")private String name;private String mobilePhone;private String addr;private BigDecimal balance;//    private String userState;private UserStateEnum userState;private String deleted;@TableField(typeHandler = JacksonTypeHandler.class)private UserInfoPO info;
}

【UserInfoPO】

@Data
@NoArgsConstructor
@AllArgsConstructor(staticName = "of") // 设置静态生成器方法
public class UserInfoPO {private int age;private String nikeName;
}

在这里插入图片描述

【运行结果】

[{"id": 1,"name": "user1","mobilePhone": "17612342701","addr": "成都锦城三街101号","balance": 1.00,"userState": "ON","userAddrVOList": null,"info": {"age": 11,"nikeName": "zhangsan11"}}
]


http://www.dtcms.com/a/271341.html

相关文章:

  • 基于Matlab多特征融合的可视化指纹识别系统
  • 常见 HTTP 方法的成功状态码200,204,202,201
  • whitt算法之特征向量的尺度
  • 利用编码ai工具cursor写单元测试
  • springMVC06-注解+配置类实现springMVC
  • Java位运算
  • Electron的setContentProtection()会被哪个层级的API捕获?
  • 【TCP/IP】3. IP 地址
  • 储能系统防孤岛保护测试:电网安全的“守门人”
  • C#字符串相关库函数运用梳理总结 + 正则表达式详解
  • 基于YOLOv11的CF-YOLO,如何突破无人机小目标检测?
  • 光伏无人机3D建模:毫秒级精度设计
  • HarmonyOS从入门到精通:自定义组件开发指南(六):组件生命周期详解
  • vue3.2 前端动态分页算法
  • [Python] 区分方法 函数
  • 企业级智能体平台怎么选?字节、腾讯、360、FastGPT选哪个?
  • 【牛客刷题】小欧的选数乘积
  • K8S使用命令多集群管理配置
  • EUDR法案的核心内容,EUDR未来展望,EUDR对全球供应链的影响
  • Excel 常用高级用法
  • [特殊字符] Python 批量生成词云:读取词频 Excel + 自定义背景 + Excel to.png 流程解析
  • 【踩坑】python写超长字符到excel中被截断
  • TDengine 集群部署及启动、扩容、缩容常见问题与解决方案
  • 自建ELK vs 云商日志服务:成本对比分析
  • Apache Tomcat SessionExample 漏洞分析与防范
  • AMIS全栈低代码开发
  • 【NVIDIA-H100】基于 nvidia-smi 数据H100 GPU 功耗异常深度分析与解决方案
  • PiscTrace应用:从 YOLO-Pose 到深蹲与引体向上计数:实时健身动作分析与实现
  • 语音大模型速览(二)- cosyvoice
  • Flink-1.19.0源码详解-番外补充4-JobGraph图