最近项目中遇到一个需求如下:由于业务需要不同,需要这两种结构的数据。
1,设置一个组,组下面嵌套组如下图;
2,组下面可以设置API,所有的API落在最低级的组上,如下图
在介绍一下设计的表结构:group表和API表
上代码
1.接收数据的实体类ApiTreeVO.java
@Data
public class ApiTreeVO implements Serializable {
private Integer id;
private String label;
private int hasApi;
private List<ApiTreeVO> children;
}
查询节点方法
//只查询组
List<ApiTreeVO> getGroup(@Param("parentId") int parentId);
//组和PAP一起嵌套
List<ApiTreeVO> getGroupApi(@Param("groupId") int groupId);
查询数据SQL如下,根据自己的需要写就ok
<select id="getGroup" resultType="com.ps.pdaas.vo.operation.ApiTreeVO">
SELECT g.id, g.group_chi_name AS label, (select 1 from operation_api a where a.group_id = g.id and a.status = 1 LIMIT 1) hasapi
from operation_group g WHERE status = 1
<if test="parentId == 0">
and g.parent_group_id = 0
</if>
<if test="parentId != 0">
and g.parent_group_id = #{parentId}
</if>
</select>
<select id="getGroupApi" resultType="com.ps.pdaas.vo.operation.ApiTreeVO">
select id,api_chi_name as label from operation_api WHERE status = 1 and group_id = #{groupId}
</select>
包装数据,先建立数根节点
/**
* 建树根节点
*
* @return
*/
public List<ApiTreeVO> buildRootTree(boolean hasApi) {
//一级group
List<ApiTreeVO> apiTreeVOS = this.getGroup(0);
if (apiTreeVOS != null) {
for (int i = 0; i < apiTreeVOS.size(); i++) {
if (hasApi){
apiTreeVOS.get(i).setChildren(buildChildTreeApi(apiTreeVOS.get(i)));
}else{
apiTreeVOS.get(i).setChildren(buildChildTree(apiTreeVOS.get(i)));
}
}
}
return apiTreeVOS;
}
/**
* 建树子节点节点
*
* @param rootNode
* @return
*/
public List<ApiTreeVO> buildChildTree(ApiTreeVO rootNode) {
//传入根节点
if (rootNode != null) {
//查询该节点下面的子节点
List<ApiTreeVO> childNode = this.getGroup(rootNode.getId());
for (int i = 0; i < childNode.size(); i++) {
childNode.get(i).setChildren(buildChildTree(childNode.get(i)));
}
//rootNode.setChildren(childNode);
return childNode;
}
return null;
}
/**
* 建树子节点节点(带有api信息)
*
* @param rootNode
* @return
*/
public List<ApiTreeVO> buildChildTreeApi(ApiTreeVO rootNode) {
//查询该节点下面的子节点
List<ApiTreeVO> childNode = this.getGroup(rootNode.getId());
//如果该节点下有
if(childNode.size()<1 && rootNode.getHasApi()==1){
return apiMapper.getGroupApi(rootNode.getId());
}
for (int i = 0; i < childNode.size(); i++) {
if(childNode.get(i).getHasApi()==1){
childNode.get(i).setChildren(apiMapper.getGroupApi(childNode.get(i).getId()));
}else{
childNode.get(i).setChildren(buildChildTree(childNode.get(i)));
}
}
return childNode;
}
在buildRootTree(boolean hasApi)传如true和false区别是否带API节点信息
POSTMAN测试结果:
1:127.0.0.1:9014/api/groupTree
{
"code": 0,
"msg": "成功",
"data": [
{
"id": 1,
"label": "基础组",
"hasApi": 0,
"children": [
{
"id": 5,
"label": "1-1",
"hasApi": 1,
"children": [
{
"id": 16,
"label": "1-1-1",
"hasApi": 0,
"children": []
}
]
},
{
"id": 6,
"label": "1-2",
"hasApi": 1,
"children": []
}
]
},
{
"id": 2,
"label": "组2",
"hasApi": 0,
"children": [
{
"id": 7,
"label": "2-1",
"hasApi": 1,
"children": []
},
{
"id": 8,
"label": "2-2",
"hasApi": 0,
"children": []
}
]
},
{
"id": 3,
"label": "组3",
"hasApi": 0,
"children": [
{
"id": 9,
"label": "3-1",
"hasApi": 0,
"children": [
{
"id": 10,
"label": "3-1-1",
"hasApi": 0,
"children": []
}
]
}
]
},
{
"id": 4,
"label": "组4",
"hasApi": 0,
"children": []
}
]
}
2:127.0.0.1:9014/api/groupApiTree
{
"code": 0,
"msg": "成功",
"data": [
{
"id": 1,
"label": "基础组",
"hasApi": 0,
"children": [
{
"id": 5,
"label": "1-1",
"hasApi": 1,
"children": [
{
"id": 1,
"label": "查看黑名单",
"hasApi": 0,
"children": null
},
{
"id": 22,
"label": "测试api",
"hasApi": 0,
"children": null
}
]
},
{
"id": 6,
"label": "1-2",
"hasApi": 1,
"children": [
{
"id": 7,
"label": "查看征信报告",
"hasApi": 0,
"children": null
}
]
}
]
},
{
"id": 2,
"label": "组2",
"hasApi": 0,
"children": [
{
"id": 7,
"label": "2-1",
"hasApi": 1,
"children": [
{
"id": 21,
"label": "测试",
"hasApi": 0,
"children": null
}
]
},
{
"id": 8,
"label": "2-2",
"hasApi": 0,
"children": []
}
]
},
{
"id": 3,
"label": "组3",
"hasApi": 0,
"children": [
{
"id": 9,
"label": "3-1",
"hasApi": 0,
"children": [
{
"id": 10,
"label": "3-1-1",
"hasApi": 0,
"children": []
}
]
}
]
},
{
"id": 4,
"label": "组4",
"hasApi": 0,
"children": []
}
]
}