微服务不能多表联查时候用代码实现联查思想
前言之前文章中提到,公司项目改造,使用微服务,而微服务就是代表,各自的模块有独立的数据库分开来的,需要其他功能的时候就调用服务,那就表示不能像以前一样多表查询了,这个时候怎么办???不能多表查询,只能调用服务来实现,那没办法了,想出了一个临时方案,那就是在代码中实现多表查询多表查询其实也是关联,代码中也只要想办法来关联起来就行,下面用项目实例来举个例子需求有一个模块,其实就是查...
前言
之前文章中提到,公司项目改造,使用微服务,而微服务就是代表,各自的模块有独立的数据库分开来的,需要其他功能的时候就调用服务,那就表示不能像以前一样多表查询了,这个时候怎么办???不能多表查询,只能调用服务来实现,那没办法了,想出了一个临时方案,那就是在代码中实现多表查询
多表查询其实也是关联,代码中也只要想办法来关联起来就行,下面用项目实例来举个例子
需求
有一个模块,其实就是查询,页面很简单,有几个搜索条件,一个搜索按钮,刚进入页面的时候是无条件分页返回所有,有条件的时候根据搜索条件查询分页返回,之前做的时候都是多表联查,因为这几个搜索条件和页面展示所需的都不可能是在一张表里出现的,是需要多表联查出来;
思路
多表的话需要四张表,一张是主表,巡查轨迹表,一张是用户表,一张是用户角色表,一张是区域表
关系是:轨迹表有用户表ID字段,角色表也是一样,用户表有区域表的编码字段,都是可以根据用户ID找出关系的
说明一下,除了轨迹表在自己手里,其他三张表都是需要通过调服务来实现的
关系理清楚了,是离不开用户表,那就调用服务接口里有根据区域或者是角色的方法将传进来的参数进行他们库里查找,如果找到了那就可以确定是几个用户,如果传进来参数是空,服务返回所有的分页用户就行,获取到了用户,自己写mapperXML的sql语句,将用户ID传进来,再通过用户查出轨迹表的数据,轨迹表有对应userID字段的,再通过轨迹表的用户ID找出对应用户,为什么要多做这一步,上面不是有用户集合了吗,因为那是备着条件查询的,万一没传,那么多用户不知道对应了哪个轨迹,调用区域服务的接口方法,用对应用户ID中的区域编码字段查区域信息,在用对应用户ID调用角色服务,最后拼接页面需要信息返回
实现
根据页面需要,一个个来,页面中有一个巡查次数,先写sql查出
<select id="findCount" resultType="com.uhope.rl.worklog.dto.RolePatrolDTO" parameterType="java.util.HashMap">
SELECT count( * ) AS count, USERID AS userId
FROM md_locusrecord
<where>
<if test="userDTOS != null">
AND USERID IN
<foreach collection="userDTOS" item="userDto" open="(" separator="," close=")">
#{userDto.id}
</foreach>
</if>
<if test="userId != null">
AND USERID = #{userId}
</if>
<if test="startTime != null">
AND md_locusrecord.STARTTIME >= #{startTime}
</if>
<if test="endTime != null">
AND md_locusrecord.STARTTIME <= #{endTime}
</if>
</where>
GROUP BY USERID
</select>
这几个if标签都是留着条件查询用的,其中foreach
标签是用in函数来多个用户ID来查,要是单个,就用下面的一个if
Service实现类的写法:
@Override
public List<RolePatrolDTO> selectCount(String userId, String startTime, String endTime, List<UserDTO> userDTOS) {
HashMap<String, Object> map = new HashMap<>(16);
map.put("userId", userId);
map.put("startTime", startTime);
map.put("endTime", endTime);
map.put("userDTOS", userDTOS);
return mdLocusrecordMapper.findCount(map);
}
传输DTO类:
public class RolePatrolDTO {
/**
* 行政区域编码
*/
private String areaCode;
/**
* 行政区域名称
*/
private String areaName;
/**
* 角色名称
*/
private String roleName;
/**
* 用户名称
*/
private String userName;
/**
* 用户ID
*/
private String userId;
/**
* 巡查次数
*/
private Integer count;
/**
* 开始时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date startTime;
/**
* 结束时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date endTime;
/**
* 创建时间
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
/**
* 巡查时长
*/
private String duration;
/**
* 巡查纪要
*/
private String summary;
public String getRoleName() {
return roleName;
}
public RolePatrolDTO setRoleName(List<RoleDTO> roles) {
StringBuilder builder = new StringBuilder();
for (RoleDTO role : roles) {
builder.append(role.getName()).append(",");
}
builder.deleteCharAt(builder.length() - 1);
this.roleName = builder.toString();
return this;
}
public String getDuration() {
return duration;
}
public void setDuration(String duration) {
this.duration = duration;
}
public String getSummary() {
return summary;
}
public void setSummary(String summary) {
this.summary = summary;
}
public String getAreaCode() {
return areaCode;
}
public void setAreaCode(String areaCode) {
this.areaCode = areaCode;
}
public String getUserName() {
return userName;
}
public RolePatrolDTO setUserName(String userName) {
this.userName = userName;
return this;
}
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
public Date getStartTime() {
return startTime;
}
public void setStartTime(Date startTime) {
this.startTime = startTime;
}
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
public Date getEndTime() {
return endTime;
}
public void setEndTime(Date endTime) {
this.endTime = endTime;
}
public String getAreaName() {
return areaName;
}
public RolePatrolDTO setAreaName(String areaName) {
this.areaName = areaName;
return this;
}
public Integer getCount() {
return count;
}
public RolePatrolDTO setCount(Integer count) {
this.count = count;
return this;
}
public String getUserId() {
return userId;
}
public void setUserId(String userId) {
this.userId = userId;
}
@JSONField(format = "yyyy-MM-dd HH:mm:ss")
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
@Override
public String toString() {
return "RolePatrolDTO{" +
"areaCode='" + areaCode + '\'' +
", areaName='" + areaName + '\'' +
", roleName='" + roleName + '\'' +
", userName='" + userName + '\'' +
", userId='" + userId + '\'' +
", count=" + count +
", startTime=" + startTime +
", endTime=" + endTime +
", duration='" + duration + '\'' +
", summary='" + summary + '\'' +
'}';
}
}
综合以上思路,看完整代码
/**
* 分页数据以及搜索,无参分页返回所有,有参根据参数查询分页返回
* @param regionCode 行政区域编码
* @param roleId 巡查角色ID
* @param userId 巡查人员ID
* @param startTime 开始时间
* @param endTime 结束时间
* @param page 页数
* @param size 页码
* @return
*/
@GetMapping("/queryUserList")
public Result queryUserList(@RequestParam(required = false) Long regionCode,
@RequestParam(required = false) String roleId,
@RequestParam(required = false) String userId,
@RequestParam(required = false) String startTime,
@RequestParam(required = false) String endTime,
@RequestParam(required = false, defaultValue = "1") Integer page,
@RequestParam(required = false, defaultValue = "10") Integer size){
//根据有参或者无参查询用户
Result<com.uhope.base.dto.PageInfo<UserDTO>> userList = userService.queryUserList(null, regionCode, null, roleId, page, size);
//服务客户端出错直接返回
if (userList.getResCode() == Constant.RESULT_CODE_FAILURE) {
return ResponseMsgUtil.failure();
}
//获取用户
List<UserDTO> users = userList.getData().getRecords();
//如果有参数找不到用户,直接返回,页面显示暂无数据
if (users == null || users.size() == 0){
return ResponseMsgUtil.success(new PageInfo<>());
}
//分页查询巡查次数,有参或者无参,用户集合不为空会在sql中循环查询,详情查看sql
PageHelper.startPage(page, size);
List<RolePatrolDTO> rolePatrolDTOS = mdLocusrecordService.selectCount(userId, startTime, endTime, users);
//由于服务调服务,不允许多表联查,只能在代码中进行虚拟多表联查,无条件时关联查出所有返回
for (RolePatrolDTO rolePatrolDTO : rolePatrolDTOS){
//查关联用户
Result<UserDTO> byId = userService.getById(rolePatrolDTO.getUserId());
if (byId.getResCode() == Constant.RESULT_CODE_FAILURE){
return ResponseMsgUtil.failure();
}
//这个不是集合,这个是单个对象的
UserDTO userDTO = byId.getData();
//查关联行政区域
Result<List<AdministrativeRegionDTO>> result = administrativeRegionService.find(0, userDTO.getRegionId(), 0);
if (result.getResCode() == Constant.RESULT_CODE_FAILURE) {
return ResponseMsgUtil.failure();
}
AdministrativeRegionDTO administrativeRegion = result.getData().get(0);
//查关联角色
Result<List<RoleDTO>> byUserId = roleService.queryRoleListByUserId(userDTO.getId());
if (byUserId.getResCode() == Constant.RESULT_CODE_FAILURE) {
return ResponseMsgUtil.failure();
}
List<RoleDTO> roleDTOS = byUserId.getData();
//放入封装的对象中,巡查次数sql中已经有了
rolePatrolDTO.setAreaName(administrativeRegion.getAreaName())
.setUserName(userDTO.getName())
.setRoleName(roleDTOS);
}
PageInfo pageInfo = new PageInfo(rolePatrolDTOS);
return ResponseMsgUtil.success(pageInfo);
}
都是围绕着用户来关联的,通过这样的方式,模拟了一次sql多表联查,最后将查出来的信息装入DTO返回给前端页面展示,一个用户可以有多条轨迹,所以就出来了巡查次数
还有一个详情页面,也是差不多的思路,这里我就直接贴代码了:
<select id="findDuration" resultType="com.uhope.rl.worklog.dto.RolePatrolDTO" parameterType="java.util.HashMap">
SELECT
CEIL(
TIME_TO_SEC(
TIMEDIFF(a.endtime, a.starttime)
) / 60
) AS duration,//结束时间减去开始时间,是巡查总时长
USERID AS userId,
CREATETIME AS createTime,
STARTTIME AS startTime,
ENDTIME AS endTime,
(
SELECT
count(c.id)
FROM
md_patrolrecord c,
md_locusrecord
WHERE
c.uploaduser = md_locusrecord.USERID
AND c.TRAILID = md_locusrecord.ID
) AS summary //子查询,关联字段查出查询纪要日志写过几次
FROM
md_locusrecord a
WHERE
USERID = #{userId}
<if test="startTime != null">
AND STARTTIME >= #{startTime}
</if>
<if test="endTime != null">
AND STARTTIME <= #{endTime}
</if>
</select>
/**
* 点击查看详情兼详情搜索框
* @param userId 用户ID
* @param startTime 开始时间
* @param endTime 结束时间
* @param page 页数
* @param size 页码
* @return
*/
@GetMapping("/detail")
public Result detail(@RequestParam(required = true) String userId,
@RequestParam(required = false) String startTime,
@RequestParam(required = false) String endTime,
@RequestParam(required = false, defaultValue = "1") Integer page,
@RequestParam(required = false, defaultValue = "10") Integer size){
PageHelper.startPage(page, size);
List<RolePatrolDTO> duration = mdLocusrecordService.findDuration(userId, startTime, endTime);
for (RolePatrolDTO patrolDTO : duration) {
Result<UserDTO> byId = userService.getById(patrolDTO.getUserId());
if (byId.getResCode() == Constant.RESULT_CODE_FAILURE){
return ResponseMsgUtil.failure();
}
UserDTO user = byId.getData();
if (user.getName() == null){
user.setName("测试数据");
}
patrolDTO.setUserName(user.getName());
}
PageInfo<RolePatrolDTO> pageInfo = new PageInfo<>(duration);
return ResponseMsgUtil.success(pageInfo);
}
更多推荐
所有评论(0)