728x90

살짝 코드가 복잡해지기 시작한다. 메인 코드만 쓰는 구조를 벗어나, 로직에 따라 파일을 분리하는 디자인으로 주소 선택기를 만들어 보자.

정확하게는 시도/구군/동 선택기이다.

먼저 실행한 결과와 조건부터 보자.

 

 

 

[조건]

  • DAO 개념을 적용해 Database에 접근하는 로직과 비즈니스 로직을 구분한다.
  • 먼저 원하는 시도를 선택한 뒤에 구군 선택이 가능해야 한다.
  • 원하는 구군을 선택해야 동 선택이 가능해야 한다.
  • 만약 시도를 변경하면 다른 값들이 빈 칸으로 바뀌어야 하고, 구군을 바꾸면 동의 값만 빈 칸으로 바뀌어야 한다. (다시 선택하도록)

시작

[zipcodeDAO.java]
public class ZipcodeDAO {
    // 생성자가 가동되는 순간 데이터베이스 커넥션 시작
    // 이 커넥션을 이용해서 셀렉션 (39th line) 시작
    private Connection conn = null;
    private PreparedStatement pstmt = null;
    private ResultSet rs = null;
    public ZipcodeDAO() {
        // 데이터 연결
        String url = "jdbc:mysql://localhost:3306/project";
        String user = "root";
        String password = "123456";

        try {
            Class.forName("org.mariadb.jdbc.Driver");
            conn = DriverManager.getConnection(url, user, password);
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            System.out.println("[에러] : " + e.getMessage());
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            System.out.println("[에러] : " + e.getMessage());
        }

    }
    public ArrayList<String> allSido() {
        // sido 데이터 검색
        ArrayList<String> sidodatas = new ArrayList<String>();
        try {
            String sql = "select distinct sido from zipcode";
            pstmt = conn.prepareStatement(sql);

            rs = pstmt.executeQuery();

            while(rs.next()) {
                sidodatas.add(rs.getString("sido"));
            }
        } catch (SQLException e) {
            System.out.println("[에러] : "+e.getMessage());
        } finally {
            if( rs != null ) try { rs.close(); } catch( SQLException e ) {}
            if( pstmt != null ) try { pstmt.close(); } catch( SQLException e ) {}
            if( conn != null ) try { conn.close(); } catch( SQLException e ) {}
        }
        return sidodatas;
    }

    public ArrayList<String> allGugun(String sido) {
        ArrayList<String> gugundatas = new ArrayList<String>();
        // gugun 데이터 검색
        try {
            String sql = "select distinct gugun from zipcode where sido = ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, sido);
            rs = pstmt.executeQuery();

            while(rs.next()) {
                gugundatas.add(rs.getString("gugun"));
            }
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            System.out.println("[에러] : "+e.getMessage());
        } finally {
            if( rs != null ) try { rs.close(); } catch( SQLException e ) {}
            if( pstmt != null ) try { pstmt.close(); } catch( SQLException e ) {}
            if( conn != null ) try { conn.close(); } catch( SQLException e ) {}
        }
        return gugundatas;
    }

    public ArrayList<String> allDong(String gugun) {
        ArrayList<String> dongdatas = new ArrayList<String>();
        // dong 데이터 검색
        try {
            String sql = "select distinct dong from zipcode where gugun = ?";
            pstmt = conn.prepareStatement(sql);
            pstmt.setString(1, gugun);
            rs = pstmt.executeQuery();

            while (rs.next()) {
                dongdatas.add(rs.getString("dong"));
            }
        } catch (SQLException e) {
            System.out.println("[에러] : "+e.getMessage());
        } finally {
            if( rs != null ) try { rs.close(); } catch( SQLException e ) {}
            if( pstmt != null ) try { pstmt.close(); } catch( SQLException e ) {}
            if( conn != null ) try { conn.close(); } catch( SQLException e ) {}
        }
        return dongdatas;
    }

}

먼저 DB를 조회하기 위한 DAO 코드를 짠다. 시도, 구군, 동 각각의 ArrayList를 만들어 데이터 추가.

[SidoComboBoxModel.java]
public class SidoComboBoxModel extends DefaultComboBoxModel<String> {

