peopleSoft实现树状数据管理器

适用场景:

在一个程序运行周期内,需要大量的对同一颗树状数据进行各种查询、运算

此管理器可缓存树状数据并做相应处理,减少数据库IO,极大提升效率

实现方法:

1.为树节点建立实体类,数据以树状结构组织

2.为每一个节点建立索引,使用HashMap实现索引功能

------------------------------------代码分割线------------------------------------

实体类:

/* 此类是一个树节点实体类 */

class TreeDataEntity
   /* 自己的ID */
   property string id;
   /* 父节点Id */
   property string parentId;
   /* 父节点 */
   property GT_COMMON:UTIL:entity:TreeDataEntity parent;
   
   /* 存放节点信息 */
   property any anyProperty;
   
   /* 孩子节点数组 */
   property array of GT_COMMON:UTIL:entity:TreeDataEntity childrenArray;
   
   method TreeDataEntity(&_id As string, &_parentId As string);
   method addChild(&childNode As GT_COMMON:UTIL:entity:TreeDataEntity);
   method getAllChildren(&dataBearer As array of GT_COMMON:UTIL:entity:TreeDataEntity);
   
   property integer treeLvl get set;
   property integer childrenCount get;
private
   instance integer &_treeLvl;
end-class;

method TreeDataEntity
   /+ &_id as String, +/
   /+ &_parentId as String +/
   %This.childrenArray = CreateArrayRept(%This, 0);
   %This.treeLvl = - 1;
   %This.id = &_id;
   %This.parentId = &_parentId;
end-method;

method addChild
   /+ &childNode as GT_COMMON:UTIL:entity:TreeDataEntity +/
   %This.childrenArray.Push(&childNode);
end-method;

method getAllChildren
   /+ &dataBearer as Array of GT_COMMON:UTIL:entity:TreeDataEntity +/
   Local integer &i;
   For &i = 1 To &childrenArray.Len
      &dataBearer.Push(&childrenArray [&i]);
      &childrenArray [&i].getAllChildren(&dataBearer);
   End-For;
end-method;

set treeLvl
   /+ &NewValue as Integer +/
   %This._treeLvl = &NewValue;
end-set;

get treeLvl
   /+ Returns Integer +/
   If %This._treeLvl = - 1 Then
      Local string &tmp = %This.parentId;
      If None(&tmp) Then
         %This._treeLvl = 1;
      Else
         %This._treeLvl = %This.parent.treeLvl + 1;
      End-If;
   End-If;
   Return %This._treeLvl;
end-get;

get childrenCount
   /+ Returns Integer +/
   Local integer &i, &_childrenCount;
   &_childrenCount = &childrenArray.Len;
   For &i = 1 To &childrenArray.Len
      &_childrenCount = &_childrenCount + &childrenArray [&i].childrenCount;
   End-For;
   Return &_childrenCount;
end-get;

管理器:

import COMMON:UTIL:entity:TreeDataEntity;

class TreeDataManager
   method TreeDataManager();
   /* 获取节点 */
   method getNodeById(&id As string) Returns COMMON:UTIL:entity:TreeDataEntity;
   /* 获取父节点ID */
   method getParentNodeId(&id As string) Returns string;
   /* 获取父节点对象 */
   method getParentNode(&id As string) Returns COMMON:UTIL:entity:TreeDataEntity;
   /* 获取直属子节点对象数组 */A
   method getChildrenArray(&id As string) Returns array of COMMON:UTIL:entity:TreeDataEntity;
   /* 获取所有子节点对象数组 */
   method getAllChildrenArray(&id As string) Returns array of COMMON:UTIL:entity:TreeDataEntity;
   /* 获取直属子节点个数 */
   method getChildrenCount(&id As string) Returns integer;
   /* 获取所有子节点个数 */
   method getAllChildrenCount(&id As string) Returns integer;
   /* 判断A是否为B的子节点 */
   method IsABsChild(&idA As string, &idB As string) Returns boolean;
   
   /* 添加节点时父节点一定要存在。  
    此模式好处是:添加速度较快,取节点级别时速度较快。 */
   method addTreeNode(&node As COMMON:UTIL:entity:TreeDataEntity);
   
   /* 无序添加模式,可随意添加任何节点。 
    此模式好处是可以随意添加节点信息,比如当树结构表中无索引时,按序查询数据是比较慢的,可以在查询时不进行排序,使用此方法添加。 
    缺点是添加速度相对较慢,取节点级别时需要临时计算 */
   method disorderAddTreeNode(&node As COMMON:UTIL:entity:TreeDataEntity);
   rem method disorderAddTreeNode(&node As COMMON:UTIL:entity:TreeDataEntity);
   
   /* 是否存在某个节点 */
   method containsNode(&id As string) Returns boolean;
   
   method clean();
   
   
