자바 - JDBC 연동 & 우편번호검색기

지환·2023년 10월 17일
0

JAVA

목록 보기
32/39
post-thumbnail

디비 연동 4단계

  • List는 Row 관리한다.

  • Generic 타입은 Col에 해당하는 값을 관리한다.

  • VO / MAP타입을 사용할 수 있는데 VO타입에는 타입이 정확해서 형전환을 할 필요가 없지만 Map은 객체타입으로 받기 때문에 그 값을 가지고 놀 때는 형 전환을 해야한다.

  • 제네릭타입에는 멀티타입으로 적을 수 없어서 2개 이상의 집합을 조인했을 경우 VO타입 보다는 MAP을 사용하는게 복잡도를 줄일 수 있다.


  • JDBC API 연동하기 - 원시적인 방법 - 생산성이 떨어짐, 코드양이 늘어남(오타)
    반복되는 코드의 양이 점점 늘어난다. - 일괄처리가 불가능해짐 - 사표
    학습목표 - List, Map활용 연습 + CRUD포함 - 게시판수준 - 8시간이내 처리가능한가?
  • Spring - JPA API - Hibernate사용함 - sql문이 없다.
    sql은 없지만 클래스 설계를 해야 한다.
    업무적인 depth가 깊어지면 조인대상 테이블이 4~5개 이상이다
    무한 루프(반복) - 재귀호출

  • 자바API를 활용하여 오라클 서버(동기화, 데이터영속성 보장)와 통신하기

  • java.sql.* - 커넥션 풀을 사용하지 않고....

  • javax.sql.* - 엔터프라이즈 서버(중간에 미들웨어 관리:EJB기술-Spring 경량서비스)가 제공하는 커넥션 풀을 사용할 때

  • 4단계

  • 물리적으로 떨어져 있는 서버와 연결통로를 확보하기
    (전처리 부분 : 각 벤더가 제공하는 드라이버 클래스를 로딩하기) - ojdbc6.jar배포 - 운영서버에 배포시 첨부해야 함
    서버의 ip주소 , port, scott, tiger - 상수로 처리해서 캡슐화 해서

  • java.sql.Connection(Interface)

DML문(SELECT, INSERT, UPDATE, DELETE) - 데이터 조작어
SELECT - 단순 검색 - 물리적인 테이블에 값을 변경하지 않음 - commit, rollback대상이 아님
INSERT, UPDATE, DELETE는 commit과 rollback의 대상임 - 물리적인 변화가 있다
DELETE - row가 전체 삭제 됨 - 컬럼명에 해당하는 셀만 삭제하는 것 불가함
INSERT는 없던 row를 새로 추가함 - add

sql문을 자바로 작성하여 오라클 서버에 전달하고 그 처리를 요청함

SELECT문 - executeQuery():ResultSet(Interface-커서를 조작하는데 필요한 메소드를 정의하고 있음)
INSERT, UPDATE, DELETE - executeUpdate():int - PreparedStatement(Interface) - 전령역할

Connection con  = DriverManager.getConnection(URL, "scott", "tiger");

PreparedStatement pstmt = con.preparedStatement("sql문");

ResultSet rs = pstmt.executeQuery();

while(rs.next()){
  Map or VO담기 - 한개 로우만 담을 수 있다.
  list.add(Map or VO)
}

오라클 서버에서 응답으로 오는 정보를 취득하려면 이종간이므로 오라클에서 제공하는 기능들을 추상화 해야 한다 확장성, 유지보수 구현하는 메소드가 존재함(메소드 오버라이딩)


사용한 자원은 반드시 명시적으로 반납하라. - 자바 튜닝팀 요구사항

공통코드 - 반복되는 코드를 줄임 이유는 MyBatis로 처리한다.

계속해서 반복되는 코드를 찾아보자! -> 개선 의지가 필요하다.

  1. 드라이버 클래스의 반복이 진행된다. -> insert, update, delete, select : DML에서 바뀌는 건 DML만 변경되고 컬럼명 변경된다.

orcle.jdbc.driver.OracleDriver 클래스 이름

SQL

SELECT
       컬럼명1, 컬럼명2,.....
  FROM 집합이름1, 집합이름2,....
 WHERE 집합이름1.컬럼명 = 집합이름2.컬럼명
 
SELECT
       e.empno, e.ename, d.dname
  FROM emp e, dept d
 WHERE e.deptno = d.deptno;  
 
