(17)-23.10.17[JAVA]

DANA·2023년 10월 17일

KDT-구디아카데미

목록 보기
17/56
// 테스트의 예외처리
package com.util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

// 테스트 시나리오를 작성할 수 있다.
// 무엇을 테스트 할 것인가?
// 예외처리를 하는 것은 서비스의 안정화를 위한 필수이다.
public class Exception1 {
	DBConnectionMgr dbMgr = null; // 인스턴스화를 직접하지 않는다
	// 전역변수 자리에 추가한 인스턴스화는 언제 메모리에 상주하는가?
	// new Exception1()했을 때 비로소 그 때에야 메모리 상주됨 - 시점
	DBConnectionMgr dbMgr2 = new DBConnectionMgr();
	Connection con = null;
	PreparedStatement pstmt = null; // 쿼리문을 스캔. select:pstmt.executeQuery():ResultSet, insert|upate|delete -> executeUpdate():int
	ResultSet rs = null;
	Exception1(){
		dbMgr = DBConnectionMgr.getInstance();
		System.out.println("Exception1():"+dbMgr);
		test(20);
	}
	public void test(int deptno) {
		System.out.println("test():"+dbMgr);
		System.out.println(con);
		try {
			// 인터페이스가 getConnection메소드 호출을 통해서 주소번지 갖게 되었다(메모리에 상주하게 되었다)->상주하지 않으면 NullPointerException
			con = dbMgr.getConnection();
			System.out.println(con);
			pstmt = con.prepareStatement("SELECT deptno, dname, loc FROM dept WHERE deptno=?");
			pstmt.setInt(1, deptno); 
			rs = pstmt.executeQuery(); // 오라클서버에게 select 처리해줘
			System.out.println(rs.next());
			System.out.println(rs.isFirst());
			System.out.println(rs.next()); // 왜 false가 나오지? 데이터 조회결과가 1건이니까
			// System.out.println(rs.isLast());
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		new Exception1();
	}

}
package com.step5;

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Vector;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;

import com.google.gson.Gson;
import com.util.DBConnectionMgr;
// ActionListener al = new DeptManager();
//자바는 단일 상속만 가능하다.- 다중상속은 불가함 - 다중상속의 단점을 보완하기 위해 인터페이스가 제공됨
//단 인터페이스는 여러개를 implements할 수 있다.(추상클래스, 인터페이스는 설계관점에서 중요함 - 특징, 컨벤션)
public class DeptManager3 extends JFrame implements ActionListener{
	//선언부
	//JDBC API 를 활용하여 오라클 서버에서 부서목록 조회하기
	Connection 					con  	= null;//연결통로확보
	PreparedStatement 	pstmt 	= null;//Connection생성되야 PreparedStatement메모리 로딩됨
	//데이터베이스가 지원하는 커서를 조작하는데 필요한 메소드를 정의하고 있는 인터페이스이다.
	ResultSet						rs			= null;//open..cursor..fectch..close 커서를 조작해서 원하는 정보를 반환받음
	//공통코드에서 재사용 가능한 메소드를 설계함
	DBConnectionMgr dbMgr = null;                                                       
	List<Map<String, Object>> deptList = new ArrayList<>();//왜 전역변수로 하는가? 입력|수정|삭제|조회
	String header[] = {"부서번호","부서명","지역"};
	String datas[][] = new String[0][0];//2차배열 - 대괄호가 2쌍이 필요함
	//생성자의 파라미터를 통해서 서로 다른 클래스가 의존관계를 맺고 하나의 기능을 서비스 할 수  있다.
	//생성자도 파라미터를 여러개 갖을 수 있다. - 메소드 오버로딩
	DefaultTableModel dtm_dept = new DefaultTableModel(datas, header);//<table>-양식  자바가 있어야 DataSet구성함
	JTable jt_dept = new JTable(dtm_dept);
	JScrollPane jsp_dept = new JScrollPane(jt_dept);
	JPanel jp_north = new JPanel();
	JButton jbtnSelect = new JButton("조회");
	JButton jbtnDelete = new JButton("삭제");
	JButton jbtnAdd = new JButton("행추가");
	JButton jbtnDel = new JButton("행삭제");
	JButton jbtnExit = new JButton("종료");
	//생성자
	//A a = new A();//기초
	//A a = A.getInstance();//복제본을 허락하지 않고 원본 하나만 관리한다. - 싱글톤 패턴
	//B  b = new A();//추상클래스 상속관계
	//C c = new A();//인터페이스 구현체 클래스
	// 접근제한자가 없는 경우는 friendly 상태라 하는데
	// 다른 패키지에서 접근이 불가능한 상태임
	// public > protected(패키지가 다르더라도 서로 상속관계면 접근 가능하다) > friendly상태 > private
	public DeptManager3(){
		//메소드를 통해서 객체를 주입받고 있는데 .연산자 앞에 인스턴스변수가 아니라 클래스 타입이 직접 사용되었다.
		dbMgr  = DBConnectionMgr.getInstance();//초기화 하였다.
		//Calendar cal = Calendar.getInstance();
		initDisplay();
	}////////////// end of DeptManager

