之前写项目,前端要求返回一棵树形,刚开始我还不知道,要递归遍历?这是肯定的,但是有些树形不知道它的深度。所以单纯的查询应该是不行。了解到可用Stream()方法,发现真的很好用,简直不要太爽。
先上实体类,这是一张地区表。我用的是MyBatis-Plus。
地区表获取:
链接:https://pan.baidu.com/s/1Ia8m9FjjYoyRw3qt574Wbw
提取码:zhl1
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.util.List;
@TableName("REGION")
public class RegionEntity {
/**
* 区域主键
*/
@TableId("ID")
private Integer id;
/**
* 区域名称
*/
@TableField("NAME")
private String name;
/**
* 父级id
*/
@TableField("P_ID")
private Integer pId;
/**
* 简称
*/
@TableField("S_NAME")
private String sName;
/**
* 等级
*/
@TableField("LEVEL")
private Integer level;
/**
* 区域编码
*/
@TableField("CITY_CODE")
private String cityCode;
/**
* 邮政编码
*/
@TableField("EMAIL_CODE")
private String emailCode;
/**
* 组合名称
*/
@TableField("MER_NAME")
private String merName;
/**
* 拼音
*/
@TableField("PINYIN")
private String pinYin;
/**
* 临时
*/
@TableField(exist = false)
List<RegionEntity> children;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getpId() {
return pId;
}
public void setpId(Integer pId) {
this.pId = pId;
}
public String getsName() {
return sName;
}
public void setsName(String sName) {
this.sName = sName;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
public String getCityCode() {
return cityCode;
}
public void setCityCode(String cityCode) {
this.cityCode = cityCode;
}
public String getEmailCode() {
return emailCode;
}
public void setEmailCode(String emailCode) {
this.emailCode = emailCode;
}
public String getMerName() {
return merName;
}
public void setMerName(String merName) {
this.merName = merName;
}
public String getPinYin() {
return pinYin;
}
public void setPinYin(String pinYin) {
this.pinYin = pinYin;
}
public List<RegionEntity> getChildren() {
return children;
}
public void setChildren(List<RegionEntity> children) {
this.children = children;
}
@Override
public String toString() {
return "RegionEntity{" +
"id=" + id +
", name='" + name + '\'' +
", pId=" + pId +
", sName='" + sName + '\'' +
", level=" + level +
", cityCode='" + cityCode + '\'' +
", emailCode='" + emailCode + '\'' +
", merName='" + merName + '\'' +
", pinYin='" + pinYin + '\'' +
", children=" + children +
'}';
}
}
由于MyBatis-Plus有自带的BaseMapper,所以可用直接继承。
Mapper层:
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.recruit.talentadmin.entity.RegionEntity;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface RegionMapper extends BaseMapper<RegionEntity> {
}
Service层:
import com.recruit.talentadmin.entity.RegionEntity;
import java.util.List;
public interface RegionService {
List<RegionEntity> listRegion();
List<RegionEntity> listRegionTree();
}
Service实现类:(核心)
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.recruit.talentadmin.entity.RegionEntity;
import com.recruit.talentadmin.mapper.RegionMapper;
import com.recruit.talentadmin.service.RegionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class RegionServiceImpl implements RegionService {
private RegionMapper regionMapper;
@Autowired
public void setRegionMapper(RegionMapper regionMapper) {
this.regionMapper = regionMapper;
}
/**
* 查询所有地区列表
* @return
*/
@Override
public List<RegionEntity> listRegion() {
QueryWrapper<RegionEntity> queryWrapper = new QueryWrapper<>(null);
return regionMapper.selectList(queryWrapper);
}
@Override
public List<RegionEntity> listRegionTree(){
List<RegionEntity> regionEntityList = listRegion();
return regionEntityList.stream()
.filter(regionEntity -> regionEntity.getpId()==0)
.peek(regionEntity -> regionEntity.setChildren(getChildren(regionEntity,regionEntityList)))
.collect(Collectors.toList());
}
//递归查找所有地区的子区域
private List<RegionEntity> getChildren(RegionEntity root, List<RegionEntity> all) {
return all.stream()
.filter(regionEntity -> regionEntity.getpId().equals(root.getId()))
.peek(regionEntity -> regionEntity.setChildren(getChildren(regionEntity, all)))
.collect(Collectors.toList());
}
}
在实现类里边将listRegion()方法所得到的全部数据通过Stream()转化成流,通过filter过滤器先获取父节点是0的根节点,再掉用peek方法设置子节点。直接点是通过getChildren()方法获取的,与获取根节点原理相同。
Controller:
import com.recruit.talentadmin.common.Result;
import com.recruit.talentadmin.entity.RegionEntity;
import com.recruit.talentadmin.service.RegionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/system")
public class RegionController {
private RegionService regionService;
@Autowired
public void setRegionService(RegionService regionService) {
this.regionService = regionService;
}
@GetMapping("/listRegionTree")
public Result<List<RegionEntity>> listRegionTree(){
Result<List<RegionEntity>> result = new Result<>();
List<RegionEntity> regionEntityList = regionService.listRegionTree();
if(regionEntityList==null){
result.setCode(500);
result.setMsg("未查询到数据");
}else {
result.setData(regionEntityList);
result.setMsg("查询成功");
result.setCode(200);
}
return result;
}
}
最后看看postmen测试效果:
效果达成,ok。