递归的一个应用

需求说明

有表 t_dept_info ,它有dept_iddept_namep_dept_id 三个关键字段,有一家公司,他们的部门分为四级。现需要取出任意部门下所有没有下级部门的部门。以下面的组织架构为例,

在这里插入图片描述
有的部门在二级,有的在三级上,如果使用常规的 sql 自关联的方法,不能适应情况的发展,如果,在第四级或者第六级上面新增部门。那就需要修改 sql 了。

解决办法

  1. 可以将部门理解为一棵树,使用递归的方式遍历上面所有叶子节点(没有子树的节点,也就是没有下级部门的部门)
  2. 使用栈的数据结构遍历到叶子节点。这种方式从原理上比递归是快的。

递归的方式:

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

/**
 * @className: LoadDeptInfo
 * @Description:
 * @Author: wangyifei
 * @Date: 2024/7/12 9:27
 */
public class LoadDeptInfo {
    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://IP:3306/DB";
    static final String USER = "user";
    static final String PASS = "pwd";
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            // 注册 JDBC 驱动
            Class.forName(JDBC_DRIVER);

            // 打开连接
            conn = DriverManager.getConnection(DB_URL, USER, PASS);

            // SQL 查询语句
            String sql = "SELECT dept_id, dept_name, p_dept_id FROM DB.t_dept "
                    + "where company_id = 5  ";

            // 创建预处理语句
            pstmt = conn.prepareStatement(sql);

            // 执行查询
            rs = pstmt.executeQuery();

            // 处理结果集
            Map<String , Dept> depts = new HashMap<>();
            while (rs.next()) {
                // 根据字段名称取出数据
                String deptId  = rs.getString("dept_id");
                String deptName = rs.getString("dept_name");
                String pDeptId = rs.getString("p_dept_id");
                depts.put( deptId , new Dept(deptId + "" , deptName , pDeptId+""));
            }
//            System.out.println(depts.size());
            List<String> result = getDeptInfo(depts , 18960 + "");
            System.out.println(String.join("\nunion all" , result));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (rs != null) {
                    rs.close();
                }
                if (pstmt != null) {
                    pstmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException se) {
                se.printStackTrace();
            }
        }
    }
    public static boolean hasChildren(Map<String , Dept> depts , String pDeptId){
        Collection<Dept> values = depts.values();
        for (Dept value : values) {
            if(pDeptId.equals(value.getpDeptId())){
                return true ;
            }
        }
        return false ;
    }

    public static List<String> getDeptInfo(Map<String , Dept> depts , String deptId) {
        List<String> rs = new ArrayList<>();
        if(!hasChildren(depts , deptId)){
           return null ;
        }else{
            Collection<Dept> values = depts.values();
            for(Dept v : values){
                if(deptId.equals(v.getpDeptId())){
                    List<String> deptInfo = getDeptInfo(depts, v.getDeptId());
                    if(null != deptInfo){
                        rs.addAll(deptInfo);
                    }else{
                        rs.add(" select " + v.getDeptId() + " as dept_id , '"
                                + v.getDeptName() + "' as dept_name ");
                    }
                }
            }
        }

        return rs;
    }

    public static class Dept{
        private String deptId ;
        private String deptName ;
        private String pDeptId ;

        public String getDeptId() {
            return deptId;
        }

        public void setDeptId(String deptId) {
            this.deptId = deptId;
        }

        public String getDeptName() {
            return deptName;
        }

        public void setDeptName(String deptName) {
            this.deptName = deptName;
        }

        public String getpDeptId() {
            return pDeptId;
        }

        public void setpDeptId(String pDeptId) {
            this.pDeptId = pDeptId;
        }

        public Dept(String deptId, String deptName, String pDeptId) {
            this.deptId = deptId;
            this.deptName = deptName;
            this.pDeptId = pDeptId;
        }
    }
}

利用栈的方式

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @className: LoadDeptInfo
 * @Description:
 * @Author: wangyifei
 * @Date: 2024/7/12 9:27
 */