	//화면 처리부
	public void initDisplay() {
		jbtnSelect.addActionListener(this);
		jbtnDelete.addActionListener(this);
		jbtnAdd.addActionListener(this);//행추가
		jbtnDel.addActionListener(this);//행삭제
		jp_north.setLayout(new FlowLayout(FlowLayout.LEFT));
		jp_north.add(jbtnSelect);
		jp_north.add(jbtnDelete);
		jp_north.add(jbtnAdd);//행추가 JPanel붙이기
		jp_north.add(jbtnDel);
		jp_north.add(jbtnExit);
		this.add("North", jp_north);
		this.add("Center", jsp_dept);
		this.setSize(500, 400);//this:DeptManager
		this.setVisible(true);
	}//////////// end of initDisplay  /////////////
	//select가 모든 업무 페이지의 시작 페이지이므로  맡은 업무의 첫 시작임 - 
	//어떤 경우에 제네릭을 Map으로 가져갈 것인가? -  List<Map<String,Object>> -> 조인시에 선택한다
	//현재 메소드 getDTOList는 무엇이 문제인가?
	public List<DeptDTO> getDTOList(){//먼저 연습하고 Map을 연습 할것
		System.out.println("제네릭 타입을 getter/setter로 처리할때");
		List<DeptDTO> list = new ArrayList<>();//list.size()=0
		StringBuilder sql = new StringBuilder();
		sql.append("SELECT deptno, dname, loc FROM dept");//4건 모두 조회함 10,20,30,40
		try {
			//아래 코드에서 NullPointerException이 발생 했다면 생성자에서 객체 주입이 안됨
			//dbMgr.코드에서 직접적인 원인이 있음
			//DBConnectionMgr이 생성되어야 getConnection메소드를 호출할 수 있을 것이고
			//호출이 되어야 리턴값으로 Connection 객체를 주입 받음
			con = dbMgr.getConnection();
			pstmt = con.prepareStatement(sql.toString());
			rs = pstmt.executeQuery();
			DeptDTO dto = null;
			while(rs.next()) {
				//아래 코드에서 반복문이 실행될 때마다 서로 다른 주소번지가 4개 만들어지니까
				//문제점 - DeptDTO는 테이블 dept테이블을 클래스로 설계한 것이다.
				dto = new DeptDTO(rs.getInt("deptno"), rs.getString("dname"),rs.getString("loc"));
				//아래 코드를 작성하지 않으면 4개의 정보가 모두 유지되지 않음
				list.add(dto);//0, null, null, 0 ,null, null, 0,null, null, 0 , null,null
			}
			System.out.println(list);
			//자바를 통해서 DB연동한 후에 후처리하기(자바컬렉션 프레임워크를 JSON포맷으로 변경함)
			//Gson g = new Gson();브라우저를 통해서 출력할 때만 사용하면 된다. - JSON포맷이어야 javascript에서 꺼내기가 가능함
			//String temp = g.toJson(list);
		} catch (SQLException se) {
			System.out.println(se.toString());//부적합한 식별자  - 컬럼명이 존재하지 않을 때 - SQLException해당됨
		} catch (Exception e) {
			e.printStackTrace();//stack메모리에 쌓여있는 에러 메시지 히스토리를 볼 수  있다.(라인번호와 함께 메시지 출력됨)
		}
		return list;
	}
	public List<Map<String,Object>> getMapList(){//2개 이상의 테이블 조인시 - 이것으로 연습 더 많이
		System.out.println("제네릭 타입을 Map으로 처리할 때");
		List<Map<String,Object>> list = new ArrayList<>();
		// StringBuffer는 스레드안전, StringBuilder 불안전하다 - 인터셉트를 당할 수 있다- 로컬이니까 괜찮아
		StringBuilder sql = new StringBuilder(); // String과 비교할 때 하나로 관리를 함 - 메모리에 대한 이익이 있다.
		//sql.append("SELECT deptno, dname, loc FROM dept");//4건 모두 조회함 10,20,30,40
		sql.append("SELECT empno, ename, sal, dname"); 
		sql.append("  FROM emp, dept               ");
		sql.append(" WHERE emp.deptno = dept.deptno");
		try {
			//아래 코드에서 NullPointerException이 발생 했다면 생성자에서 객체 주입이 안됨
			//dbMgr.코드에서 직접적인 원인이 있음
			//DBConnectionMgr이 생성되어야 getConnection메소드를 호출할 수 있을 것이고
			//호출이 되어야 리턴값으로 Connection 객체를 주입 받음
			con = dbMgr.getConnection();
			pstmt = con.prepareStatement(sql.toString());
			rs = pstmt.executeQuery();
			Map<String,Object>map = null;
			while(rs.next()) {
				//아래 코드에서 반복문이 실행될 때마다 서로 다른 주소번지가 4개 만들어지니까
				//문제점 - DeptDTO는 테이블 dept테이블을 클래스로 설계한 것이다.
				// 사용자 정의 DTO클래스처럼 생성자를 만들어서 사용불가함 - 제공받는 클래스이다.
				map = new HashMap<>();
				map.put("empno",rs.getInt(1));
				map.put("ename",rs.getString("ename"));
				map.put("sal",rs.getInt("sal"));
				map.put("dname",rs.getString("dname"));
				//아래 코드를 작성하지 않으면 4개의 정보가 모두 유지되지 않음
				// 사원의 수가 14명이다.
				list.add(map);//0, null, null, 0 ,null, null, 0,null, null, 0 , null,null
			}
			System.out.println(list);
			//자바를 통해서 DB연동한 후에 후처리하기(자바컬렉션 프레임워크를 JSON포맷으로 변경함)
			//Gson g = new Gson();브라우저를 통해서 출력할 때만 사용하면 된다. - JSON포맷이어야 javascript에서 꺼내기가 가능함
			//String temp = g.toJson(list);
		} catch (SQLException se) {
			System.out.println(se.toString());//부적합한 식별자  - 컬럼명이 존재하지 않을 때 - SQLException해당됨
		} catch (Exception e) {
			e.printStackTrace();//stack메모리에 쌓여있는 에러 메시지 히스토리를 볼 수  있다.(라인번호와 함께 메시지 출력됨)
		}		
		
		return list;
	}	
	//메인 메소드
	public static void main(String[] args) {
		JFrame.setDefaultLookAndFeelDecorated(true);
		DeptManager3 dm = new DeptManager3();//new JFrame()호출되는 것이다.
	}//////////////// end of main ////////////////
	@Override
	public void actionPerformed(ActionEvent e) {
		System.out.println("actionPerformed호출은 반드시 addActionListener가 있어야 됨");
		Object obj = e.getSource();
		//행삭제해 보기
		if(obj == jbtnDel) {
			//dtm_dept.removeRow(0);
			int index = jt_dept.getSelectedRow();//사용자가 선택한 로우의 index값을 반환함
			if(index<0) {//-1반환(EOF)
				JOptionPane.showMessageDialog(this,"삭제할 행을 선택하시오.","INFO", JOptionPane.INFORMATION_MESSAGE);
				return;//메소드 탈출
			}		
			else {
				dtm_dept.removeRow(index);
			}
		}
		//행추가해보기
		else if(obj == jbtnAdd) {
			//Vector addRow = new Vector();
			Object addRow2[] = new Object[3];
			dtm_dept.addRow(addRow2);
		}
		//너 삭제 할거니?
		else if(obj == jbtnDelete) {
			int index = jt_dept.getSelectedRow();//사용자가 선택한 로우의 index값을 반환함
			if(index<0) {//-1반환(EOF)
				JOptionPane.showMessageDialog(this,"삭제할 데이터를 선택하시오.","INFO", JOptionPane.INFORMATION_MESSAGE);
				return;//메소드 탈출
			}
			//여기로 못오게 함
			else {
				System.out.println(index);//index값을 add(int, E)  1 remove(1), 
				//insert here
				Map<String,Object> map = deptList.remove(index);
				System.out.println(map+", rdept.get(DEPTNO):"+map.get("DEPTNO"));
				//insert here - 삭제 성공하였습니다.
				if(map !=null) {
					JOptionPane.showMessageDialog(this, "삭제 성공하였습니다.","Info" , JOptionPane.INFORMATION_MESSAGE);
					refreshData();
				}else {
					JOptionPane.showMessageDialog(this, "삭제 실패하였습니다.","Info" , JOptionPane.ERROR_MESSAGE);
					return;
				}
			}
		}
		//너 조회버튼 누른거야?
		else if(obj == jbtnSelect) {
			System.out.println("조회버튼 클릭");//log
			List<DeptDTO> list = getDTOList();//오라클 서버에서 조회한 결과를 쥐고 있다. - 리턴타입이 쥐고 있다.
			while(dtm_dept.getRowCount()>0) {//dtm은 데이터셋(자바측)받는 클래스이다.
				dtm_dept.removeRow(0);//0번째 로우를 지우는 이유는 로우가 삭제 될때 마다 dtm의 로우수가 줄어든다. - 왜?
			}
			
			for(int i=0;i<list.size();i++) {//list.size()=4이다. 10,20,30,40
				DeptDTO dept = list.get(i);
				Vector<Object>  v = new Vector<>();//3번 생성됨
				v.add(0, dept.getDeptno());
				v.add(1,dept.getDname());
				v.add(2,dept.getLoc());
				//addRow메소드의 오버로딩은 2가지 임 - 1)Vector, 2)Object[]
				dtm_dept.addRow(v);//4번 반복 되니까 - 로우에 추가하는 코드를 4번 실행함 - list.size()=4
			}
		}////////////////// end of if ///////////////
		
	}///////////////////// end of actionPerformed
	//새로고침(F5) 구현하기
	public void refreshData() {
		while(dtm_dept.getRowCount()>0) {//dtm은 데이터셋(자바측)받는 클래스이다.
			dtm_dept.removeRow(0);//0번째 로우를 지우는 이유는 로우가 삭제 될때 마다 dtm의 로우수가 줄어든다. - 왜?
		}
		for(int i=0;i<deptList.size();i++) {
			Map<String,Object> map = deptList.get(i);
			Vector<Object>  v = new Vector<>();//3번 생성됨
			v.add(0,map.get("DEPTNO"));
			v.add(1,map.get("DNAME"));
			v.add(2,map.get("LOC"));
			dtm_dept.addRow(v);
		}	
	}//////////////////end of refreshData //////////////////
}
// DeptManager3 메소드 단위테스트
package com.util;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

import com.step5.DeptManager3;

// 테스트 시나리오를 작성할 수 있다.
// 무엇을 테스트 할 것인가?
// 예외처리를 하는 것은 서비스의 안정화를 위한 필수이다.
public class Exception1 {
	DBConnectionMgr dbMgr = null; // 인스턴스화를 직접하지 않는다
	// 전역변수 자리에 추가한 인스턴스화는 언제 메모리에 상주하는가?
	// new Exception1()했을 때 비로소 그 때에야 메모리 상주됨 - 시점
	DBConnectionMgr dbMgr2 = new DBConnectionMgr();
	Connection con = null;
	PreparedStatement pstmt = null; // 쿼리문을 스캔. select:pstmt.executeQuery():ResultSet, insert|upate|delete -> executeUpdate():int
	ResultSet rs = null;
	Exception1(){
		dbMgr = DBConnectionMgr.getInstance();
		System.out.println("Exception1():"+dbMgr);
		test(20);
	}
	public void test(int deptno) {
		System.out.println("test():"+dbMgr);
		System.out.println(con);
		try {
			// 인터페이스가 getConnection메소드 호출을 통해서 주소번지 갖게 되었다(메모리에 상주하게 되었다)->상주하지 않으면 NullPointerException
			con = dbMgr.getConnection();
			System.out.println(con);
			pstmt = con.prepareStatement("SELECT deptno, dname, loc FROM dept WHERE deptno=?");
			pstmt.setInt(1, deptno); 
			rs = pstmt.executeQuery(); // 오라클서버에게 select 처리해줘
			System.out.println(rs.next());
			System.out.println(rs.isFirst());
			System.out.println(rs.next()); // 왜 false가 나오지? 데이터 조회결과가 1건이니까
			// System.out.println(rs.isLast());
		}catch(Exception e){
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		// new Exception1();
		DeptManager3 dm = new DeptManager3();
		dm.getMapList();
	}

}

로그인 화면

(src 밑에 이미지 폴더 만들어서 이미지 넣으면 연동)

package com.step5;

import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;

public class LoginForm extends JFrame implements ActionListener {
	/////////////////////////////////////////////////////
	/* 선언부 */
	/////////////////////////////////////////////////////
	String nickName="";
	String imgPath="D:\\workspace_java\\dev_java\\src\\image\\";
	JLabel jlb_id = new JLabel("아이디");
	JLabel jlb_pw = new JLabel("패스워드");

