文章目錄
- 【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"}}
]