mybatis实现 主从表 left join 1:n 一对多 分页查询 主表从表都有查询条件+count
需求:
========================================
1.主从表数据 是 1:m
2.主从表各自都有查询条件
3.最后查询结果 需要分页,并统计总数
注意:
=======================================
1.查询的分页,必须在数据库做,否则分页没有意义
解决方法:
注意 下面的入参中 [第一页的10条]
pageNum=0PageSize=10
实际入参应该是处理过的
pageNum = pageNum*10pageSize = 10
##############################有对应实体接收查询结果的情况下################################
1.mapper.xml应该这么写
2.mapper.java应该这么写
List <自定义的bean> pageFind(WorksheetDataSaveBean queryBean); 自定义的bean>
############################### 不确定返回字段类型[即表中属性是动态的,没有对应实体的情况下]###################################
1.mapper.xml中应该这么写
[下面的示例中:因为我不确定返回的字段,所以用HashMap直接接收查询结果后 自己处理的结果集]
2.mapper.java应该这么写
List
===================================count=============================================
count 是什么?count就是页面的 总共total条数
1.mapper.xml应该这么写
2.mapper.java应该这么写
Long count(WorksheetDataSaveBean queryBean);
====================================附录,完整的 分页+left join+count+不确认返回列+Map接收+mybatis标签嵌套+json字段查询+字符串转日期+字符串转数值+结果集封装处理========================================
需求:
1.数据表 列是动态的多列,因此不确定查询返回是哪些列【因此使用Map接收】
2.主表一行 关联 子表的多行 【因此需要left join】
3.对于主表和子表的所有列,需要提供查询功能【因此需要使用mybatis标签拼接查询条件】
4.主表是正常数据,子表是JSON数据存储【因此需要提供有关JSON字段查询处理的操作】
5.查询出的List<Map>结果集 size=主size*子size 【因此,结果集需要将子表数据封装进主表数据集 java处理】
6.上述结果集条数不能作为分页查询的count统计,返回总页码【因此需要额外count()查询,以返回正确的total】
代码参考:
1.Mapper.xml【一个page查询 一个count查询】
2.Mapper.java
List
3.入参数据结构
public class WorksheetDataSaveBean { private Long dataId; private Long rowId; private Listlist; //入参集合 private List resultList;//结果列集合 要返回哪些列信息 private List slaveList;//子表单查询条件 private Integer pageNum = 0; private Integer pageSize = 10;
public class WorksheetData { public static final Integer DATE_UNIT_SECOND = 1; public static final Integer DATE_UNIT_MINUTE = 2; public static final Integer DATE_UNIT_HOUR = 3; public static final Integer DATE_UNIT_DAY = 4; public static final Integer DATE_UNIT_MONTH = 5; public static final Integer DATE_UNIT_YEAR = 6; public static final String RELATED_OPERATOR_AND = "AND"; public static final String RELATED_OPERATOR_OR = "OR"; private Long id; private String cname; private String value; private String tableName;//子表单cname 对应的子表单列 在主表单中的列名 例如:table_0 table_1 private String operator = "equals";//操作符 [equals] / [between and] / [like] / private String reOperator = RELATED_OPERATOR_AND;//查询条件[条件内] 关联符 AND(默认) OR 提供给select/checkbox/dept-user/dept-base使用 private String endValue;//区间操作 结束区间值 提供给date/input-number 字段使用 private Integer dateUnit = DATE_UNIT_DAY;// 按秒、分、时、天(默认)、月、年 提供给date字段查询使用 private String dateFormat; private ListvalueList;//对checkbox、select 提供多值查询功能 public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getCname() { return cname; } public void setCname(String cname) { this.cname = cname; } public String getValue() { return value; } public void setValue(String value) { this.value = value; initValueList(); } public String getOperator() { return operator; } public void setOperator(String operator) { this.operator = operator; } public String getEndValue() { return endValue; } public void setEndValue(String endValue) { this.endValue = endValue; } public String getTableName() { return tableName; } public void setTableName(String tableName) { this.tableName = tableName; } public String getReOperator() { return reOperator; } public void setReOperator(String reOperator) { this.reOperator = reOperator; } public Integer getDateUnit() { return dateUnit; } public void setDateUnit(Integer dateUnit) { this.dateUnit = dateUnit; initDateFormat(); } public String getDateFormat() { return dateFormat; } public void setDateFormat(String dateFormat) { this.dateFormat = dateFormat; } public List getValueList() { return valueList; } public void setValueList(List valueList) { this.valueList = valueList; } private String initDateFormat(){ dateFormat = "'%Y-%m-%d %H:%i:%S'"; switch (dateUnit){ case 1:dateFormat = "'%Y-%m-%d %H:%i:%S'";break; case 2:dateFormat = "'%Y-%m-%d %H:%i'";break; case 3:dateFormat = "'%Y-%m-%d %H'";break; case 4:dateFormat = "'%Y-%m-%d'";break; case 5:dateFormat = "'%Y-%m'";break; case 6:dateFormat = "'%Y'";break; default:dateFormat = "'%Y-%m-%d'"; } return dateFormat; } private void initValueList(){ List list = null; if (this.cname.contains("select") || this.cname.contains("checkbox") || this.cname.contains("dept-user") || this.cname.contains("dept-base")){ String[] split = this.value.split(","); list = Arrays.asList(split); } this.valueList = list; }}
4.controller
@RequestMapping(value = "/pageFindTableData",method = RequestMethod.POST,name="表单数据分页全字段查询") public PageResultBean
检查表是否存在的sql
列名检查 以及 区分主表和子表的查询条件[因为主表是正常数据,子表是JSON数据,查询方式不同,因此需要区分处理]
/** * 列名合法性检查 * [并处理 列名 加上``符号] * * =======处理列名注意======= * 只有主表单字段 需要处理列名 * 子表单查询字段 列名无需处理【json中查询 字段不能带 ``查询】 * * * @param dataId dataId * @param paramList 入参列名集合 * @param includeSlaveTable 是否包含子表单列 * @return 列名是否合法 */ private boolean checkColName(Long dataId,ListparamList,boolean includeSlaveTable){ int size = paramList.size(); WorksheetColBase check = new WorksheetColBase(); check.setDataid(dataId); check.setState(includeSlaveTable ? null: 0); List byDataIdCheckList = mapper.findByDataId(check); for (WorksheetData data : paramList) { String colName = data.getCname(); String tableName = data.getTableName(); for (WorksheetColBase worksheetColBase : byDataIdCheckList) { if (colName.equals(worksheetColBase.getColName())){ String tableColName = worksheetColBase.getTableColName(); if (tableName == null){ if (tableName == tableColName){ //处理列名 data.setCname("`"+colName+"`"); size--; } }else { if (tableName.equals(tableColName)){ size--; } } } } } return size == 0 ? true : false; } /** * 区分 子表单 查询条件 和 主表查询条件 * @param bean */ private void diffSlaveList(WorksheetDataSaveBean bean){ List list = bean.getList(); //入参查询集合 if (list != null ){ List slaveList = new ArrayList<>(); //子表单查询集合 for (int i = 0; i < list.size(); i++) { WorksheetData data = list.get(i); String tableName = data.getTableName(); if (tableName != null){ slaveList.add(data); list.remove(data); i--; } } bean.setSlaveList(slaveList); } }
组装数据集的工具类
public class WorksheetPageFindMap { private Map> resultMap = new HashMap<>(); private Long rowId;//行ID private Map rowMap;//行Map private List > slaveList;//子表单List private Map slaveMap;//子表单Map public List > dealMap(List > list){ for (Map oldMap : list) { rowMap = new HashMap<>(); slaveMap = new HashMap<>(); Set keySet = oldMap.keySet(); for (String key : keySet) { String value = String.valueOf(oldMap.get(key)); if (key.equals("id")){ rowId = Long.valueOf(value); init(); append(key,rowId); }else { if (key.contains("slaveTable_")){ dealSlaveMap(key.split("slaveTable_")[1],value); }else { if (key.contains("date")){ value = value.split("\\.")[0]; } append(key,value); } } } dealSlaveList(); } List > resultList = new ArrayList<>(); for (Map stringObjectMap : resultMap.values()) { resultList.add(stringObjectMap); } return resultList; } //初始化行方法 private void init(){ Map oldRowMap = resultMap.get(rowId); if (oldRowMap != null){ List > oldSlaveList = (List) oldRowMap.get("table"); if (oldSlaveList != null){ if (rowMap.get("table") == null){ slaveList = new ArrayList<>(); } slaveList.addAll(oldSlaveList); append("table",slaveList); } } resultMap.put(rowId,rowMap); } //行数据追加方法 private void append(String key,Object value){ rowMap.put(key,value); } //子表单集合 初始化 private void dealSlaveMap(String key,String value){ slaveMap.put(key,value); } //子表单List 处理 private void dealSlaveList(){ //说明有子表单数据 if (slaveMap.size() > 0 ){ slaveList = (List) rowMap.get("table"); if (slaveList == null){ slaveList = new ArrayList<>(); append("table",slaveList); } slaveList.add(slaveMap); } }}
最后conut ,拿到total,一起返回结果即可
返回结果集