在最近的开发中,一星期内遇到了两个类似的需求:返回组装好的部门树、返回组装好的地区信息树,最终都需要返回 List 集合对象给前端。
于是在经过需求分析和探索实践后,我对于这种基于 Stream 和 List 结构的父、子树形结构的操作有了新的认识,现在拿出来和大家作分享交流。
一般来说完成这样的需求大多数人会想到递归,但递归的方式弊端过于明显:方法多次自调用效率很低、数据量大容易导致堆栈溢出、随着树深度的增加其时间复杂度会呈指数级增加等。
核心思路如下:
一次数据库查询全部数据(几万条),其它全是内存操作、性能高;
同时熟练使用 stream 流操作、Lambda 表达式、Java 地址引用,完成组装;
使用缓存注解(底层Redis分布式缓存实现),过期后自动更新缓存,再次调用接口则先命中缓存,没有的话再查数据库
使用RocketMQ来做异步通知更新,即当数据有更改时,可以异步将数据先更新,再写入缓存,使业务更合理,考虑更全面
一、以部门结构为例
这里的实体是放在 MySQL 里的,使用简单的封装好的查询语句,这个很简单,剩下的就是内存操作了。
1.1实体
租户表:租户就是一个组织或者公司,所以每个租户都有自己的部门。下面的表结构我只列了一些核心的字段,其它不重要。
@Data
public class PmTenant {
/**
* 主键Id
/
@TableId(type = IdType.ASSIGN_ID)
private Long id;
/*
* 租户名称
/
private String tenantName;
/*
* 租户唯一编码,对外暴露
/
private String tenantCode;
/*
* 租户Id
/
private String tenantId;
/*
* 租户状态,0可用,1禁用
*/
private Integer status;
}
部门表:公司里都会有许多的部门,一个部门里还有部门。从最顶层公司到你所在的的部门,可能会有多达六、七层。以下同样只展示核心字段:
@Data
public class PmDept {
/**
* 主键id