// 테스트의 예외처리
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
}
}