-- 오라클 컬럼은 자바에서 변수이다.
-- 기본키는 not null제약조건이다. unique(유일무이)하다, 식별자 역할함, 인덱스를 제공함 - 검색 속도빠름
-- 메모장에 저장하는 것과는 뭔가 달라야 함
-- dept집합과 1:n관계형태에 있는 emp집합은 dept집합의 deptno를 받아서 태어난 집합임
-- 부서집합의 deptno은 emp집합으로 가서 외래키가 되었다.

SELECT empno FROM emp;
SELECT empno from emp;

select empno, ename
from emp
where empno = "x"; ---> x 자리에 자바에선 파라미터가 들어간다.
- 업무에 따라 집합이름과 컬럼명만 바뀐다. && 나머지는 다 그래로다. - synta - 문법 


1. 문법적으로 맞는지 안 맞는지 파싱하고 
	2. DBMS에게 실행계획을 받아낸다.
	3. 옵티마이저가 실행계획에 따라 처리한다.
	4. open, cursor .. fetch .. close

2. URL : jdbc:oracle:thin:ip(172:16.2.66:1521:orcl11) - SID 이름

주소방식을 사용한다.

디비 조인

1. 관계 형태에는 1:1, 1:n , n:n (조인하지 않는다.) - 카타시안의 곱이다.(데이터가 복제된다.) -> 일어날 수 있는 모든 경우의 수가 조회된다.
2. 카타시안의 곱 : 데이터를 복제할 목적이 아니라면 사용하지 않는다.
3. equals 조인은 natural 조인이란 양쪼 집합에 모두 존재하는 것만 출력한다.
4. 카타시안의 곱은 (n:n) 관계는 업무적인 정의가 덜 되었다. 설계가 덜 되었다. 

우편번호검색기


* 사용자로부터 동이름을 입력 받아서 조건 검색을 구현하기
* @Param dong
* sql문
* 		select zipcode, address 
-> 두개의 컬럼이 DTO or Map -> List에 담아라 -> row레벨을 담는 컨셉이다.
   			from zipcode_t
   			where dong like '당산' || '%';
* 화면이 존재하는 경우 DB서버에서 가져온 정보를 가지고 후처리를 해야함.
* 전처리는 Conection 맺는거.
* return타입을 void로 했으니까 
* UI-react-화면과 로직(Model-계층 = UI+데이터셋 만난다.) 분리
*DefaultTableModel -> addRow(Vector), addRow(Object[])
*-데이터셋에 데이터를 추가 하는  건 row 단위로 처리된다.

초기코드

package com.step6;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import com.util.DBConnectionMgr;

