관리 메뉴

피터의 개발이야기

JAVA 조직도 트리구조 만드는 재귀코딩 본문

Programming/JAVA

JAVA 조직도 트리구조 만드는 재귀코딩

기록하는 백앤드개발자 2023. 5. 8. 02:42
반응형

 

ㅁ 들어가며

  다음은 조직도 테이블 구조를 트리구조 JSON 형태로 변환하는 Java 코드 샘플입니다. 이 코드는 JDBC 드라이버를 사용하여

데이터베이스에서 데이터를 가져오는 것을 전제로 합니다.

 

import java.sql.*;
import java.util.*;

public class OrgChart {
    public static void main(String[] args) {
        try {
            Class.forName("com.mysql.jdbc.Driver");
            Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/orgchart", "username", "password");
            Statement stmt = conn.createStatement();
            ResultSet rs = stmt.executeQuery("SELECT * FROM employees ORDER BY manager_id ASC, employee_id ASC");

            Map<Integer, Employee> employees = new HashMap<>();

            while (rs.next()) {
                int employeeId = rs.getInt("employee_id");
                String name = rs.getString("name");
                int managerId = rs.getInt("manager_id");

                Employee employee = new Employee(employeeId, name);
                employees.put(employeeId, employee);

                if (managerId != 0) {
                    Employee manager = employees.get(managerId);
                    if (manager != null) {
                        manager.addSubordinate(employee);
                    }
                }
            }

            Employee ceo = null;
            for (Employee employee : employees.values()) {
                if (employee.getManager() == null) {
                    ceo = employee;
                    break;
                }
            }

            System.out.println(ceo.toJSON());

            rs.close();
            stmt.close();
            conn.close();
        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
        }
    }

    static class Employee {
        private int employeeId;
        private String name;
        private List<Employee> subordinates;
        private Employee manager;

        public Employee(int employeeId, String name) {
            this.employeeId = employeeId;
            this.name = name;
            this.subordinates = new ArrayList<>();
        }

        public int getEmployeeId() {
            return employeeId;
        }

        public String getName() {
            return name;
        }

        public void addSubordinate(Employee subordinate) {
            subordinates.add(subordinate);
            subordinate.manager = this;
        }

        public Employee getManager() {
            return manager;
        }

        public String toJSON() {
            StringBuilder sb = new StringBuilder();
            sb.append("{");
            sb.append("\"name\":\"" + name + "\",");
            sb.append("\"subordinates\": [");
            for (int i = 0; i < subordinates.size(); i++) {
                sb.append(subordinates.get(i).toJSON());
                if (i != subordinates.size() - 1) {
                    sb.append(",");
                }
            }
            sb.append("]");
            sb.append("}");
            return sb.toString();
        }
    }
}

이 코드는 데이터베이스에 employees 테이블이 있다고 가정합니다. employees 테이블은 다음과 같은 필드를 포함해야 합니다.

  • employee_id (int): 직원 ID
  • name (varchar): 직원 이름
  • manager_id (int): 상사의 직원 ID

최고경영자(CEO)는 manager_id가 0이어야 합니다.

 

이 코드는 모든 직원 정보를 Employee 객체에 저장하고, 각각의 직원에 대한 관계를 설정하여 조직도를 만듭니다. 

 

 

public LinkedHashMap<String, Object> getTreeNode() {

		// 부서별 노드 생성
		Map<String, LinkedHashMap<String, Object>> treeNode = new HashMap<>();

		// db에 저장된 조직 및 사원 데이터 가져오기
		List<OrganizationChartDTO> orgDTOList = treeService.getTreeNode();

		// 부서별 사원리스트 가공
		orgDTOList.forEach(orgDTO -> {
			LinkedHashMap<String, Object> nodeMap = treeNode.get(orgDTO.getDeptCode());
			// 신규부서
			if (SeedUtil.isNullOrEmpty(nodeMap)){
				nodeMap = new LinkedHashMap<>();
				nodeMap.put("deptName", orgDTO.getDeptName());
				nodeMap.put("deptCode",orgDTO.getDeptCode());
				nodeMap.put("parentDeptCode", orgDTO.getParentDeptCode());

				// 신규 사원 추가
				List<NodeDto.Employee> employeeList = new ArrayList<>();
				employeeList.add(
						NodeDto.Employee.builder()
								.id(orgDTO.getAccountId())
								.name(orgDTO.getPersonName())
								.build()
				);
				nodeMap.put("employeeList", employeeList);
			}
			else{
				List<NodeDto.Employee> employeeList = (List<NodeDto.Employee>) nodeMap.get("employeeList");

				employeeList.add(
						NodeDto.Employee.builder()
								.id(orgDTO.getAccountId())
								.name(orgDTO.getPersonName())
								.build()
				);
			}

			treeNode.put((String) nodeMap.get("deptCode"), nodeMap);
		});

		// 최상위 부서의 트리생성 hash ver
		LinkedHashMap<String,Object> rootMap = toMakeTree(treeNode.get("0"), treeNode, 1);
		return rootMap;
	}



	// hash Version
	private LinkedHashMap<String,Object> toMakeTree(LinkedHashMap<String, Object> rootMap,Map<String, LinkedHashMap<String, Object>> treeNode, int depth){

		// 자식노드 색인
		Map<String, LinkedHashMap<String, Object>> filtered =	treeNode.entrySet().stream()
				.filter(mapEntry -> mapEntry.getValue().get("parentDeptCode").equals((String) rootMap.get("deptCode")))
				.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

		// 자식이 있는 경우
		if (!filtered.isEmpty()){
			for (LinkedHashMap<String, Object> nodeMap : filtered.values()){
				nodeMap = toMakeTree2(nodeMap, treeNode, depth+1);
				String depthStr = "depth" + Integer.toString(depth+1) + "List";
				List<LinkedHashMap<String, Object>> childList =(List<LinkedHashMap<String, Object>>) rootMap.get(depthStr);
				if (SeedUtil.isNullOrEmpty(childList)) childList = new ArrayList<>();
				childList.add(nodeMap);
				rootMap.put(depthStr, childList);
			}
		}

		return rootMap;
	}


public class NodeDto {

    @Data
    public static class TreeNodeDto {
        private int depth;
        private String detpName;
        private String detpCode;
        private String parentCode;
        private List<Employee> employeeList;
        private List<TreeNodeDto> childList;
    }

    @Data
    @Builder
    public static class Employee{
        String name;
        String id;
    }
}
반응형
Comments