private
   method mergeNodeArray(&nodeA As array of COMMON:UTIL:entity:TreeDataEntity, &nodeB As array of COMMON:UTIL:entity:TreeDataEntity) Returns array of COMMON:UTIL:entity:TreeDataEntity;
   
   /* 节点数据索引 */
   instance JavaObject &hashMap;
end-class;



method TreeDataManager
   %This.hashMap = CreateJavaObject("java.util.HashMap");
end-method;



method getNodeById
   /+ &id as String +/
   /+ Returns COMMON:UTIL:entity:TreeDataEntity +/
   Return %This.hashMap.get(&id);
end-method;



method getParentNodeId
   /+ &id as String +/
   /+ Returns String +/
   Return %This.getNodeById(&id).parentId;
end-method;



method getParentNode
   /+ &id as String +/
   /+ Returns COMMON:UTIL:entity:TreeDataEntity +/
   Return %This.getNodeById(&id).parent;
end-method;



method getChildrenArray
   /+ &id as String +/
   /+ Returns Array of COMMON:UTIL:entity:TreeDataEntity +/
   Return %This.hashMap.get(&id).childrenArray;
   
end-method;



method getAllChildrenArray
   /+ &id as String +/
   /+ Returns Array of COMMON:UTIL:entity:TreeDataEntity +/
   Local array of COMMON:UTIL:entity:TreeDataEntity &result;
   Local COMMON:UTIL:entity:TreeDataEntity &entityTemp;
   Local COMMON:UTIL:entity:TreeDataEntity &entity = %This.hashMap.get(&id);
   If &entity <> Null Then
      &result = CreateArrayRept(&entityTemp, 0);
      &entity.getAllChildren(&result);
   End-If;
   Return &result;
end-method;



method getChildrenCount
   /+ &id as String +/
   /+ Returns Integer +/
   Return %This.hashMap.get(&id).childrenArray.len;
end-method;



method getAllChildrenCount
   /+ &id as String +/
   /+ Returns Integer +/
   Return %This.hashMap.get(&id).childrenCount;
end-method;



method IsABsChild
   /+ &idA as String, +/
   /+ &idB as String +/
   /+ Returns Boolean +/
   Local COMMON:UTIL:entity:TreeDataEntity &tdme = %This.getNodeById(&idA);
   Local integer &i;
   For &i = 1 To 9999
      If &tdme = Null Then
         Break;
      End-If;
      If &tdme.parentId = &idB Then
         Return True;
      Else
         &tdme = %This.getNodeById(&tdme.parentId);
      End-If;
   End-For;
   Return False;
end-method;

method addTreeNode
   /+ &node as COMMON:UTIL:entity:TreeDataEntity +/
   %This.hashMap.put(&node.id, &node);
   Local COMMON:UTIL:entity:TreeDataEntity &parentNote = %This.hashMap.get(&node.parentId);
   If &parentNote <> Null Then
      &parentNote.addChild(&node);
      &node.parent = &parentNote;
      &node.treeLvl = &parentNote.treeLvl + 1;
   Else
      &node.treeLvl = 1;
   End-If;
end-method;

method disorderAddTreeNode
   /+ &node as COMMON:UTIL:entity:TreeDataEntity +/
   Local COMMON:UTIL:entity:TreeDataEntity &_node = %This.hashMap.get(&node.id);
   If &_node <> Null Then /* 之前添加过此节点(可能是重复添加,也可能是之前为了维护树结构而创建的虚拟树节点),合并子节点 */
      &_node.anyProperty = &node.anyProperty;
      &_node.parentId = &node.parentId;
      &_node.childrenArray = %This.mergeNodeArray(&node.childrenArray, &_node.childrenArray);
      &node = &_node;
   Else
      %This.hashMap.put(&node.id, &node);
   End-If;
   
   /* 维护树结构数据 */
   Local COMMON:UTIL:entity:TreeDataEntity &parentNote = %This.hashMap.get(&node.parentId);
   If &parentNote = Null Then /* 如果此节点的父节点还没添加,那面就先创建一个空的父节点,后续添加时再补充信息 */
      &parentNote = create COMMON:UTIL:entity:TreeDataEntity(&node.parentId, "");
      %This.hashMap.put(&node.parentId, &parentNote);
   Else
      /* 父节点已经添加,检查一下树结构的此路径是否出现死循环,如果有,抛出异常 */
      Local COMMON:UTIL:entity:TreeDataEntity &parentNote2 = &parentNote;
      Local string &msg;
      While &parentNote2 <> Null
         If &parentNote2.id = &node.id Then /* 死循环 */
            &msg = &node.id;
            &parentNote2 = &parentNote;
            While &parentNote2 <> Null
               &msg = &msg | " → " | &parentNote2.id;
               If &parentNote2.id = &node.id Then
                  throw CreateException(0, 0, &node.id | ":路径上存在死循环(" | &msg | ")");
               End-If;
               &parentNote2 = &parentNote2.parent;
            End-While;
         End-If;
         &parentNote2 = &parentNote2.parent;
      End-While;
   End-If;
   &parentNote.addChild(&node);
   &node.parent = &parentNote;
   rem End-If;
