feat: 新需求功能代码提交,新增MPJLambdaWrapper查询。

This commit is contained in:
tianyongbao
2025-10-16 00:27:38 +08:00
parent f54859f62d
commit ab3508d6c4
19 changed files with 192 additions and 534 deletions

View File

@@ -1,5 +1,6 @@
package org.dromara.fishery.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlusJoin;
import org.dromara.fishery.domain.DeviceBindRecord;
import org.dromara.fishery.domain.vo.DeviceBindRecordVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
@@ -10,6 +11,6 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
* @author intc
* @date 2025-10-14
*/
public interface DeviceBindRecordMapper extends BaseMapperPlus<DeviceBindRecord, DeviceBindRecordVo> {
public interface DeviceBindRecordMapper extends BaseMapperPlusJoin<DeviceBindRecord, DeviceBindRecordVo> {
}

View File

@@ -1,6 +1,7 @@
package org.dromara.fishery.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlusJoin;
import org.dromara.fishery.domain.Device;
import org.dromara.fishery.domain.vo.DeviceVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
@@ -11,6 +12,6 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
* @author intc
* @date 2025-10-14
*/
public interface DeviceMapper extends BaseMapperPlus<Device, DeviceVo> {
public interface DeviceMapper extends BaseMapperPlusJoin<Device, DeviceVo> {
}

View File

@@ -1,5 +1,6 @@
package org.dromara.fishery.mapper;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlusJoin;
import org.dromara.fishery.domain.Pond;
import org.dromara.fishery.domain.vo.PondVo;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
@@ -10,6 +11,6 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
* @author intc
* @date 2025-10-11
*/
public interface PondMapper extends BaseMapperPlus<Pond, PondVo> {
public interface PondMapper extends BaseMapperPlusJoin<Pond, PondVo> {
}

View File

@@ -5,8 +5,7 @@ import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -14,15 +13,12 @@ import org.dromara.fishery.domain.AquUser;
import org.dromara.fishery.domain.bo.DeviceBindRecordBo;
import org.dromara.fishery.domain.vo.DeviceBindRecordVo;
import org.dromara.fishery.domain.DeviceBindRecord;
import org.dromara.fishery.mapper.AquUserMapper;
import org.dromara.fishery.mapper.DeviceBindRecordMapper;
import org.dromara.fishery.service.IDeviceBindRecordService;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;
/**
* 设备绑定记录Service业务层处理
@@ -36,7 +32,6 @@ import java.util.stream.Collectors;
public class DeviceBindRecordServiceImpl implements IDeviceBindRecordService {
private final DeviceBindRecordMapper baseMapper;
private final AquUserMapper aquUserMapper;
/**
* 查询设备绑定记录
@@ -58,12 +53,8 @@ public class DeviceBindRecordServiceImpl implements IDeviceBindRecordService {
*/
@Override
public TableDataInfo<DeviceBindRecordVo> queryPageList(DeviceBindRecordBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<DeviceBindRecord> lqw = buildQueryWrapper(bo);
Page<DeviceBindRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
// 批量填充用户信息
enrichRecordListWithUserInfo(result.getRecords());
MPJLambdaWrapper<DeviceBindRecord> wrapper = buildQueryWrapper(bo);
Page<DeviceBindRecordVo> result = baseMapper.selectJoinPage(pageQuery.build(), DeviceBindRecordVo.class, wrapper);
return TableDataInfo.build(result);
}
@@ -75,50 +66,61 @@ public class DeviceBindRecordServiceImpl implements IDeviceBindRecordService {
*/
@Override
public List<DeviceBindRecordVo> queryList(DeviceBindRecordBo bo) {
LambdaQueryWrapper<DeviceBindRecord> lqw = buildQueryWrapper(bo);
List<DeviceBindRecordVo> recordList = baseMapper.selectVoList(lqw);
// 批量填充用户信息
enrichRecordListWithUserInfo(recordList);
return recordList;
MPJLambdaWrapper<DeviceBindRecord> wrapper = buildQueryWrapper(bo);
return baseMapper.selectVoJoinList(wrapper);
}
private LambdaQueryWrapper<DeviceBindRecord> buildQueryWrapper(DeviceBindRecordBo bo) {
/**
* 构建查询条件包装器(使用 MPJLambdaWrapper 支持联表查询)
*
* @param bo 查询条件业务对象
* @return 构建好的查询条件包装器
*/
private MPJLambdaWrapper<DeviceBindRecord> buildQueryWrapper(DeviceBindRecordBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<DeviceBindRecord> lqw = Wrappers.lambdaQuery();
lqw.orderByDesc(DeviceBindRecord::getCreateTime);
lqw.like(StringUtils.isNotBlank(bo.getIotId()), DeviceBindRecord::getIotId, bo.getIotId());
lqw.eq(bo.getDeviceType() != null, DeviceBindRecord::getDeviceType, bo.getDeviceType());
lqw.eq(StringUtils.isNotBlank(bo.getSerialNum()), DeviceBindRecord::getSerialNum, bo.getSerialNum());
lqw.eq(bo.getUserId() != null, DeviceBindRecord::getUserId, bo.getUserId());
lqw.eq(bo.getIsBind() != null, DeviceBindRecord::getIsBind, bo.getIsBind());
MPJLambdaWrapper<DeviceBindRecord> wrapper = new MPJLambdaWrapper<>();
// 选择主表所有字段
wrapper.selectAll(DeviceBindRecord.class);
// 选择关联表的字段(使用 selectAs 映射到 VO
wrapper.selectAs(AquUser::getUserName, DeviceBindRecordVo::getUserName)
.selectAs(AquUser::getMobilePhone, DeviceBindRecordVo::getMobilePhone);
// 关联查询用户表
wrapper.leftJoin(AquUser.class, AquUser::getId, DeviceBindRecord::getUserId);
// 默认按创建时间倒序排序
wrapper.orderByDesc(DeviceBindRecord::getCreateTime);
// 基础查询条件
wrapper.like(StringUtils.isNotBlank(bo.getIotId()), DeviceBindRecord::getIotId, bo.getIotId());
wrapper.eq(bo.getDeviceType() != null, DeviceBindRecord::getDeviceType, bo.getDeviceType());
wrapper.eq(StringUtils.isNotBlank(bo.getSerialNum()), DeviceBindRecord::getSerialNum, bo.getSerialNum());
wrapper.eq(bo.getUserId() != null, DeviceBindRecord::getUserId, bo.getUserId());
wrapper.eq(bo.getIsBind() != null, DeviceBindRecord::getIsBind, bo.getIsBind());
// 处理额外的查询参数
if (params != null && !params.isEmpty()) {
handleExtraParams(lqw, params);
handleExtraParams(wrapper, params);
}
return lqw;
return wrapper;
}
/**
* 处理额外的查询参数
*
* @param lqw 查询包装器
* @param params 额外参数
* @param wrapper 查询包装器
* @param params 额外参数
*/
private void handleExtraParams(LambdaQueryWrapper<DeviceBindRecord> lqw, Map<String, Object> params) {
private void handleExtraParams(MPJLambdaWrapper<DeviceBindRecord> wrapper, Map<String, Object> params) {
// 处理用户搜索关键词(用户名或手机号)
String userKeyword = (String) params.get("userKeyword");
if (StringUtils.isNotBlank(userKeyword)) {
List<Long> matchingUserIds = getMatchingUserIds(userKeyword);
if (matchingUserIds.isEmpty()) {
// 如果没有符合条件的用户,直接返回空结果
lqw.eq(DeviceBindRecord::getId, -1); // 使用不存在的ID来返回空结果
return;
}
lqw.in(DeviceBindRecord::getUserId, matchingUserIds);
// 使用联表查询直接在 SQL 中过滤用户信息
wrapper.and(w -> w.like(AquUser::getUserName, userKeyword)
.or()
.like(AquUser::getMobilePhone, userKeyword));
}
}
@@ -174,63 +176,5 @@ public class DeviceBindRecordServiceImpl implements IDeviceBindRecordService {
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 为记录列表批量填充用户信息
*
* @param recordList 记录列表
*/
private void enrichRecordListWithUserInfo(List<DeviceBindRecordVo> recordList) {
if (recordList == null || recordList.isEmpty()) {
return;
}
// 收集所有的用户ID
List<Long> userIds = recordList.stream()
.map(DeviceBindRecordVo::getUserId)
.filter(userId -> userId != null)
.distinct()
.collect(Collectors.toList());
if (userIds.isEmpty()) {
return;
}
// 批量查询用户信息
List<AquUser> userList = aquUserMapper.selectBatchIds(userIds);
Map<Long, AquUser> userMap = userList.stream()
.collect(Collectors.toMap(AquUser::getId, user -> user, (existing, replacement) -> existing));
// 为每条记录设置用户信息
for (DeviceBindRecordVo record : recordList) {
if (record.getUserId() != null) {
AquUser user = userMap.get(record.getUserId());
if (user != null) {
record.setUserName(user.getUserName());
record.setMobilePhone(user.getMobilePhone());
}
}
}
}
/**
* 根据用户关键词查询符合条件的用户ID列表
*
* @param userKeyword 用户搜索关键词(用户名或手机号)
* @return 符合条件的用户ID列表
*/
private List<Long> getMatchingUserIds(String userKeyword) {
if (StringUtils.isBlank(userKeyword)) {
return Arrays.asList();
}
LambdaQueryWrapper<AquUser> userQuery = Wrappers.lambdaQuery();
userQuery.like(AquUser::getUserName, userKeyword)
.or()
.like(AquUser::getMobilePhone, userKeyword);
List<AquUser> matchingUsers = aquUserMapper.selectList(userQuery);
return matchingUsers.stream()
.map(AquUser::getId)
.collect(Collectors.toList());
}
}

View File

@@ -1,11 +1,9 @@
package org.dromara.fishery.service.impl;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
@@ -16,15 +14,14 @@ import org.dromara.fishery.domain.Device;
import org.dromara.fishery.domain.Pond;
import org.dromara.fishery.domain.bo.DeviceBo;
import org.dromara.fishery.domain.vo.DeviceVo;
import org.dromara.fishery.mapper.AquUserMapper;
import org.dromara.fishery.mapper.DeviceMapper;
import org.dromara.fishery.mapper.PondMapper;
import org.dromara.fishery.service.IDeviceService;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -41,8 +38,6 @@ import lombok.extern.slf4j.Slf4j;
public class DeviceServiceImpl implements IDeviceService {
private final DeviceMapper baseMapper;
private final AquUserMapper aquUserMapper;
private final PondMapper pondMapper;
/**
* 查询设备管理
@@ -56,7 +51,7 @@ public class DeviceServiceImpl implements IDeviceService {
}
/**
* 分页查询设备管理列表 - 批量查询方案避免N+1问题
* 分页查询设备管理列表 - JOIN查询方案避免N+1问题
*
* @param bo 查询条件
* @param pageQuery 分页参数
@@ -64,12 +59,9 @@ public class DeviceServiceImpl implements IDeviceService {
*/
@Override
public TableDataInfo<DeviceVo> queryPageList(DeviceBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<Device> lqw = buildQueryWrapper(bo);
Page<DeviceVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
MPJLambdaWrapper<Device> wrapper = buildQueryWrapper(bo);
Page<DeviceVo> result = baseMapper.selectJoinPage(pageQuery.build(), DeviceVo.class, wrapper);
// 批量填充关联数据
enrichDeviceListWithUserInfo(result.getRecords());
enrichDeviceListWithPondInfo(result.getRecords());
// 计算过期信息
calculateExpirationInfo(result.getRecords());
@@ -77,84 +69,83 @@ public class DeviceServiceImpl implements IDeviceService {
}
/**
* 查询符合条件的设备管理列表 - 批量查询方案避免N+1问题
* 查询符合条件的设备管理列表 - JOIN查询方案避免N+1问题
*
* @param bo 查询条件
* @return 设备管理列表
*/
@Override
public List<DeviceVo> queryList(DeviceBo bo) {
LambdaQueryWrapper<Device> lqw = buildQueryWrapper(bo);
List<DeviceVo> deviceList = baseMapper.selectVoList(lqw);
MPJLambdaWrapper<Device> wrapper = buildQueryWrapper(bo);
List<DeviceVo> deviceList = baseMapper.selectJoinList(DeviceVo.class, wrapper);
// 批量填充关联数据
enrichDeviceListWithUserInfo(deviceList);
enrichDeviceListWithPondInfo(deviceList);
// 计算过期信息
calculateExpirationInfo(deviceList);
return deviceList;
}
private LambdaQueryWrapper<Device> buildQueryWrapper(DeviceBo bo) {
private MPJLambdaWrapper<Device> buildQueryWrapper(DeviceBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<Device> lqw = Wrappers.lambdaQuery();
MPJLambdaWrapper<Device> wrapper = new MPJLambdaWrapper<>();
// Select main table fields
wrapper.selectAll(Device.class);
// Select joined table fields with Lambda mapping
wrapper.selectAs(AquUser::getUserName, DeviceVo::getUserName)
.selectAs(AquUser::getMobilePhone, DeviceVo::getMobilePhone);
wrapper.selectAs(Pond::getPondName, DeviceVo::getPondName);
// Left join with user table
wrapper.leftJoin(AquUser.class, AquUser::getId, Device::getUserId);
// Left join with pond table
wrapper.leftJoin(Pond.class, Pond::getId, Device::getPondId);
// 处理排序逼辑如果expiredFlag为1按过期时间倒序否则按创建时间倒序
String expiredFlag = params != null ? (String) params.get("expiredFlag") : null;
if ("1".equals(expiredFlag)) {
// 按deadTime倒序过期时间越早的越靠后即过期越久的越靠前
lqw.orderByAsc(Device::getDeadTime);
wrapper.orderByAsc(Device::getDeadTime);
} else {
lqw.orderByDesc(Device::getCreateTime);
wrapper.orderByDesc(Device::getCreateTime);
}
lqw.eq(bo.getUserId() != null, Device::getUserId, bo.getUserId());
lqw.eq(StringUtils.isNotBlank(bo.getSerialNum()), Device::getSerialNum, bo.getSerialNum());
lqw.like(StringUtils.isNotBlank(bo.getDeviceName()), Device::getDeviceName, bo.getDeviceName());
lqw.eq(bo.getDeviceType() != null, Device::getDeviceType, bo.getDeviceType());
lqw.eq(bo.getBindTime() != null, Device::getBindTime, bo.getBindTime());
lqw.eq(bo.getPondId() != null, Device::getPondId, bo.getPondId());
lqw.like(StringUtils.isNotBlank(bo.getIccId()), Device::getIccId, bo.getIccId());
lqw.eq(StringUtils.isNotBlank(bo.getCategory()), Device::getCategory, bo.getCategory());
wrapper.eq(bo.getUserId() != null, Device::getUserId, bo.getUserId());
wrapper.eq(StringUtils.isNotBlank(bo.getSerialNum()), Device::getSerialNum, bo.getSerialNum());
wrapper.like(StringUtils.isNotBlank(bo.getDeviceName()), Device::getDeviceName, bo.getDeviceName());
wrapper.eq(bo.getDeviceType() != null, Device::getDeviceType, bo.getDeviceType());
wrapper.eq(bo.getBindTime() != null, Device::getBindTime, bo.getBindTime());
wrapper.eq(bo.getPondId() != null, Device::getPondId, bo.getPondId());
wrapper.like(StringUtils.isNotBlank(bo.getIccId()), Device::getIccId, bo.getIccId());
wrapper.eq(StringUtils.isNotBlank(bo.getCategory()), Device::getCategory, bo.getCategory());
// 处理额外的查询参数
if (params != null && !params.isEmpty()) {
handleExtraParams(lqw, params);
handleExtraParams(wrapper, params);
}
return lqw;
return wrapper;
}
/**
* 处理额外的查询参数
*
* @param lqw 查询包装器
* @param wrapper 查询包装器
* @param params 额外参数
*/
private void handleExtraParams(LambdaQueryWrapper<Device> lqw, Map<String, Object> params) {
// 处理用户搜索关键词(用户名或手机号)
private void handleExtraParams(MPJLambdaWrapper<Device> wrapper, Map<String, Object> params) {
// 处理用户搜索关键词(用户名或手机号)- 直接在SQL中进行JOIN查询
String userKeyword = (String) params.get("userKeyword");
if (StringUtils.isNotBlank(userKeyword)) {
List<Long> matchingUserIds = getMatchingUserIds(userKeyword);
if (matchingUserIds.isEmpty()) {
// 如果没有符合条件的用户,直接返回空结果
lqw.eq(Device::getId, -1); // 使用不存在的ID来返回空结果
return;
}
lqw.in(Device::getUserId, matchingUserIds);
wrapper.and(w -> w.like(AquUser::getUserName, userKeyword)
.or()
.like(AquUser::getMobilePhone, userKeyword));
}
// 处理塘口搜索关键词(塘口名称)
// 处理塘口搜索关键词(塘口名称)- 直接在SQL中进行JOIN查询
String pondKeyword = (String) params.get("pondKeyword");
if (StringUtils.isNotBlank(pondKeyword)) {
List<Long> matchingPondIds = getMatchingPondIds(pondKeyword);
if (matchingPondIds.isEmpty()) {
// 如果没有符合条件的塘口,直接返回空结果
lqw.eq(Device::getId, -1); // 使用不存在的ID来返回空结果
return;
}
lqw.in(Device::getPondId, matchingPondIds);
wrapper.like(Pond::getPondName, pondKeyword);
}
// 处理是否过期查询条件
@@ -165,10 +156,10 @@ public class DeviceServiceImpl implements IDeviceService {
Date currentDate = new Date();
if (isExpired == 1) {
// 查询已过期的设备deadTime < 当前时间)
lqw.lt(Device::getDeadTime, currentDate);
wrapper.lt(Device::getDeadTime, currentDate);
} else if (isExpired == 0) {
// 查询未过期的设备deadTime >= 当前时间 或 deadTime 为空)
lqw.and(wrapper -> wrapper.ge(Device::getDeadTime, currentDate)
wrapper.and(w -> w.ge(Device::getDeadTime, currentDate)
.or()
.isNull(Device::getDeadTime));
}
@@ -230,122 +221,7 @@ public class DeviceServiceImpl implements IDeviceService {
return baseMapper.deleteByIds(ids) > 0;
}
/**
* 为设备列表批量填充用户信息
*
* @param deviceList 设备列表
*/
private void enrichDeviceListWithUserInfo(List<DeviceVo> deviceList) {
if (deviceList == null || deviceList.isEmpty()) {
return;
}
// 收集所有的用户ID
List<Long> userIds = deviceList.stream()
.map(DeviceVo::getUserId)
.filter(userId -> userId != null)
.distinct()
.collect(Collectors.toList());
if (userIds.isEmpty()) {
return;
}
// 批量查询用户信息
List<AquUser> userList = aquUserMapper.selectBatchIds(userIds);
Map<Long, AquUser> userMap = userList.stream()
.collect(Collectors.toMap(AquUser::getId, user -> user, (existing, replacement) -> existing));
// 为每个设备设置用户信息
for (DeviceVo device : deviceList) {
if (device.getUserId() != null) {
AquUser user = userMap.get(device.getUserId());
if (user != null) {
device.setUserName(user.getUserName());
device.setMobilePhone(user.getMobilePhone());
}
}
}
}
/**
* 为设备列表批量填充塘口信息
*
* @param deviceList 设备列表
*/
private void enrichDeviceListWithPondInfo(List<DeviceVo> deviceList) {
if (deviceList == null || deviceList.isEmpty()) {
return;
}
// 收集所有的塘口ID
List<Long> pondIds = deviceList.stream()
.map(DeviceVo::getPondId)
.filter(pondId -> pondId != null)
.distinct()
.collect(Collectors.toList());
if (pondIds.isEmpty()) {
return;
}
// 批量查询塘口信息
List<Pond> pondList = pondMapper.selectBatchIds(pondIds);
Map<Long, Pond> pondMap = pondList.stream()
.collect(Collectors.toMap(Pond::getId, pond -> pond, (existing, replacement) -> existing));
// 为每个设备设置塘口信息
for (DeviceVo device : deviceList) {
if (device.getPondId() != null) {
Pond pond = pondMap.get(device.getPondId());
if (pond != null) {
device.setPondName(pond.getPondName());
}
}
}
}
/**
* 根据用户关键词查询符合条件的用户ID列表
*
* @param userKeyword 用户搜索关键词(用户名或手机号)
* @return 符合条件的用户ID列表
*/
private List<Long> getMatchingUserIds(String userKeyword) {
if (StringUtils.isBlank(userKeyword)) {
return Arrays.asList();
}
LambdaQueryWrapper<AquUser> userQuery = Wrappers.lambdaQuery();
userQuery.like(AquUser::getUserName, userKeyword)
.or()
.like(AquUser::getMobilePhone, userKeyword);
List<AquUser> matchingUsers = aquUserMapper.selectList(userQuery);
return matchingUsers.stream()
.map(AquUser::getId)
.collect(Collectors.toList());
}
/**
* 根据塘口关键词查询符合条件的塘口ID列表
*
* @param pondKeyword 塘口搜索关键词(塘口名称)
* @return 符合条件的塘口ID列表
*/
private List<Long> getMatchingPondIds(String pondKeyword) {
if (StringUtils.isBlank(pondKeyword)) {
return Arrays.asList();
}
LambdaQueryWrapper<Pond> pondQuery = Wrappers.lambdaQuery();
pondQuery.like(Pond::getPondName, pondKeyword);
List<Pond> matchingPonds = pondMapper.selectList(pondQuery);
return matchingPonds.stream()
.map(Pond::getId)
.collect(Collectors.toList());
}
/**
* 计算设备列表的过期信息

View File

@@ -15,7 +15,6 @@ import org.dromara.fishery.domain.Fish;
import org.dromara.fishery.domain.Pond;
import org.dromara.fishery.domain.bo.PondBo;
import org.dromara.fishery.domain.vo.PondVo;
import org.dromara.fishery.mapper.AquUserMapper;
import org.dromara.fishery.mapper.FishMapper;
import org.dromara.fishery.mapper.PondMapper;
import org.dromara.fishery.service.IPondService;
@@ -24,6 +23,7 @@ import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -43,8 +43,6 @@ public class PondServiceImpl implements IPondService {
private final FishMapper fishMapper;
private final AquUserMapper aquUserMapper;
/**
* 查询塘口管理
*
@@ -57,7 +55,7 @@ public class PondServiceImpl implements IPondService {
}
/**
* 分页查询塘口管理列表
* 分页查询塘口管理列表 - JOIN查询方案避免N+1问题
*
* @param bo 查询条件
* @param pageQuery 分页参数
@@ -65,44 +63,47 @@ public class PondServiceImpl implements IPondService {
*/
@Override
public TableDataInfo<PondVo> queryPageList(PondBo bo, PageQuery pageQuery) {
LambdaQueryWrapper<Pond> lqw = buildQueryWrapper(bo);
Page<PondVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
MPJLambdaWrapper<Pond> wrapper = buildQueryWrapper(bo);
Page<PondVo> result = baseMapper.selectJoinPage(pageQuery.build(), PondVo.class, wrapper);
// 填充鱼类名称信息
// 填充鱼类名称信息鱼类ID是数组仍需后处理
enrichPondListWithFishNames(result.getRecords());
// 填充用户信息
enrichPondListWithUserInfo(result.getRecords());
return TableDataInfo.build(result);
}
/**
* 查询符合条件的塘口管理列表
* 查询符合条件的塘口管理列表 - JOIN查询方案避免N+1问题
*
* @param bo 查询条件
* @return 塘口管理列表
*/
@Override
public List<PondVo> queryList(PondBo bo) {
LambdaQueryWrapper<Pond> lqw = buildQueryWrapper(bo);
List<PondVo> list = baseMapper.selectVoList(lqw);
MPJLambdaWrapper<Pond> wrapper = buildQueryWrapper(bo);
List<PondVo> list = baseMapper.selectJoinList(PondVo.class, wrapper);
// 填充鱼类名称信息
// 填充鱼类名称信息鱼类ID是数组仍需后处理
enrichPondListWithFishNames(list);
// 填充用户信息
enrichPondListWithUserInfo(list);
return list;
}
private LambdaQueryWrapper<Pond> buildQueryWrapper(PondBo bo) {
private MPJLambdaWrapper<Pond> buildQueryWrapper(PondBo bo) {
Map<String, Object> params = bo.getParams();
LambdaQueryWrapper<Pond> lqw = Wrappers.lambdaQuery();
MPJLambdaWrapper<Pond> wrapper = new MPJLambdaWrapper<>();
// Select main table fields
wrapper.selectAll(Pond.class);
// Select joined table fields with Lambda mapping
wrapper.selectAs(AquUser::getUserName, PondVo::getUserName)
.selectAs(AquUser::getMobilePhone, PondVo::getMobilePhone);
// Left join with user table
wrapper.leftJoin(AquUser.class, AquUser::getId, Pond::getUserId);
// 基础条件查询
lqw.eq(bo.getUserId() != null, Pond::getUserId, bo.getUserId())
wrapper.eq(bo.getUserId() != null, Pond::getUserId, bo.getUserId())
.like(StringUtils.isNotBlank(bo.getPondName()), Pond::getPondName, bo.getPondName())
.like(StringUtils.isNotBlank(bo.getFishKindIds()), Pond::getFishKindIds, bo.getFishKindIds())
.eq(bo.getPlaceTime() != null, Pond::getPlaceTime, bo.getPlaceTime())
@@ -110,32 +111,28 @@ public class PondServiceImpl implements IPondService {
// 处理额外的查询参数
if (params != null && !params.isEmpty()) {
handleExtraParams(lqw, params);
handleExtraParams(wrapper, params);
}
// 默认按创建时间升序排列
lqw.orderByDesc(Pond::getCreateTime);
wrapper.orderByDesc(Pond::getCreateTime);
return lqw;
return wrapper;
}
/**
* 处理额外的查询参数
*
* @param lqw 查询包装器
* @param wrapper 查询包装器
* @param params 额外参数
*/
private void handleExtraParams(LambdaQueryWrapper<Pond> lqw, Map<String, Object> params) {
// 处理用户搜索关键词
private void handleExtraParams(MPJLambdaWrapper<Pond> wrapper, Map<String, Object> params) {
// 处理用户搜索关键词 - 直接在SQL中进行JOIN查询
String userKeyword = (String) params.get("userKeyword");
if (StringUtils.isNotBlank(userKeyword)) {
List<Long> matchingUserIds = getMatchingUserIds(userKeyword);
if (matchingUserIds.isEmpty()) {
// 如果没有符合条件的用户,直接返回空结果
lqw.eq(Pond::getId, -1); // 使用不存在的ID来返回空结果
return;
}
lqw.in(Pond::getUserId, matchingUserIds);
wrapper.and(w -> w.like(AquUser::getUserName, userKeyword)
.or()
.like(AquUser::getMobilePhone, userKeyword));
}
// 处理时间范围查询
@@ -152,7 +149,7 @@ public class PondServiceImpl implements IPondService {
if (startDateTime.length() == 10) { // yyyy-MM-dd 格式
startDateTime += " 00:00:00";
}
lqw.ge(Pond::getCreateTime, startDateTime);
wrapper.ge(Pond::getCreateTime, startDateTime);
} catch (Exception e) {
log.warn("开始时间格式不正确: {}", startTime, e);
}
@@ -165,7 +162,7 @@ public class PondServiceImpl implements IPondService {
if (endDateTime.length() == 10) { // yyyy-MM-dd 格式
endDateTime += " 23:59:59";
}
lqw.le(Pond::getCreateTime, endDateTime);
wrapper.le(Pond::getCreateTime, endDateTime);
} catch (Exception e) {
log.warn("结束时间格式不正确: {}", endTime, e);
}
@@ -294,63 +291,5 @@ public class PondServiceImpl implements IPondService {
}
}
/**
* 为塘口列表填充用户信息
*
* @param pondList 塘口列表
*/
private void enrichPondListWithUserInfo(List<PondVo> pondList) {
if (pondList == null || pondList.isEmpty()) {
return;
}
// 收集所有的用户ID
List<Long> userIds = pondList.stream()
.map(PondVo::getUserId)
.filter(userId -> userId != null)
.distinct()
.collect(Collectors.toList());
if (userIds.isEmpty()) {
return;
}
// 批量查询用户信息
List<AquUser> userList = aquUserMapper.selectBatchIds(userIds);
Map<Long, AquUser> userMap = userList.stream()
.collect(Collectors.toMap(AquUser::getId, user -> user, (existing, replacement) -> existing));
// 为每个塘口设置用户信息
for (PondVo pond : pondList) {
if (pond.getUserId() != null) {
AquUser user = userMap.get(pond.getUserId());
if (user != null) {
pond.setUserName(user.getUserName());
pond.setMobilePhone(user.getMobilePhone());
}
}
}
}
/**
* 根据用户关键词查询符合条件的用户ID列表
*
* @param userKeyword 用户搜索关键词(用户名或手机号)
* @return 符合条件的用户ID列表
*/
private List<Long> getMatchingUserIds(String userKeyword) {
if (StringUtils.isBlank(userKeyword)) {
return Arrays.asList();
}
LambdaQueryWrapper<AquUser> userQuery = Wrappers.lambdaQuery();
userQuery.like(AquUser::getUserName, userKeyword)
.or()
.like(AquUser::getMobilePhone, userKeyword);
List<AquUser> matchingUsers = aquUserMapper.selectList(userQuery);
return matchingUsers.stream()
.map(AquUser::getId)
.collect(Collectors.toList());
}
}