	Font jl_font = new Font("휴먼매직체", Font.BOLD, 17);
	JTextField jtf_id = new JTextField("test");
	JPasswordField jpf_pw = new JPasswordField("123");

	JButton jbtn_login = new JButton(
			new ImageIcon(imgPath+"login.png"));
	JButton jbtn_join = new JButton(
			new ImageIcon(imgPath+"confirm.png"));

	// JPanel에 쓰일 이미지아이콘
	ImageIcon ig = new ImageIcon(imgPath+"main.PNG");

	/////////////////////////////////////////////////////
	/* 생성자 */
	/////////////////////////////////////////////////////
	public LoginForm(){
		initDisplay();
	}

	/////////////////////////////////////////////////////
	/* jpanal 오버라이드 */
	/////////////////////////////////////////////////////

	/* 배경이미지 */
	class mypanal extends JPanel {
		public void paintComponent(Graphics g) {
			g.drawImage(ig.getImage(), 0, 0, null);
			setOpaque(false);
			super.paintComponents(g);
		}
	}

	/////////////////////////////////////////////////////
	/* 화면처리 */
	/////////////////////////////////////////////////////
	public void initDisplay() {
		setContentPane(new mypanal());
		
		/* 버튼과 텍스트필드 구성 */
		jbtn_join.addActionListener(this);
		jbtn_login.addActionListener(this);
		this.setLayout(null);
		this.setTitle("자바채팅 ver.1");
		this.setSize(350, 600);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setVisible(true);
		this.setLocation(800, 250);
		this.addWindowListener(new WindowAdapter() {
			public void windowClosing(WindowEvent e) {
				System.exit(0);
			}
		});
		// id 라인
		jlb_id.setBounds(45, 200, 80, 40);
		jlb_id.setFont(jl_font);
		jtf_id.setBounds(110, 200, 185, 40);
		this.add(jlb_id);
		this.add(jtf_id);

		// pw 라인
		jlb_pw.setBounds(45, 240, 80, 40);
		jlb_pw.setFont(jl_font);
		jpf_pw.setBounds(110, 240, 185, 40);
		this.add(jlb_pw);
		this.add(jpf_pw);

		// 로그인 버튼 라인
		jbtn_login.setBounds(175, 285, 120, 40);
		this.add(jbtn_login);

		// 회원가입 버튼 라인
		jbtn_join.setBounds(45, 285, 120, 40);
		this.add(jbtn_join);		
	}

