MybatisPlus中靜態(tài)工具DB的實(shí)現(xiàn)
靜態(tài)工具DB
有的時(shí)候Service之間也會(huì)相互調(diào)用,為了避免出現(xiàn)循環(huán)依賴問題,MybatisPlus提供一個(gè)靜態(tài)工具類:Db,其中的一些靜態(tài)方法與IService中方法簽名基本一致,也可以幫助我們實(shí)現(xiàn)CRUD功能:

循環(huán)依賴的定義:
循環(huán)依賴(Circular Dependency) 是指 兩個(gè)或多個(gè)組件(類、模塊、包、服務(wù)等)之間存在直接或間接的相互依賴關(guān)系,形成一個(gè)閉環(huán),導(dǎo)致系統(tǒng)無法正確初始化、編譯或維護(hù)。
靜態(tài)根據(jù)DB示例:
@Test
void testDbGet() {
User user = Db.getById(1L, User.class);
System.out.println(user);
}
@Test
void testDbList() {
// 利用Db實(shí)現(xiàn)復(fù)雜條件查詢
List<User> list = Db.lambdaQuery(User.class)
.like(User::getUsername, "o")
.ge(User::getBalance, 1000)
.list();
list.forEach(System.out::println);
}
@Test
void testDbUpdate() {
Db.lambdaUpdate(User.class)
.set(User::getBalance, 2000)
.eq(User::getUsername, "Rose");
}Db.lambdaQuery(Address.class)中參數(shù)位置需要放實(shí)體類對象的字節(jié)碼文件,通過傳入實(shí)體類的class字節(jié)碼,拿到字節(jié)碼就能通過反射拿到實(shí)體類的相關(guān)信息,從而拿到注解上的信息諸如類名、表名等,以此實(shí)現(xiàn)CURD。
示例:
需求一
改造根據(jù)id用戶查詢的接口,查詢用戶的同時(shí)返回用戶收貨地址列表
(在userService中要注入addressService,需要查詢收貨地址列表)
首先,我們要添加一個(gè)收貨地址的VO對象,用于視圖返回給前端:
package com.itheima.mp.domain.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
@Data
@ApiModel(description = "收貨地址VO")
public class AddressVO{
@ApiModelProperty("id")
private Long id;
@ApiModelProperty("用戶ID")
private Long userId;
@ApiModelProperty("省")
private String province;
@ApiModelProperty("市")
private String city;
@ApiModelProperty("縣/區(qū)")
private String town;
@ApiModelProperty("手機(jī)")
private String mobile;
@ApiModelProperty("詳細(xì)地址")
private String street;
@ApiModelProperty("聯(lián)系人")
private String contact;
@ApiModelProperty("是否是默認(rèn) 1默認(rèn) 0否")
private Boolean isDefault;
@ApiModelProperty("備注")
private String notes;
}然后,改造原來的UserVO,添加一個(gè)地址屬性,用來存儲(chǔ)當(dāng)前用戶的地址列表屬性:
@Data
@ApiModel(description = "用戶VO實(shí)體")
public class UserVO {
@ApiModelProperty("用戶id")
private Long id;
@ApiModelProperty("用戶名")
private String username;
@ApiModelProperty("詳細(xì)信息")
private UserInfo info;
@ApiModelProperty("使用狀態(tài)(1正常 2凍結(jié))")
private UserStatus status;
@ApiModelProperty("賬戶余額")
private Integer balance;
@ApiModelProperty("用戶的收貨地址")
private List<AddressVO> addresses;
}接下來,修改UserController中根據(jù)id查詢用戶的業(yè)務(wù)接口:
@GetMapping("/{id}")
@ApiOperation("根據(jù)id查詢用戶")
public UserVO queryUserById(@PathVariable("id") Long userId){
// 基于自定義service方法查詢
return userService.queryUserAndAddressById(userId);
}由于查詢業(yè)務(wù)復(fù)雜,所以要在service層來實(shí)現(xiàn)。首先在IUserService中定義方法:
import com.baomidou.mybatisplus.extension.service.IService;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.vo.UserVO;
public interface IUserService extends IService<User> {
void deduct(Long id, Integer money);
UserVO queryUserAndAddressById(Long userId);
}然后,在UserServiceImpl中實(shí)現(xiàn)該方法:
@Override
public UserVO queryUserAndAddressById(Long Id) {
// 1.查詢用戶
User user = this.getById(Id);
if (user == null || user.getStatus()==UserStatus.FROZEN) {
throw new RuntimeException("用戶狀態(tài)異常!");
}
// 2.查詢收貨地址
List<Address> addresses = Db.lambdaQuery(Address.class)
.eq(Address::getUserId, Id)
.list();
// 3.處理vo
UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
//轉(zhuǎn)地址VO
if (CollUtil.isNotEmpty(addresses)){
userVO.setAddresses(BeanUtil.copyToList(addresses,AddressVO.class));
}
return userVO;
}BeanUtil.copyProperties :
將一個(gè)對象的屬性值拷貝到另一個(gè)已存在的對象中(淺拷貝)。
BeanUtil.copyToList:
將一個(gè) List<源對象> 拷貝成一個(gè)新的 List<目標(biāo)對象>,每個(gè)元素通過 copyProperties 創(chuàng)建新對象,因?yàn)槭莿?chuàng)建新對象,所以是一種深拷貝。
上面兩個(gè)方法的第二個(gè)參數(shù)都可以是實(shí)體類的字節(jié)碼,就比如user.class形式的格式,表示在項(xiàng)目運(yùn)行的時(shí)候,會(huì)創(chuàng)建一個(gè)user的對象去接收源對象的數(shù)據(jù),可以避免自己通過NEW關(guān)鍵字去創(chuàng)建對象接收數(shù)據(jù)。
在上面的代碼中,在查詢地址時(shí),我們采用了Db的靜態(tài)方法,因此避免了注入AddressService,減少了循環(huán)依賴的風(fēng)險(xiǎn)。即通過DB的lambdaQuery()方法,在參數(shù)中放我們要操作的實(shí)體類對象,我們可以避免循環(huán)依賴的問題,該方法會(huì)通過反射獲取實(shí)體類的相關(guān)信息,然后根據(jù)我們的條件對當(dāng)前實(shí)體類的表格進(jìn)行CRUD操作,這種方式避免了注入依賴,也相當(dāng)于避免了循環(huán)依賴。
需求二
根據(jù)id批量查詢用戶,并查詢出用戶對應(yīng)的所有地址
controller層
@GetMapping
@ApiOperation("根據(jù)id批量查詢用戶接口")
public List<UserVO> queryUserByIds(@ApiParam("用戶id集合") @RequestParam("ids") List<Long> ids){
return userService.queryUserAndAddressByIds(ids);
}service層
@Override
public List<UserVO> queryUserAndAddressByIds(List<Long> ids) {
// 1.查詢用戶
List<User> users = listByIds(ids);
if (CollUtil.isEmpty(users)) {
return Collections.emptyList();
}
// 2.查詢地址
// 2.1.獲取用戶id集合
List<Long> userIds = users.stream().map(User::getId).collect(Collectors.toList());
// 2.2.根據(jù)用戶id查詢地址
List<Address> addresses = Db.lambdaQuery(Address.class).in(Address::getUserId, userIds).list();
// 2.3.轉(zhuǎn)換地址VO
List<AddressVO> addressVOList = BeanUtil.copyToList(addresses, AddressVO.class);
// 2.4.用戶地址集合分組處理,相同用戶的放入一個(gè)集合(組)中
Map<Long, List<AddressVO>> addressMap = new HashMap<>(0);
if(CollUtil.isNotEmpty(addressVOList)) {
addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));
}
// 3.轉(zhuǎn)換VO返回
List<UserVO> list = new ArrayList<>(users.size());
for (User user : users) {
// 3.1.轉(zhuǎn)換User的PO為VO
UserVO vo = BeanUtil.copyProperties(user, UserVO.class);
list.add(vo);
// 3.2.轉(zhuǎn)換地址VO
vo.setAddresses(addressMap.get(user.getId()));
}
return list;
}和查詢單個(gè)用戶的區(qū)別在于:根據(jù)id對查詢出來的地址通過map來分組的實(shí)現(xiàn)邏輯。
到此這篇關(guān)于MybatisPlus中靜態(tài)工具DB的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)MybatisPlus 靜態(tài)工具DB內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
java中form以post、get方式提交數(shù)據(jù)中文亂碼問題總結(jié)
這篇文章主要介紹了java中form以post、get方式提交數(shù)據(jù)中文亂碼問題總結(jié),需要的朋友可以參考下2014-10-10
java使用POI批量導(dǎo)入excel數(shù)據(jù)的方法
這篇文章主要為大家詳細(xì)介紹了java使用POI批量導(dǎo)入excel數(shù)據(jù)的方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-07-07
springboot整合JavaCV實(shí)現(xiàn)視頻截取第N幀并保存圖片
這篇文章主要為大家詳細(xì)介紹了springboot如何整合JavaCV實(shí)現(xiàn)視頻截取第N幀并保存為圖片,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-08-08
Spring Cloud分布式定時(shí)器之ShedLock的實(shí)現(xiàn)
這篇文章主要介紹了Spring Cloud分布式定時(shí)器之ShedLock的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03
Java實(shí)現(xiàn)將數(shù)組的元素用逗號連接的多種方法
在 Java 開發(fā)中,我們經(jīng)常需要將數(shù)組中的元素用逗號連接成一個(gè)字符串,這種需求在日志記錄、數(shù)據(jù)導(dǎo)出、API 響應(yīng)等場景中非常常見,本文將詳細(xì)介紹如何在 Java 中實(shí)現(xiàn)這一功能,并提供多種簡潔的方法和優(yōu)化建議,需要的朋友可以參考下2025-01-01
SpringBoot自動(dòng)配置與啟動(dòng)流程詳細(xì)分析
這篇文章主要介紹了SpringBoot自動(dòng)配置原理分析,SpringBoot是我們經(jīng)常使用的框架,那么你能不能針對SpringBoot實(shí)現(xiàn)自動(dòng)配置做一個(gè)詳細(xì)的介紹。如果可以的話,能不能畫一下實(shí)現(xiàn)自動(dòng)配置的流程圖。牽扯到哪些關(guān)鍵類,以及哪些關(guān)鍵點(diǎn)2022-11-11
java通過Excel批量上傳數(shù)據(jù)的實(shí)現(xiàn)示例
Excel批量上傳是常見的一種功能,本文就來介紹一下java通過Excel批量上傳數(shù)據(jù)的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2023-10-10