end-method;

method containsNode
   /+ &id as String +/
   /+ Returns Boolean +/
   Return %This.hashMap.containsKey(&id);
end-method;

method mergeNodeArray
   /+ &nodeA as Array of COMMON:UTIL:entity:TreeDataEntity, +/
   /+ &nodeB as Array of COMMON:UTIL:entity:TreeDataEntity +/
   /+ Returns Array of COMMON:UTIL:entity:TreeDataEntity +/
   If &nodeA.Len = 0 Then
      Return &nodeB;
   End-If;
   If &nodeB.Len = 0 Then
      Return &nodeA;
   End-If;
   Local array of COMMON:UTIL:entity:TreeDataEntity &result, &passiveArray;
   If &nodeA < &nodeB Then
      &result = &nodeB;
      &passiveArray = &nodeA;
   Else
      &result = &nodeA;
      &passiveArray = &nodeB;
   End-If;
   Local integer &i;
   For &i = 1 To &passiveArray.Len
      &result.Push(&passiveArray [&i]);
   End-For;
   Return &result;
end-method;


method clean
   %This.hashMap = Null;
end-method;

部门树实体类实现:

import T_COMMON:Util:TreeDataManagerEntity;

class DeptTreeBufferUtilEntrty extends T_COMMON:Util:TreeDataManagerEntity;
   property Record deptTreeRecord;
   method DeptTreeBufferUtilEntrty(&dr As Record, &tId As string, &pId As string);
end-class;

method DeptTreeBufferUtilEntrty
   /+ &dr as Record, +/
   /+ &tId as String, +/
   /+ &pId as String +/
   %Super = create T_COMMON:Util:TreeDataManagerEntity(&tId, &pId);
   %This.deptTreeRecord = &dr;
end-method;

部门树管理器实现:

class DeptTreeBufferUtil extends T_COMMON:Util:TreeDataManager;
   method DeptTreeBufferUtil(&effdt As date);
   
end-class;

method DeptTreeBufferUtil
   /+ &effdt as Date +/
   %Super = create T_COMMON:Util:TreeDataManager();
   Local string &sqlString;
   &sqlString = &sqlString | "SELECT *                                                       ";
   &sqlString = &sqlString | "  FROM (SELECT *                                               ";
   &sqlString = &sqlString | "          FROM PSTREENODE N                                    ";
   &sqlString = &sqlString | "         WHERE N.EFFDT = (SELECT MAX(E.EFFDT)                  ";
   &sqlString = &sqlString | "                            FROM PSTREENODE E                  ";
   &sqlString = &sqlString | "                           WHERE E.EFFDT <= %dateIn(:1)        ";
   &sqlString = &sqlString | "                             AND E.SETID = 'X20210609'             ";
   &sqlString = &sqlString | "                             AND E.TREE_NAME = 'DEPT_SECURITY')";
   &sqlString = &sqlString | "           AND N.SETID = 'X20210609'                               ";
   &sqlString = &sqlString | "           AND N.TREE_NAME = 'DEPT_SECURITY') PATH             ";
   &sqlString = &sqlString | " START WITH PATH.TREE_NODE = 'DP00001'                        ";
   &sqlString = &sqlString | "CONNECT BY PRIOR PATH.TREE_NODE = PATH.PARENT_NODE_NAME        ";
   Local Record &deptTreeRecordTemp = CreateRecord(Record.PSTREENODE);
   Local Record &deptTreeRecord;
   Local SQL &sql = CreateSQL(&sqlString, &effdt);
   Local T_COMMON:Tree:DeptTreeBufferUtilEntrty &dtEn;
   While &sql.Fetch(&deptTreeRecordTemp)
      &deptTreeRecord = CreateRecord(Record.PSTREENODE);
      &deptTreeRecordTemp.CopyFieldsTo(&deptTreeRecord);
      &dtEn = create T_COMMON:Tree:DeptTreeBufferUtilEntrty(&deptTreeRecord, &deptTreeRecord.TREE_NODE.Value, &deptTreeRecord.PARENT_NODE_NAME.Value);
      %Super.addTreeNode(&dtEn);
   End-While;
end-method;

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值