    private ArrayList<String> datas = new ArrayList<String>();
    // 데이터베이스 연결
    // 데이터 가져오기
    /*
    public CustomComboBoxModel() {
        Connection conn = null;
        PreparedStatement pstmt = null;
        ResultSet rs = null;

        String url = "jdbc:mysql://192.168.0.37:3306/project";
        String user = "root";
        String password = "123456";

        try {
            Class.forName( "org.mariadb.jdbc.Driver");
            conn = DriverManager.getConnection(url,user,password);

            String sql = "select distinct sido from zipcode";
            pstmt = conn.prepareStatement(sql);

            rs = pstmt.executeQuery();
            while (rs.next()) {
                datas.add(rs.getString("sido"));
            }
        } catch (ClassNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (rs != null) try {rs.close();} catch(SQLException e) {}
            if (pstmt != null) try {pstmt.close();} catch(SQLException e) {}
            if (conn != null) try {conn.close();} catch(SQLException e) {}
        }
    }
    */

    // 생성자 Ver.2
    public SidoComboBoxModel() {
        ZipcodeDAO dao = new ZipcodeDAO();
        datas = dao.allSido();
    }

    @Override
    public int getSize() {
        return datas.size();
    }

    @Override
    public String getElementAt(int index) {
        return datas.get(index);
    }
}

[GugunComboBoxModel.java]
public class GugunComboBoxModel extends DefaultComboBoxModel<String> {
    private ArrayList<String> datas = new ArrayList<String>();

    public GugunComboBoxModel(String sido) {
        ZipcodeDAO dao = new ZipcodeDAO();
        datas = dao.allGugun(sido);
    }

    @Override
    public int getSize() {
        return datas.size();
    }

    @Override
    public String getElementAt(int index) {
        return datas.get(index);
    }
}

[DongComboBoxModel.java]
public class DongComboBoxModel extends DefaultComboBoxModel<String> {
    private ArrayList<String> datas = new ArrayList<String>();
    public DongComboBoxModel(String gugun) {
        ZipcodeDAO dao = new ZipcodeDAO();
        datas = dao.allDong(gugun);
    }

    @Override
    public int getSize() {
        return datas.size();
    }

    @Override
    public String getElementAt(int index) {
        return datas.get(index);
    }
}

다음으로는 ComboBox를 가져오기 위한 모델 파일 3종 세트.

DAO 개념을 적용했기에 SidoComboBox에 주석처리한 '데이터 가져오기' 아래 부분들을 모델 파일에 넣지 않고 간단하게 작성이 가능하다. 재사용 최고

[zipcodeMain.java]
public class ZipSearchQuiz extends JFrame {

    private JPanel contentPane;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    ZipSearchQuiz frame = new ZipSearchQuiz();
                    frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public ZipSearchQuiz() {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setBounds(100, 100, 456, 109);
        contentPane = new JPanel();
        contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
        setContentPane(contentPane);
        contentPane.setLayout(null);

        JComboBox SidoCB = new JComboBox();
        SidoCB.setModel(new SidoComboBoxModel());
        SidoCB.setBounds(12, 10, 129, 39);
        contentPane.add(SidoCB);

        JComboBox GugunCB = new JComboBox();
        GugunCB.setBounds(155, 10, 129, 39);
        contentPane.add(GugunCB);

        JComboBox DongCB = new JComboBox();
        DongCB.setBounds(296, 10, 129, 39);
        contentPane.add(DongCB);

        // 시도의 변화에 맞추어 구군을 업데이트. 동은 null값을 주어 빈 칸으로 바꾼다.
        SidoCB.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                if(e.getStateChange() == ItemEvent.SELECTED) {
                    String sido = (String)SidoCB.getSelectedItem();
                    GugunCB.setModel(new GugunComboBoxModel(sido));
                    DongCB.setModel(new DongComboBoxModel(null));
                }
            }
        });

        // 구군의 변화에 맞추어 동 리스트를 새로 가져옴
        GugunCB.addItemListener(new ItemListener() {
            public void itemStateChanged(ItemEvent e) {
                if(e.getStateChange() == ItemEvent.SELECTED) {
                    String gugun = (String)GugunCB.getSelectedItem();
                    DongCB.setModel(new DongComboBoxModel(gugun));
                }
            }
        });
    }

}

마지막 메인 파일이다. 바로 전의 RGB 계산기 코드와 같이, 생성자와 리스너를 구분해 두었다.

 

itemStateChanged 메서드를 이용, 더 큰 개념의 주소가 정해져야만 (시도 → 구군 / 구군 → 동) 작은 개념의 주소 리스트가 뜨게 했다. 시도/구군의 변화만 신경쓰면 되니 동의 리스너는 당연히 없다.

  • 네이버 블로그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기