	public static void main(String[] args) throws Exception {
		new LoginForm();
	}
	@Override
	public void actionPerformed(ActionEvent e) {
		Object obj = e.getSource();
		if (obj == jbtn_join) {
			//new memberJoin();
		} 
		else if (obj == jbtn_login) {
			if ( "".equals(jtf_id.getText()) || "".equals(jpf_pw.getText()) ){
				JOptionPane.showMessageDialog(this, "아이디와 비밀번호를 확인하세요.", "경고", 2);
				return;
			}
			try {
				String mem_id = jtf_id.getText();
				String mem_pwd = jpf_pw.getText();
				if (nickName.length()==0) {
					JOptionPane.showMessageDialog(this, "아이디와 비밀번호를 확인하세요.", "경고", 2);
					return;
				} else {
					JOptionPane.showMessageDialog(this, nickName + "님의 접속을 환영합니다.");
					this.setVisible(false);
					jtf_id.setText("");
					jpf_pw.setText("");
					//new WaitingRoom(this);
				}
			} catch (Exception ae) { 
				ae.printStackTrace();
			}
		}
	}
}

회원가입 - 우편번호 연동

//회원가입하기 // 우편번호 눌렀을 때 이전시간 화면(주소 나오는) 연동되게 하기
package com.step6;

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();
        }
    }
}
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, 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 = (int)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
		
	}
}

0개의 댓글