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 메서드를 이용, 더 큰 개념의 주소가 정해져야만 (시도 → 구군 / 구군 → 동) 작은 개념의 주소 리스트가 뜨게 했다. 시도/구군의 변화만 신경쓰면 되니 동의 리스너는 당연히 없다.
'Study > Java' 카테고리의 다른 글
오버로딩, 오버라이딩 (0) | 2021.11.27 |
---|---|
Java 배열의 초기값 / Java array's default value (0) | 2020.11.12 |
[Java Swing] RGB 계산기 만들기 (JSlider + textArea) (0) | 2020.06.19 |
최근댓글