public class ZipCodeView extends JFrame implements ActionListener, FocusListener {
	//선언부
	String zdo = null;
	//물리적으로 떨어져 있는 db서버와 연결통로 만들기
	Connection 			con 	= null;
	//위에서 연결되면 쿼리문을 전달할 전령의 역할을 하는 인터페이스 객체 생성하기
	PreparedStatement 	pstmt 	= null;
	//조회된 결과를 화면에 처리해야 하므로 오라클에 커서를 조작하기 위해 ResultSet추가
	ResultSet 			rs 		= null;
	//JFrame 은 기본적으로 BorderLayout이다(동,서,남,북,중앙 배치)
	//디폴트는 FlowLayout, ->  BorderLayout -> setLayout
	//jp_north.add("Center", jtf_dong)
	//jp_north.add("West",jbtn_search)
	JPanel jp_north = new JPanel();//Div태그 span생각
	//insert here
	String zdos[] = {"전체","서울","경기","강원"};
	String zdos2[] = {"전체","부산","전남","대구"};
	Vector<String> vzdos = new Vector<>();//vzdos.size()==>0
	JComboBox jcb_zdo = new JComboBox(zdos);//West
	JComboBox jcb_zdo2 = null;//West
	JTextField jtf_search = new JTextField("동이름을 입력하세요.");//Center
	JButton jbtn_search = new JButton("조회");//East
	String cols[] = {"우편번호","주소"};
	String data[][] = new String[0][2];
	DefaultTableModel dtm_zipcode = new DefaultTableModel(data,cols);
	JTable jtb_zipcode = new JTable(dtm_zipcode);
	JTableHeader jth = jtb_zipcode.getTableHeader();
	JScrollPane jsp_zipcode = new JScrollPane(jtb_zipcode
			,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED
			,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
	String zdos3[] = null;
	 DBConnectionMgr dbMgr = null;//싱글톤 패턴으로 관리한다. 복제본을 만들지 않는다. 절대로....
	//MemberShip memberShip = null;
	//생성자
	public ZipCodeView() {
	}

	//화면처리부
	public void initDisplay() {
		jtb_zipcode.requestFocus();
		jtf_search.addFocusListener(this);
		jbtn_search.addActionListener(this);
		jtf_search.addActionListener(this);
		//북쪽 배치하는 속지를 FlowLayout-> 동서남북중앙 - UI솔루션
		jp_north.setLayout(new BorderLayout());
		/*	*/
		//vzdos.copyInto(zdos2);
		for(int x=0;x<zdos2.length;x++) {
			vzdos.add(zdos2[x]);
		}
		for(String s:vzdos) {
			System.out.println("s===>"+s);
		}
		//jcb_zdo2 = new JComboBox(zdos3);//West
		//jp_north.add("East",jcb_zdo2);
		jp_north.add("Center",jtf_search);
		jp_north.add("East",jbtn_search);
		this.add("North",jp_north);
		this.add("Center",jsp_zipcode);
		this.setTitle("우편번호 검색");
		this.setSize(430, 400);
		this.setVisible(true);
	}
	//메인메소드
	public static void main(String[] args) {
		ZipCodeView zcs = new ZipCodeView();
		zcs.initDisplay();
	}
	/******************************************************
	 * 사용자로부터 동이름을 입력 받아서 조건 검색을 구현하기
	 * @param dong - 동이름
	 * sql문
		SELECT zipcode, address - 두 개의 컬럼이 DTO or Map - > List담아라 - > row레벨을 담는다
		  FROM zipcode_t
		 WHERE dong LIKE ?||'%';	  
	 * 화면이 존재하는 경우 DB서버에서 가져온 정보를 가지고 후처리를 해야 함
	 * return타입을 void로 했으니까 이 메소드에서 화면처리까지 진행함
	 * UI - react - 화면과 로직(Model계층-UI+데이터셋만난다) 분리  - 
	 * 데이터셋에 데이터를 추가하는 것은 row단위(1차배열,  Vector)로 처리된다
	 * DefaultTableModel -> addRow(Objectr[]), addRow(Vector)
	 * ClassNotFoundException - > ojdbc6.jar ->  build path
	 * NullPointerException발동 -> con.prepareStatement("SELECT문"); - con이 널이다. ip주소, port:1521, 1522, `1523
	 * scott/tiger - 인증실패관련메시지
	 * sid가 이미 설치된 컴터 orcl
	 * SQLException은 sql문의 오류이다. 자바의 문제가 아님 - 토드에서 단위테스트 해볼것.
	 ******************************************************/
	public void refreshData(String dong) {
		List<Map<String,Object>> list = new ArrayList<>();
		StringBuilder sql = new StringBuilder();
		sql.append("SELECT zipcode, address    ");
		sql.append("  FROM zipcode_t           ");
		sql.append(" WHERE dong LIKE ?||'%'");
		dbMgr = DBConnectionMgr.getInstance();
		try {
			con = dbMgr.getConnection();//물리적으로 떨어져 있는 서버와 연결통로 확보
			pstmt = con.prepareStatement(sql.toString());//쿼리문을 먼저 스캔하여 있을 지 모르는 변수의 자리를 치환할것.
			pstmt.setString(1, dong);//dong, 당산, 가산, 공덕
			rs = pstmt.executeQuery();
			Map<String,Object> rmap = null;
			while(rs.next()) {
				rmap = new HashMap<>();
				rmap.put("zipcode", rs.getInt("zipcode"));
				rmap.put("address", rs.getString("address"));
				list.add(rmap);
			}
			System.out.println(list);//주소번지가 33번 출력될것이다. - 단위테스트 하자
		} catch (SQLException se) {
			System.out.println(sql.toString());//출력된 쿼리문을 갈무리해서 토드에서 확인해 볼것.
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		Object obj = e.getSource();
		if(obj == jbtn_search || obj == jtf_search) {
			System.out.println(jtf_search.getText());//당산
			String dong = jtf_search.getText();
			refreshData(dong);
		}
		
	}

	@Override
	public void focusGained(FocusEvent e) {
		Object obj = e.getSource();
		if(obj == jtf_search) {
			jtf_search.setText("");
		}
		
	}

	@Override
	public void focusLost(FocusEvent e) {
		// TODO Auto-generated method stub
		
	}
}

Step-1

사용자로부터 동이름을 입력 받아서 조건 검색을 구현하기

	 * 사용자로부터 동이름을 입력 받아서 조건 검색을 구현하기
	 * @param dong - 동이름
	 * sql문
		SELECT zipcode, address - 두 개의 컬럼이 DTO or Map - > List담아라 - > row레벨을 담는다
		  FROM zipcode_t
		 WHERE dong LIKE ?||'%';	  
	 * 화면이 존재하는 경우 DB서버에서 가져온 정보를 가지고 후처리를 해야 함
	 * return타입을 void로 했으니까 이 메소드에서 화면처리까지 진행함
	 * UI - react - 화면과 로직(Model계층-UI+데이터셋만난다) 분리  - 
	 * 데이터셋에 데이터를 추가하는 것은 row단위(1차배열,  Vector)로 처리된다
	 * DefaultTableModel -> addRow(Objectr[]), addRow(Vector)
	 * ClassNotFoundException - > ojdbc6.jar ->  build path
	 * NullPointerException발동 -> con.prepareStatement("SELECT문"); - con이 널이다. ip주소, port:1521, 1522, `1523
	 * scott/tiger - 인증실패관련메시지
	 * sid가 이미 설치된 컴터 orcl
	 * SQLException은 sql문의 오류이다. 자바의 문제가 아님 - 토드에서 단위테스트 해볼것.
package com.step6;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import com.util.DBConnectionMgr;

public class ZipCodeView extends JFrame implements ActionListener, FocusListener {
	//선언부
	String zdo = null;
	//물리적으로 떨어져 있는 db서버와 연결통로 만들기
	Connection 			con 	= null;
	//위에서 연결되면 쿼리문을 전달할 전령의 역할을 하는 인터페이스 객체 생성하기
	PreparedStatement 	pstmt 	= null;
	//조회된 결과를 화면에 처리해야 하므로 오라클에 커서를 조작하기 위해 ResultSet추가
	ResultSet 			rs 		= null;
	//JFrame 은 기본적으로 BorderLayout이다(동,서,남,북,중앙 배치)
	//디폴트는 FlowLayout, ->  BorderLayout -> setLayout
	//jp_north.add("Center", jtf_dong)
	//jp_north.add("West",jbtn_search)
	JPanel jp_north = new JPanel();//Div태그 span생각
	//insert here
	String zdos[] = {"전체","서울","경기","강원"};
	String zdos2[] = {"전체","부산","전남","대구"};
	Vector<String> vzdos = new Vector<>();//vzdos.size()==>0
	JComboBox jcb_zdo = new JComboBox(zdos);//West
	JComboBox jcb_zdo2 = null;//West
	JTextField jtf_search = new JTextField("동이름을 입력하세요.");//Center
	JButton jbtn_search = new JButton("조회");//East
	String cols[] = {"우편번호","주소"};
	String data[][] = new String[0][2];
	DefaultTableModel dtm_zipcode = new DefaultTableModel(data,cols);
	JTable jtb_zipcode = new JTable(dtm_zipcode);
	JTableHeader jth = jtb_zipcode.getTableHeader();
	JScrollPane jsp_zipcode = new JScrollPane(jtb_zipcode
			,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED
			,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
	String zdos3[] = null;
	 DBConnectionMgr dbMgr = null;//싱글톤 패턴으로 관리한다. 복제본을 만들지 않는다. 절대로....
	//MemberShip memberShip = null;
	//생성자
	public ZipCodeView() {
	}

	//화면처리부
	public void initDisplay() {
		jtb_zipcode.requestFocus();
		jtf_search.addFocusListener(this);
		jbtn_search.addActionListener(this);
		jtf_search.addActionListener(this);
		//북쪽 배치하는 속지를 FlowLayout-> 동서남북중앙 - UI솔루션
		jp_north.setLayout(new BorderLayout());
		/*	*/
		//vzdos.copyInto(zdos2);
		for(int x=0;x<zdos2.length;x++) {
			vzdos.add(zdos2[x]);
		}
		for(String s:vzdos) {
			System.out.println("s===>"+s);
		}
		//jcb_zdo2 = new JComboBox(zdos3);//West
		//jp_north.add("East",jcb_zdo2);
		jp_north.add("Center",jtf_search);
		jp_north.add("East",jbtn_search);
		this.add("North",jp_north);
		this.add("Center",jsp_zipcode);
		this.setTitle("우편번호 검색");
		this.setSize(430, 400);
		this.setVisible(true);
	}
	//메인메소드
	public static void main(String[] args) {
		ZipCodeView zcs = new ZipCodeView();
		zcs.initDisplay();//화면이 먼저 열리도록 하고 오라클서버를 나중에 연결하자
		//zcs.refreshData("가산");
	}

	public void refreshData(String dong) {
		List<Map<String,Object>> list = new ArrayList<>();
		StringBuilder sql = new StringBuilder();
		sql.append("SELECT zipcode, address    ");
		sql.append("  FROM zipcode_t           ");
		sql.append(" WHERE dong LIKE ?||'%'");
		dbMgr = DBConnectionMgr.getInstance();
		try {
			con = dbMgr.getConnection();//물리적으로 떨어져 있는 서버와 연결통로 확보
			pstmt = con.prepareStatement(sql.toString());//쿼리문을 먼저 스캔하여 있을 지 모르는 변수의 자리를 치환할것.
			pstmt.setString(1, dong);//dong, 당산, 가산, 공덕
			rs = pstmt.executeQuery();
			Map<String,Object> rmap = null;
			while(rs.next()) {
				rmap = new HashMap<>();
				rmap.put("zipcode", rs.getInt("zipcode"));
				rmap.put("address", rs.getString("address"));
				list.add(rmap);
			}
			System.out.println(list);//주소번지가 33번 출력될것이다. - 단위테스트 하자
			//메소드 설계가 리턴타입이 빠져 있으므로 화면 처리까지 여기서 해야 함.
			for(int i=0;i<list.size();i++) {//33번 반복됨 - row수
				Map<String, Object> map = list.get(i);
				Vector<Object> v = new Vector<>();
				v.add(0,map.get("zipcode"));
				v.add(1,map.get("address"));
				dtm_zipcode.addRow(v);
			}
		} catch (SQLException se) {
			System.out.println(sql.toString());//출력된 쿼리문을 갈무리해서 토드에서 확인해 볼것.
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		Object obj = e.getSource();
		if(obj == jbtn_search || obj == jtf_search) {
			System.out.println(jtf_search.getText());//당산
			String dong = jtf_search.getText();
			refreshData(dong);
		}
		
	}

	@Override
	public void focusGained(FocusEvent e) {
		Object obj = e.getSource();
		if(obj == jtf_search) {
			jtf_search.setText("");
		}
		
	}

	@Override
	public void focusLost(FocusEvent e) {
		// TODO Auto-generated method stub
		
	}
}

----------------------------------------
s===>전체
s===>부산
s===>전남
s===>대구
당산
[{zipcode=150040, address=서울 영등포구 당산동}, {zipcode=150041, address=서울 영등포구 당산동1}, {zipcode=150800, address=서울 영등포구 당산동11~256}, {zipcode=150750, address=서울 영등포구 당산동1가 진로아파트}, {zipcode=150801, address=서울 영등포구 당산동1257~457}, {zipcode=150042, address=서울 영등포구 당산동2}, {zipcode=150935, address=서울 영등포구 당산동2가 대우미래사랑}, {zipcode=150935, address=서울 영등포구 당산동2가 대우메종리브르}, {zipcode=150752, address=서울 영등포구 당산동2가 당산2가현대아파트 101-107}, {zipcode=150043, address=서울 영등포구 당산동3}, {zipcode=150802, address=서울 영등포구 당산동31~10}, {zipcode=150803, address=서울 영등포구 당산동311~384}, {zipcode=150804, address=서울 영등포구 당산동3385~560}, {zipcode=150720, address=서울 영등포구 당산동3가 영등포구청}, {zipcode=150955, address=서울 영등포구 당산동3가 영등포세무서}, {zipcode=150720, address=서울 영등포구 당산동3가 영등포구보건소}, {zipcode=150802, address=서울 영등포구 당산동3561~563}, {zipcode=150044, address=서울 영등포구 당산동4}, {zipcode=150805, address=서울 영등포구 당산동41~32}, {zipcode=150722, address=서울 영등포구 당산동4가 동양타워빌딩}, {zipcode=150753, address=서울 영등포구 당산동4가 현대3차아파트 101-106}, {zipcode=150754, address=서울 영등포구 당산동4가 현대5차아파트 501-513}, {zipcode=150806, address=서울 영등포구 당산동433~96}, {zipcode=150045, address=서울 영등포구 당산동5}, {zipcode=150755, address=서울 영등포구 당산동5가 효성아파트}, {zipcode=150771, address=서울 영등포구 당산동5가 삼성래미안4차아파트 401-425}, {zipcode=150046, address=서울 영등포구 당산동6}, {zipcode=150807, address=서울 영등포구 당산동61~120}, {zipcode=150808, address=서울 영등포구 당산동6121~173}, {zipcode=150809, address=서울 영등포구 당산동6174~325}, {zipcode=150810, address=서울 영등포구 당산동6326~378}, {zipcode=150942, address=서울 영등포구 당산동6가 강변삼성래미안아파트 301-313}, {zipcode=150723, address=서울 영등포구 당산동2가 영등포유통상가}]

Exception 종류

	
	 * 올 수 있는 Exception 종류는?
	 * 1. ClassNotFoundException -> ojdbc6.jar -> build path 문제
	 * 
	 * 2. NullPointerException발동 
	 * -> con.prepareStatement("SELECT문"); - con이 null이다. 
	 * -> ip 주소가 문제다.(port1521,1522,1523)
	 * -> scott/tiger - 인증 실패 관련 메시지
	 * ->sid가 이미 설치된 컴터 orcl 바꿔줘야 한다.
	 * 
	 * 3.SQLException은 sql문의 오류이다. 자바의 문제가 아님 
	 * -> 토드에서 단위테스트 해볼것.
	 

최종코드

MemberShipView

package com.chat;

import java.awt.FlowLayout;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;

public class MemberShipView extends JDialog implements ActionListener{
    //선언부
    JPanel jp_center = new JPanel();
    JLabel jlb_id = new JLabel("아이디");
    JTextField jtf_id = new JTextField(10);
    JLabel jlb_pw = new JLabel("패스워드");
    JTextField jtf_pw = new JTextField(10);
    JLabel jlb_nickName = new JLabel("대화명");
    JTextField jtf_nickName = new JTextField(20);
    JLabel jlb_name = new JLabel("성명");
    JTextField jtf_name = new JTextField(30);
    JLabel jlb_gender = new JLabel("성별");
    String[] genderList = {"남자","여자"};
    JComboBox jcb_gender = new JComboBox(genderList);
    JLabel 		jlb_zipcode = new JLabel("우편번호");
    public JTextField 	jtf_zipcode = new JTextField(6);
    JLabel 		jlb_address = new JLabel("주소");
    public JTextField 	jtf_address = new JTextField(100);
    JButton     jbtn_zipcode = new JButton("우편번호찾기");
    JScrollPane jsp = null;
    JPanel jp_south = new JPanel();
    JButton jbtn_ins = new JButton("등록");
    JButton jbtn_close = new JButton("닫기");
    //insert here
    //우편번호 검색기 클래스를 전역변수 자리에서 생성한다 -  MemberShipView가 생성될때 그때 생성이 됨
    //파라미터 자리에 this를 쓸 수 있는건 이 어플리케이션을 실행했을때 비로서 객체가 로딩됨
    ZipCodeView zcView = new ZipCodeView(this);//this는 현재 로딩중인 원본이다.
    //생성자
    public MemberShipView(){
        //initDisplay();
    }
    //화면처리부
    public void initDisplay() {
        jbtn_zipcode.addActionListener(this);
        jp_center.setLayout(null);
        jlb_id.setBounds(20, 20, 100, 20);
        jtf_id.setBounds(120, 20, 120, 20);
        jlb_pw.setBounds(20, 45, 100, 20);
        jtf_pw.setBounds(120, 45, 120, 20);
        jlb_nickName.setBounds(20, 70, 100, 20);
        jtf_nickName.setBounds(120, 70, 150, 20);
        jlb_name.setBounds(20, 95, 100, 20);
        jtf_name.setBounds(120, 95, 150, 20);
        jlb_gender.setBounds(20, 120, 100, 20);
        jcb_gender.setBounds(120, 120, 150, 20);
        jcb_gender.setFont(new Font("굴림",1,14));
        jlb_zipcode.setBounds(20, 145, 100, 20);
        jtf_zipcode.setBounds(120, 145, 100, 20);
        jbtn_zipcode.setBounds(230, 145, 120, 20);
        jlb_address.setBounds(20, 170, 100, 20);
        jtf_address.setBounds(120, 170, 250, 20);
        jp_center.add(jlb_id);
        jp_center.add(jtf_id);
        jp_center.add(jlb_pw);
        jp_center.add(jtf_pw);
        jp_center.add(jlb_nickName);
        jp_center.add(jtf_nickName);
        jp_center.add(jlb_name);
        jp_center.add(jtf_name);
        jp_center.add(jlb_gender);
        jp_center.add(jcb_gender);
        jp_center.add(jlb_zipcode);
        jp_center.add(jtf_zipcode);
        jp_center.add(jbtn_zipcode);
        jp_center.add(jlb_address);
        jp_center.add(jtf_address);
        jp_south.setLayout(new FlowLayout(FlowLayout.RIGHT));
        jp_south.add(jbtn_ins);
        jp_south.add(jbtn_close);
        this.add("South",jp_south);
        jsp = new JScrollPane(jp_center);
        this.add("Center",jsp);
        this.setTitle("회원가입");
        this.setSize(400, 500);
        this.setVisible(true);
    }
    public static void main(String[] args) {
    	MemberShipView ms = new MemberShipView();// 전역변수자리에 인스턴스화 한 객체들이 비로서 이때 로딩이 됨
        ms.initDisplay();
    }
    @Override
    public void actionPerformed(ActionEvent e) {
    	System.out.println("action");
        Object obj = e.getSource();
        if(obj == jbtn_zipcode) {
            //insert here 우편번호 검색기
        	zcView.initDisplay();
        }
    }
}

ZipCodeView


package com.chat;


import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.JTableHeader;
import com.util.DBConnectionMgr;

public class ZipCodeView extends JFrame implements ActionListener, FocusListener, MouseListener {
	//선언부
	String zdo = null;
	//물리적으로 떨어져 있는 db서버와 연결통로 만들기
	Connection 			con 	= null;
	//위에서 연결되면 쿼리문을 전달할 전령의 역할을 하는 인터페이스 객체 생성하기
	PreparedStatement 	pstmt 	= null;
	//조회된 결과를 화면에 처리해야 하므로 오라클에 커서를 조작하기 위해 ResultSet추가
	ResultSet 			rs 		= null;
	//JFrame 은 기본적으로 BorderLayout이다(동,서,남,북,중앙 배치)
	//디폴트는 FlowLayout, ->  BorderLayout -> setLayout
	//jp_north.add("Center", jtf_dong)
	//jp_north.add("West",jbtn_search)
	JPanel jp_north = new JPanel();//Div태그 span생각
	//insert here
	String zdos[] = {"전체","서울","경기","강원"};
	String zdos2[] = {"전체","부산","전남","대구"};
	Vector<String> vzdos = new Vector<>();//vzdos.size()==>0
	JComboBox jcb_zdo = new JComboBox(zdos);//West
	JComboBox jcb_zdo2 = null;//West
	JTextField jtf_search = new JTextField("동이름을 입력하세요.");//Center
	JButton jbtn_search = new JButton("조회");//East
	String cols[] = {"우편번호","주소"};
	String data[][] = new String[0][2];
	DefaultTableModel dtm_zipcode = new DefaultTableModel(data,cols);
	JTable jtb_zipcode = new JTable(dtm_zipcode);
	JTableHeader jth = jtb_zipcode.getTableHeader();
	JScrollPane jsp_zipcode = new JScrollPane(jtb_zipcode
			,JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED
			,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
	String zdos3[] = null;
	 DBConnectionMgr dbMgr = null;//싱글톤 패턴으로 관리한다. 복제본을 만들지 않는다. 절대로....
	MemberShipView memberShipView = null;//null이 뭔가를 가리키는 시점은 ZipCodeVIew생성자가 호출될때
	//생성자
	public ZipCodeView() {
	}

	public ZipCodeView(MemberShipView memberShipView) {
		this.memberShipView = memberShipView;// 재정의, 치환하기
	}

	//화면처리부
	public void initDisplay() {
		jtb_zipcode.requestFocus();
		jtf_search.addFocusListener(this);
		jtb_zipcode.addMouseListener(this);
		jbtn_search.addActionListener(this);
		jtf_search.addActionListener(this);
		//북쪽 배치하는 속지를 FlowLayout-> 동서남북중앙 - UI솔루션
		jp_north.setLayout(new BorderLayout());
		/*	*/
		//vzdos.copyInto(zdos2);
		for(int x=0;x<zdos2.length;x++) {
			vzdos.add(zdos2[x]);
		}
		for(String s:vzdos) {
			System.out.println("s===>"+s);
		}
		//jcb_zdo2 = new JComboBox(zdos3);//West
		//jp_north.add("East",jcb_zdo2);
		jp_north.add("Center",jtf_search);
		jp_north.add("East",jbtn_search);
		this.add("North",jp_north);
		this.add("Center",jsp_zipcode);
		this.setTitle("우편번호 검색");
		this.setSize(430, 400);
		this.setVisible(true);
	}
	//메인메소드
	public static void main(String[] args) {
		ZipCodeView zcs = new ZipCodeView();
		zcs.initDisplay();//화면이 먼저 열리도록 하고 오라클서버를 나중에 연결하자
		//zcs.refreshData("가산");
	}
	/******************************************************
	 * 사용자로부터 동이름을 입력 받아서 조건 검색을 구현하기
	 * @param dong - 동이름
	 * sql문
		SELECT zipcode, address - 두 개의 컬럼이 DTO or Map - > List담아라 - > row레벨을 담는다
		  FROM zipcode_t
		 WHERE dong LIKE ?||'%';	  
	 * 화면이 존재하는 경우 DB서버에서 가져온 정보를 가지고 후처리를 해야 함
	 * return타입을 void로 했으니까 이 메소드에서 화면처리까지 진행함
	 * UI - react - 화면과 로직(Model계층-UI+데이터셋만난다) 분리  - 
	 * 데이터셋에 데이터를 추가하는 것은 row단위(1차배열,  Vector)로 처리된다
	 * DefaultTableModel -> addRow(Objectr[]), addRow(Vector)
	 * ClassNotFoundException - > ojdbc6.jar ->  build path
	 * NullPointerException발동 -> con.prepareStatement("SELECT문"); - con이 널이다. ip주소, port:1521, 1522, `1523
	 * scott/tiger - 인증실패관련메시지
	 * sid가 이미 설치된 컴터 orcl
	 * SQLException은 sql문의 오류이다. 자바의 문제가 아님 - 토드에서 단위테스트 해볼것.
	 ******************************************************/
	public void refreshData(String dong) {
		List<Map<String,Object>> list = new ArrayList<>();
		StringBuilder sql = new StringBuilder();
		sql.append("SELECT zipcode, address    ");
		sql.append("  FROM zipcode_t           ");
		sql.append(" WHERE dong LIKE ?||'%'");
		dbMgr = DBConnectionMgr.getInstance();
		try {
			con = dbMgr.getConnection();//물리적으로 떨어져 있는 서버와 연결통로 확보
			pstmt = con.prepareStatement(sql.toString());//쿼리문을 먼저 스캔하여 있을 지 모르는 변수의 자리를 치환할것.
			pstmt.setString(1, dong);//dong, 당산, 가산, 공덕
			rs = pstmt.executeQuery();
			Map<String,Object> rmap = null;
			while(rs.next()) {
				rmap = new HashMap<>();
				rmap.put("zipcode", rs.getInt("zipcode"));
				rmap.put("address", rs.getString("address"));
				list.add(rmap);
			}
			System.out.println(list);//주소번지가 33번 출력될것이다. - 단위테스트 하자
			//메소드 설계가 리턴타입이 빠져 있으므로 화면 처리까지 여기서 해야 함.
			for(int i=0;i<list.size();i++) {//33번 반복됨 - row수
				Map<String, Object> map = list.get(i);
				Vector<Object> v = new Vector<>();
				v.add(0,map.get("zipcode"));
				v.add(1,map.get("address"));
				dtm_zipcode.addRow(v);
			}
		} catch (SQLException se) {
			System.out.println(sql.toString());//출력된 쿼리문을 갈무리해서 토드에서 확인해 볼것.
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		Object obj = e.getSource();
		if(obj == jbtn_search || obj == jtf_search) {
			System.out.println(jtf_search.getText());//당산
			String dong = jtf_search.getText();
			refreshData(dong);
		}
		
	}

	@Override
	public void focusGained(FocusEvent e) {
		Object obj = e.getSource();
		if(obj == jtf_search) {
			jtf_search.setText("");
		}
		
	}

	@Override
	public void focusLost(FocusEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseClicked(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mousePressed(MouseEvent e) {
		if(e.getClickCount()==2) {//더블클릭한거야?
			//화면 테이블에서 더블클릭했을 때 선택된 로우의 index값을 반환해줌
			int index = jtb_zipcode.getSelectedRow();//1.8부터 오토박싱을 통해서 int와 Wrapper클래스는 자동으로 형전환
			int zipcode = (int)dtm_zipcode.getValueAt(index, 0);//선택된 로우의 우편번호가 담김
			String address = (String)dtm_zipcode.getValueAt(index, 1);
			System.out.println(zipcode +",  "+ address);//
			//insert here - 부모창인 회원가입 창에서 우편번호 와 주소자리(MemberShipView)에 조회된 결과를 자동으로 출력해줌
			//부모(MemberShipView)의 주소번지가 필요하다.
			//valueOf메소드의 파라미터자리에 어떤 값이 오든 String 타입으로 형전환해주는 메소드 이다.
			//관전 포인트 하나더 - 싱글톤으로 제공되는 메소드 입니다.
			//MemberShipView를 인스턴스화 하면 그 때 즉시 전역변수의 ZipCodeView객체가 생성되고 이때 파라미터 자리에 this는
			//앞에 인스턴스화를 통해 현재 로딩 중인 그 원본이므로 복사본이 아니다.
			memberShipView.jtf_zipcode.setText(String.valueOf(zipcode));
			memberShipView.jtf_address.setText(String.valueOf(address));
		}
	}

	@Override
	public void mouseReleased(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseEntered(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void mouseExited(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
}
profile
아는만큼보인다.

0개의 댓글