业务场景:存在一个编码归属表A:【产品,项目,父编码...】,保存的是业务的产品信息,一个产品有多个项目,多个父编码。另外还有一个子编码归属表B:【父编码,子编码】,表示一个父编码的下层还有多个子编码。
一般多数的查询中,都需要用到业务制定的这张编码表,通过编码进行搜索
ex:业务有一个质量问题单表,字段包括了:单号、发生时间、问题描述、编码、原因分析、发生工序......现在需要查询产品A对应的编码都发生了哪些问题,进行查询过滤,产品A对应有多个编码,如上介绍的业务逻辑,并且还需要把子编码也加上过滤。那下面我们简要看看如何设计这个查询接口。
首先我们定义这个表对应的一个VO实体类,属性一一对应表字段,另外这里补充一点,为了方便接口传参,有时也会在实体类中定义不存在的表字段作为传参时使用的属性,比如:我们查询问题单发生时间在22年1月至6月时,一般都是传递{"startDate":"2022-01","endDate":"2022-06"}这种形式,而我们属性中就可用定义这两个属性 private String startDate;private String endDate
DB编码表如下:
产品 | 项目 | 父编码 |
---|---|---|
it | getdata | 123 |
父编码 | 子编码 |
---|---|
123 | 456 |
XML映射文件如下:
说明:因为方法是分页查询,传参设计的时候定为两个(ProblemListVO,PageVo),所以判断时需要用_parameter.get(0)来取实体VO的属性,_parameter.get(1)来取分页的页号,页容量
这里where条件是实际业务常用的几种:
1.date_format(CREATE_TIME,"%Y-%m-%d") <![CDATA[ >= ]]> #{0.startDate}
通过传递时间参数,进行过滤时间大于等于指定的日期。
2.ITEM_CODE IN(..UNION..)
因为业务传参的是产品属性,product,一个产品对应多个编码,所以为了考虑用户便捷高效,给用户传递产品,后台转换对应的多个编码,编码需要包含父编码与子编码,为了效率问题,我们用UNION来拼接对应产品的父编码与子编码。
3.PROBLEM_DESC like concat('%',#{0.problemDesc},'%')
模糊匹配,存在一种情况,业务想查该问题单的问题描述字段中,存在指定的文字如:严重/停线等,则可以使用like,进行匹配。
4.foreach collection='_parameter.get("0").process'
list集合参数,一般是像前端有个下拉框选择固定的内容,比如问题单中的工序,会有:测试工序/加工工序,采用foreach 接收参数,同样可以用like 模糊匹配数据,或者完全匹配,视业务需求
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.app.it.dao.IProblemListDao">
<sql id ="problem_select">
select
NO no,
PROBLEM_DESC problemDesc,
ITEM_CODE itemCode,
CREATE_TIME createTime,
PROCESS process,
......
from schema.A
<where>
<if test='_parameter.get("0").startDate !=null and _parameter.get("0").startDate!=""'>
date_format(CREATE_TIME,"%Y-%m-%d") <![CDATA[ >= ]]> #{0.startDate}
</if>
<if test='_parameter.get("0").endDate !=null and _parameter.get("0").endDate !=""'>
and date_format(CREATE_TIME,"%Y-%m-%d") <![CDATA[ <= ]]> #{0.endDate}
</if>
<if test='_parameter.get("0").product !=null and _parameter.get("0").product !=""'>
and ITEM_CODE in (
select SUB_CODE from schema.SUB_B
where PARENT_CODE in
(
select PARENT_CODE from PARENT_B
where PRODUCT = #{0.product}
)
union
(
select PARENT_CODE from PARENT_B
where PRODUCT = #{0.product}
)
)
</if>
<if test='_parameter.get("0").problemDesc !=null and _parameter.get("0").problemDesc !=""'>
and PROBLEM_DESC like concat('%',#{0.problemDesc},'%')
</if>
<if test='_parameter.get("0").process!=null and _parameter.get("0").process.size()>0'>
and
<foreach collection='_parameter.get("0").process' item='item' open='(' separator='or' close=')'>
PROCESS like concat('%',#{item},'%')
</foreach>
</if>
</where>
order by CREATE_TIME desc
</sql>
<select id = "getProblemList" resultType="com.app.it.vo.ProblemListVO">
select * from (
<include refid='problem_select'/> ) t limit #{1.pageIndex},#{1.pageSize}
</select>
</mapper>
Dao层接口
@Repository
public interface IProblemDao{
public List<ProblemListVO> getProblemList(ProblemParamVO param,PageVO page);
}
VO实体类
//问题单表VO
@Data
public class ProblemListVO implements Serializable {
private static final long serialVersionUID = 1L;
private String no; // 单号
private String createTime; // 发生时间
private String problemDesc; // 问题描述
private String itemCode; // 编码
private List<String >process; // 工序
}
//问题单传参参数VO
@Data
public class ProblemParamVO implements Serializable {
private static final long serialVersionUID = 1L;
private String startDate; // 开始时间
private String endDate; // 结束时间
private String problemDesc; // 问题描述
private String product; // 产品
private List<String> process; // 工序
}
Service层
public interface IProblemListService {
public List<ProblemListVO> getProblemList(
ProblemParamVO param, PageVO pageVO)
}
@Service
public class ProblemListService implements IProblemListService {
@Autowired
private IProblemListDao iProblemListDao;
@Override
public List<ProblemListVO> getProblemList( ProblemParamVO param, PageVO pageVO){
return iProblemListDao. getProblemList( param,pageVO);
}
}
Controller层
@RestController
@RequestMapping("/app")
public class ProblemListController {
@Autowired
private IProblemListService iProblemListService;
//分页传参,通过用PathParam注解传递分页VO,路径能解析到对应的两个分页属性
@RequestMapping("/problem/page/{pageSize}/{curPage}")
public List<ProblemListVO> getProblemList(@RequestBody ProblemParamVO param,@PathParam("") PageVO pageVO){
return iProblemListService. getProblemList( param,pageVO);
}
}
前端请求:
URL:域名/app/problem/page/100/1
Body:{
"startDate":"2022-01-01",
"endDate":"2022-06-30",
"product":"it",
"problemDesc" :"严重",
"process": ["测试","加工"]}
总结:unionhttps://so.csdn.net/so/search?q=union&spm=1001.2101.3001.70201.UNION对两个结果集进行并集操作, 不包括重复行,相当于distinct, 同时进行默认规则的排序,在无需去重的前提下,使用union all的执行效率要比union高