在流程管理中有用户自定义流程的需求就是用户自己建立流程节点并指定流程节点的走向 因为是用户自己操作所以需要对用户建立的流程的连通性进行判断从开始节点经过若干审核节点的流转后是否最终能到达结束节点 一个流程必须有一个开始节点一个结束节点和若干审核节点 例如用户建立的节点如下 然后用户指定节点的流向 )正确的节点流向 以上这些都是正确的节点流向所谓正确就是开始节点经过若干审核节点的流转可以最终连通到结束节点 )不正确的节点流向 以上这些都是不正确定的节点流向 所以必须检查用户指定的流向是否能从开始节点经过若干审核节点连通到结束节点 )建立两个表一个节点表和一个流向表 )对应的实体 节点Node: /** * 节点 * @author Luxh * */@Entity@Table(name=t_node)public class Node { @Id @GeneratedValue private Integer id; //节点名称 private String name; //节点标记START开始节点AUDIT审核节点END结束节点 private String flag; //一个检查标记位在递归是设置避免死循环 Y已检查 private String checkStatus;} 流向Flow: /** * 流向 * @author Luxh * */@Entity@Table(name=t_flow)public class Flow { @Id @GeneratedValue private Integer id; //开始编号 private Integer beginNo; //指向编号 private Integer endNo; )递归判断方法 /** * 节点检查测试 * @author Luxh * */public class NodeTest { EntityManagerFactory emf = null; @Before public void before() { //根据在persistencexml中配置的persistenceunit name 创建EntityManagerFactory emf = PersistencecreateEntityManagerFactory(myJPA) } @After public void after() { if(null != emf) { emfclose() } } /** * 添加节点数据 */ @Test public void testAddNode(){ EntityManager em = emfcreateEntityManager() emgetTransaction()begin() Node n = new Node() nsetName(开始节点) nsetFlag(START) Node n = new Node() nsetName(节点) nsetFlag(AUDIT) Node n = new Node() nsetName(节点) nsetFlag(AUDIT) Node n = new Node() nsetName(节点) nsetFlag(AUDIT) Node n = new Node() nsetName(结束节点) nsetFlag(END) empersist(n) empersist(n) empersist(n) empersist(n) empersist(n) emgetTransaction()commit() emclose() } /** * 添加节点流向数据 */ @Test public void testAddFlow(){ EntityManager em = emfcreateEntityManager() emgetTransaction()begin() Flow f = new Flow() fsetBeginNo() fsetEndNo() Flow f = new Flow() fsetBeginNo() fsetEndNo() Flow f = new Flow() fsetBeginNo() fsetEndNo() Flow f = new Flow() fsetBeginNo() fsetEndNo() Flow f = new Flow() fsetBeginNo() fsetEndNo() empersist(f) empersist(f) empersist(f) empersist(f) empersist(f) empersist(f) emgetTransaction()commit() emclose() } /** * 测试 */ @Test public void testIsStartCanEnd() { //获取JPA实体管理器 EntityManager em = emfcreateEntityManager() //流程开始节点的编号 Integer beginNo = ; List<String> flagList = new ArrayList<String>() //因为可能会多次检查开始节点是否可以连通结束节点 //所以在调用递归检查方法前一定要清空当前流程所有节点的标记位 //实际中节点表肯定会有一个字段表示所属流程根据该字段清空当前流程的所有节点的标记位 //调用清空标记位方法 //… //首次调用时一定是传入开始节点的编号 isStartCanEnd(beginNoflagListem) if(ntains(END)) { Systemoutprintln(开始节点可以连通结束节点) }else { Systemoutprintln(开始节点无法连通结束节点) } emclose() } /** * 递归判断 开始节点是否可以连通到结束节点 * @param beginNo 开始编号 * @param flagList 存放结束节点标记递归结束后如果flagList中有结束标记说明开始节点可以连通到结束节点 * @param em JPA的实体管理器类似以hibernate的session */ public void isStartCanEnd(Integer beginNoList<String> flagListEntityManager em) { //根据开始编号查询出该开始编号的所有指向的节点的编号 String jpql = select f from Flow f where fbeginNo = ?; List<Flow> flows = emcreateQuery(jpql)setParameter( beginNo)getResultList() if(flows != null && flowssize()>) { //遍历开始编号所指向的所有流向 for(Flow f : flows) { //根据编号找出节点 Node n = emfind(Nodeclass fgetEndNo()) //如果是结束节点就中断循环 if(ENDequals(ngetFlag())) { flagListadd(ngetFlag())//将结束节点的标记存放到flagList中 break; }else if(STARTequals(ngetFlag())||Yequals(ngetCheckStatus())) { //如果是开始节点或者节点的标记位Y说明该节点已被查找过跳过避免递归时死循环 continue; }else { emgetTransaction()begin() nsetCheckStatus(Y)//设置节点的标记位 rge(n) emgetTransaction()commit() //如果是审核节点则递归查找结束节点 isStartCanEnd(ngetId()flagListem) } } } } } |