public class LoadDeptInfo {
    static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
    static final String DB_URL = "jdbc:mysql://IP:3306/DB";
    static final String USER = "user";
    static final String PASS = "pwd";
    static final Map<String , List<Dept>> parentChildren = new HashMap<>();
    public static void main(String[] args) {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;
        try {
            // 注册 JDBC 驱动
            Class.forName(JDBC_DRIVER);

            // 打开连接
            conn = DriverManager.getConnection(DB_URL, USER, PASS);

            // SQL 查询语句
            String sql = "SELECT dept_id, dept_name, p_dept_id FROM DB.t_dept "
                    + "where company_id = 5  ";

            // 创建预处理语句
            pstmt = conn.prepareStatement(sql);

            // 执行查询
            rs = pstmt.executeQuery();

            // 处理结果集
            Map<String , Dept> depts = new HashMap<>();
            while (rs.next()) {
                // 根据字段名称取出数据
                String deptId  = rs.getString("dept_id");
                String deptName = rs.getString("dept_name");
                String pDeptId = rs.getString("p_dept_id");
                depts.put( deptId , new Dept(deptId + "" , deptName , pDeptId+""));
            }
//            System.out.println(depts.size());
            List<String> result = getDeptInfo1(depts , 18960 + "");
            System.out.println(String.join("\nunion all" , result));
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            try {
                if (rs != null) {
                    rs.close();
                }
                if (pstmt != null) {
                    pstmt.close();
                }
                if (conn != null) {
                    conn.close();
                }
            } catch (SQLException se) {
                se.printStackTrace();
            }
        }
    }
    public static boolean hasChildren(Map<String , Dept> depts , String pDeptId){
        Collection<Dept> values = depts.values();
        Set<String> strings = parentChildren.keySet();
        if(strings.contains(pDeptId)){
            return true ;
        }
        for (Dept value : values) {
            if(pDeptId.equals(value.getpDeptId())){
                parentChildren.computeIfPresent(pDeptId , (key , o ) -> {
                    o.add(value);
                    return o ;
                });
                parentChildren.putIfAbsent(pDeptId , new ArrayList<Dept>(){
                    {add(value);}
                });
                return true ;
            }
        }
        return false ;
    }

    public static List<String> getDeptInfo1(Map<String , Dept> depts , String parentDeptId){
        List<String> leafDept = new ArrayList<>();
        Collection<Dept> values = depts.values();
        Stack<Dept> stack = new Stack<>();
        stack.push(depts.get(parentDeptId));
        while(!stack.isEmpty()){
            Dept pop = stack.pop();
            List<Dept> children = findChildren(depts, pop.getDeptId());
            if(Objects.isNull(children) || children.isEmpty()){
                leafDept.add(" select " + pop.getDeptId() + " as dept_id , '"
                        + pop.getDeptName() + "' as dept_name ");
            }
            for (Dept child : children) {
                stack.push(child);
            }
        }
        return leafDept ;
    }
    public static List<Dept> findChildren(Map<String , Dept> depts ,String deptId){
        List<Dept> collect = depts.values().stream().filter(x -> !parentChildren.containsKey(x.getDeptId()) && null != x.getpDeptId() && x.getpDeptId().equals(deptId)).collect(Collectors.toList());

        parentChildren.computeIfPresent(deptId , (key , o ) -> {
            o.addAll(collect);
            return o ;
        });
        parentChildren.putIfAbsent(deptId , collect);
        return collect ;
    }

    public static class Dept{
        private String deptId ;
        private String deptName ;
        private String pDeptId ;

        public String getDeptId() {
            return deptId;
        }

        public void setDeptId(String deptId) {
            this.deptId = deptId;
        }

        public String getDeptName() {
            return deptName;
        }

        public void setDeptName(String deptName) {
            this.deptName = deptName;
        }

        public String getpDeptId() {
            return pDeptId;
        }

        public void setpDeptId(String pDeptId) {
            this.pDeptId = pDeptId;
        }

        public Dept(String deptId, String deptName, String pDeptId) {
            this.deptId = deptId;
            this.deptName = deptName;
            this.pDeptId = pDeptId;
        }
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值