版权声明:转发请注明链接和出处,靴靴 https://blog.csdn.net/weixin_43525116/article/details/84979343
应用情景:货物类需要按照批次分类,以树列表形式展示
- 父列表展示每个批次中任意的一个货物;
- 点击该父列表中的某行,下拉展示子列表,子列表展示该行同一批次的所有单号;
小白版解决方案:逻辑分页
先查询所有数据到内存,再从内存截取需要数据采用程序内部逻辑,该方案属于前台分页。
- 查询出所有货物的数据
- 使用Map,根据批次batchFlag字段,对货物分组
List<BillVo> list = billDao.searchBillList(billSo);
Map<String, List<BillVo>> map = new HashMap<>();
for (BillVo vo: list) {
String batchFlag = vo.getBatchFlag();
if (map.containsKey(batchFlag)) {
map.get(batchFlag).add(vo);
} else {
List<BillVo> tempList = new ArrayList<>();
tempList.add(vo);
map.put(batchFlag,tempList);
}
}
- 遍历每个批次的List,提取出父列表,并展示该批次的总数和总重量
// 遍历每个批次的List,提取出父菜单List
List<BillVo> billVos = new ArrayList<>();
for (String batchFlag : map.keySet()) {
List<BillVo> sameBatchFlagList = map.get(batchFlag);
//计算总重量
Double sumWeight = 0.0d;
if(CollectionUtils.isNotEmpty(sameBatchFlagList)){
for(BillVo vo : sameBatchFlagList){
sumWeight = DecimalUtil.add(sumWeight,vo.getChargedWeight())
.doubleValue();
}
}
// 获取第一个作为父菜单展示
BillVo billVo = sameBatchFlagList.get(0);
billVo.setBatchSize(Integer.toString(sameBatchFlagList.size()));
billVo.setSumWeight(sumWeight));
billVos.add(billVo);
}
- 最终使用 PageList 类封装,分页数据。
改进版方案:物理分页(推荐)
在数据库执行查询时(实现分页查询),查询需要的数据依赖数据库SQL语句,属于后台分页。
因为分类依据batch_flag
字段没有添加索引,所以可以Group By batch_flag,有索引的字段sen_site_id,send_date
减少查询数量级,提高查询速度;
Mapper.xml 里的sql
语句
<select id="searchBillParentListOut" resultMap="billVoResultMap">
SELECT t.send_site_id, t.send_date, t.batch_flag, COUNT(1) AS batch_size, SUM(charged_weight) AS sum_weight FROM gw_bill t
<include refid="SO_Where_Clause"/>
GROUP BY t.send_site_id, t.send_date, t.batch_flag
</select>
<sql id="SO_Where_Clause">
<where>
1=1
<if test="id!=null">
and t.ID=#{id}
</if>
<if test="sendDate!=null">
and t.SEND_DATE = #{sendDate}
</if>
<if test="sendDateFrom!=null">
and t.SEND_DATE<![CDATA[ >= ]]>#{sendDateFrom}
</if>
<if test="sendDateTo!=null">
and t.SEND_DATE<![CDATA[ <= ]]>#{sendDateTo}
</if>
<if test="sendSiteId!=null">
and t.SEND_SITE_ID=#{sendSiteId}
</if>
...
</where>
<include refid="Common.Order_By_Clause"/>
</sql>
分页查询
使用Spring-Mybatis结合,自动分页查询,Dao层从传参提取出分页参数,然后将分页参数传给Mybatis。(本文是比较浅显的实践,未说明Mybatis分页插件实现的原理)
Dao层
// 父列表List,分页查询,按批次分组
@Override
public List<BillVo> searchBillParentListOut(BillSo so) {
// 提取分页参数
RowBounds rowBounds = getRowBounds(so);
if (so.getLimit() == 0) {
rowBounds = new RowBounds((so.getPageNumber() - 1) * so.getPageSize(), so.getPageSize());
}
try {
// 执行BillMapper.xml里id为searchBillParentListOut的sql语句
return sqlSessionTemplate.selectList("Bill.searchBillParentListOut", so, rowBounds);
} catch (Exception e) {
logger.warn(getStatementPrefix() + "error.getVOListBySo", e);
throw new DAOException(e);
}
}
selectList方法的几种重载
/**
* 普通sql语句
*/
public <E> List<E> selectList(String statement) {
return this.sqlSessionProxy.<E> selectList(statement);
}
/**
* sql语句,传入参数类So,where语句就可以使用搜索节点<include refid="SO_Where_Clause"/>
*/
public <E> List<E> selectList(String statement, Object parameter) {
return this.sqlSessionProxy.<E> selectList(statement, parameter);
}
/**
* sql语句,传入参数类So,分页参数,使用了SqlSession
*/
public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
return this.sqlSessionProxy.<E> selectList(statement, parameter, rowBounds);
}
子列表数据量不大,不需要分页,一般查询就好。
注意点
因为查出来的分页数据parentList
是当前页的父列表数据,所以使用PageList
类封装传给前台的时候,list总量setFullListSize()
需要一个新的count sql
语句,来查询父列表所有页的总数。