------------------------------------------------
회원관리 JDBC 프로그램 작성2
-> 자료형 클래스 및 액션, 화면구성 클래스 분리


1. 기능 구현
- 이름, 전화번호를 입력 받아서 데이터베이스에 저장
- 번호, 이름, 전화번호를 콘솔에 출력

2. 화면 구성
이름 전화번호(x exit)?kim 010-123-1234
1명의 회원이 추가되었습니다.
이름 전화번호(x exit)?x

------------------
전체 회원수 : 1명
------------------
번호 이름 전화번호
1 kim 010-123-1234
------------------

3. 데이터베이스 준비


--테이블 생성
CREATE TABLE memberList (
  mid NUMBER --회원 고유 번호 지정. PK 지정(필수). 시퀀스 지정(선택).
  ,name NVARCHAR2(20) --한글 입력 가능. 20자 이내
  ,phone VARCHAR2(20) --20자 이내.
);


--제약 조건 추가
ALTER TABLE 테이블이름
 ADD CONSTRAINT 제약이름 제약종류(제약대상);
ALTER TABLE 테이블이름
 DROP CONSTRAINT 제약이름;

--mid 컬럼에 PK 제약 지정
ALTER TABLE memberList
  ADD CONSTRAINT memberList_mid_pk PRIMARY KEY(mid);


--시퀀스 객체 사용시
CREATE SEQUENCE memberListSeq;


--입력 쿼리를 이용한 샘플 데이터 입력.
INSERT INTO memberList (mid, name, phone)
  VALUES (memberListSeq.nextval, 'hong', '010-123-1234');
INSERT INTO memberList (mid, name, phone)
  VALUES (memberListSeq.nextval, 'park', '010-234-2345');
COMMIT;


--권장하지 않는 표현. 컬럼 리스트에서 * 사용하지 않는다.
SELECT * FROM memberList;

--전체 명단 출력 쿼리 (프로그램에서 사용 예정)
--권장하는 표현
SELECT mid, name, phone FROM memberList  ORDER BY mid;

--인원수 출력 쿼리 (프로그램에서 사용 예정)
--함수 사용시 반드시 별칭 사용.
SELECT COUNT(*) AS "count" FROM memberList;

 

 

 

4. 프로그램 준비
//Member.java -> 자료형 클래스
//MemberDAO.java -> 데이터베이스 액션 처리. 메소드 단위로 액션 처리.
//JDBC05.java -> main() 메소드. 화면 구성. 콘솔 액션.


5. 소스 코드

//Member.java
package com.test;

//자료형 클래스
public class Member {

 //멤버변수, getter, setter 등록
 
 //멤버변수
 //입력, 출력에 관련된 모든 항목
 //->번호, 이름, 전화번호

 //동일 자료, 동일 변수 사용할 것.
 //-> 데이터베이스 테이블에서 사용한 컬럼명을 변수명으로 사용.
 //-> 특별한 자료형을 사용하지 않는 경우 외에는 모두 String으로 처리.
 private String mid, name, phone;

 public String getMid() {
  return mid;
 }

 public void setMid(String mid) {
  this.mid = mid;
 }

 public String getName() {
  return name;
 }

 public void setName(String name) {
  this.name = name;
 }

 public String getPhone() {
  return phone;
 }

 public void setPhone(String phone) {
  this.phone = phone;
 }

}

 

 

 

//MemberDAO.java
package com.test;

//1. 패키지 등록
import java.util.*;
import java.sql.*;

//데이터베이스 액션 클래스
//-> 메소드 단위로 작성
//-> 콘솔 관련 액션 코드 작성 X
public class MemberDAO {
 
 //샘플 쿼리 종류만큼 메소드 작성.
 //1. INSERT INTO memberList (mid, name, phone) VALUES (memberListSeq.nextval, 'hong', '010-123-1234');
 //2. SELECT mid, name, phone FROM memberList  ORDER BY mid;
 //3. SELECT COUNT(*) AS "count" FROM memberList;
 //-> 메소드 작성시 데이터베이스 연결 액션은 각각 별도 진행.
 //-> 메소드 작성시 반환자료형, 매개변수 구성 확인
 
 //출력 관련 메소드 -> 인원수 반환
 //->반환자료형 int 사용
 public int count() {
  int result = 0;
  
  Connection conn = null;
  Statement stmt = null;
  try {
   //2. JDBC 드라이버 등록
   Class.forName("oracle.jdbc.driver.OracleDriver");
   
   //3. 커넥션 객체 준비
   conn = DriverManager.getConnection("jdbc:oracle:thin:username/password@IP주소:1521:xe");
      
   //4. 출력 쿼리 준비 및 실행
   stmt = conn.createStatement();
   //주의. 문장 끝에 ;(semicolon) 없다.
   String sql = String.format("SELECT COUNT(*) AS \"count\" FROM memberList");
   //executeQuery() 메소드는 SELECT 쿼리 전용
   ResultSet rs = stmt.executeQuery(sql);
   while(rs.next()) {
    result = rs.getInt("count");
   }
   rs.close();
   
  }catch(Exception e){
   e.printStackTrace();
  }finally{
   //5. 마무리
   try {
    if (stmt != null) {
     stmt.close();
    }
   }catch(Exception e){
   }
   try {
    if (conn != null) {
     conn.close();
    }
   }catch(Exception e){
   }
  }
  
  return result;
 }
 
 //출력 관련 메소드 -> 명단 반환
 //데이터베이스에서 읽어온 자료 전체를 하나의 자료형으로 반환
 //->반환자료형 컬렉션 자료형(ArrayList<Member>) 사용
 public ArrayList<Member> list() {
  ArrayList<Member> result = new ArrayList<Member>();
  
  Connection conn = null;
  Statement stmt = null;
  try {
   //2. JDBC 드라이버 등록
   Class.forName("oracle.jdbc.driver.OracleDriver");
   
   //3. 커넥션 객체 준비
   conn = DriverManager.getConnection("jdbc:oracle:thin:username/password@IP주소:1521:xe");
      
   //문제) 명단 출력 관련 쿼리 액션
   stmt = conn.createStatement();
   String sql = "SELECT mid, name, phone FROM memberList ORDER BY mid";
   ResultSet rs = stmt.executeQuery(sql);
   while(rs.next()) {
    
    String mid = rs.getString("mid");
    //int mid = rs.getInt("mid");
    String name = rs.getString("name");
    String phone = rs.getString("phone");
    
    Member member = new Member();
    member.setMid(mid);
    member.setName(name);
    member.setPhone(phone);
    
    result.add(member);
    
   }
   rs.close();
   
   
  }catch(Exception e){
   e.printStackTrace();
  }finally{
   try {
    if (stmt != null) {
     stmt.close();
    }
   }catch(Exception e){
   }
   try {
    if (conn != null) {
     conn.close();
    }
   }catch(Exception e){
   }
  }
  
  return result;
 }
 
 //입력 관련 메소드
 //-> 반환 자료형 int 사용
 //-> 입력 실패시 예외 발생
 //-> 입력 데이터는 매개변수를 통해서 전달 받는다.
 public int add(Member member) {
  int result = 0;

  Connection conn = null;
  Statement stmt = null;
  try {
   //2. JDBC 드라이버 등록
   Class.forName("oracle.jdbc.driver.OracleDriver");
   
   //3. 커넥션 객체 준비
   conn = DriverManager.getConnection("jdbc:oracle:thin:username/password@IP주소:1521:xe");
   
   
   //문제) 입력 관련 쿼리 액션
   stmt = conn.createStatement();
   String sql = String.format("INSERT INTO memberList (mid, name, phone) VALUES (memberListSeq.nextval, '%s', '%s')"
     , member.getName(), member.getPhone());
   
   result = stmt.executeUpdate(sql);
   
  }catch(Exception e){
   e.printStackTrace();
  }finally{
   try {
    if (stmt != null) {
     stmt.close();
    }
   }catch(Exception e){
   }
   try {
    if (conn != null) {
     conn.close();
    }
   }catch(Exception e){
   }
  }
  
  return result;
 }


}

 

 

 


//JDBC05.java
package com.test;

import java.util.*;

//콘솔 액션 클래스
public class JDBC05 {

 public static void main(String[] args) {
  
  //MemberDAO 객체를 위한 지역변수 선언
  MemberDAO dao = new MemberDAO();
  
  //입력 과정
  Scanner sc = new Scanner(System.in);
  
  //문제) 입력 관련 콘솔 액션 부분 작성
  do {
   
   System.out.print("이름 전화번호(x exit)?");
   String name = sc.next();
   if (name.equalsIgnoreCase("x")) {
    break;
   }
   String phone = sc.next(); 
   
   Member member = new Member();
   member.setName(name);
   member.setPhone(phone);

   int result = dao.add(member);
   //System.out.printf("1개 행이 삽입되었습니다.%n");
   System.out.printf("%d개 행이 삽입되었습니다.%n", result);
   
  }while(true);
  sc.close();
  
  
  //출력 과정
  //저장소로부터 회원 정보 전체를 반환하는 메소드 호출
  //-> list()->ArrayList<Member>
  //-> 컬렉션에 들어있는 회원 정보(Member 자료형)를 순차적으로 출력
  //-> 향상된 for문 이용 
  
  System.out.printf("전체 인원수 : %s명 %n", dao.count());
  
  for (Member m : dao.list()) {
   System.out.printf("%s %s %s %n"
     , m.getMid()
     , m.getName()
     , m.getPhone());
  }

 }

}

 

 

 

----------------------------------------------
콘솔, 데이터베이스 액션이 클래스별로 분리가 되었다.

데이터베이스 액션 처리 클래스 내부에서 보면, 데이터베이스 연결 및 연결 종료 과정에 대해서 중복(반복)된 코드가 존재한다.
-> 데이터베이스 연결 및 연결 종료 과정을 별도의 클래스(메소드)로 분리할 필요가 있다.

입력 쿼리에서 외부 데이터를 바인딩할 때 String.format() 메소드, %s 문자열보다는 PrepareStatement 객체를 이용한 바인딩 방법을 권장한다.
-> Statement 객체를 PrepareStatment 객체로 변경. 바인딩 문자열 ? 로 변경

 


//DBConn.java
package com.test;

import java.sql.*;

//데이터베이스 연결 액션 클래스
public class DBConn {
 
 //메소드들 내부에서 공통 사용하는 멤버는
 //멤버변수로 등록한다.
 //static 키워드 추가
 private static Connection conn;
 
 //커넥션 객체 준비 메소드
 //-> Singleton
 public static Connection getConnection() throws ClassNotFoundException, SQLException  {
  if (conn == null) {

   Class.forName("oracle.jdbc.driver.OracleDriver");
   conn = DriverManager.getConnection("jdbc:oracle:thin:username/password@IP주소:1521:xe");;

  }
  return conn;
 }
 
 //마무리 메소드
 public static void close() {
  try {
   if (conn != null) {
    conn.close();
   }
  }catch(Exception e){
  }
  conn = null;
 }

}

 

 

//MemberDAO.java -> DBConn 클래스 사용 버전
package com.test;

//1. 패키지 등록
import java.util.*;
import java.sql.*;

//데이터베이스 액션 클래스
//-> 메소드 단위로 작성
//-> 콘솔 관련 액션 코드 작성 X
public class MemberDAO {
 
 //샘플 쿼리 종류만큼 메소드 작성.
 //1. INSERT INTO memberList (mid, name, phone) VALUES (memberListSeq.nextval, 'hong', '010-123-1234');
 //2. SELECT mid, name, phone FROM memberList  ORDER BY mid;
 //3. SELECT COUNT(*) AS "count" FROM memberList;
 //-> 메소드 작성시 데이터베이스 연결 액션은 각각 별도 진행.
 //-> 메소드 작성시 반환자료형, 매개변수 구성 확인
 
 //출력 관련 메소드 -> 인원수 반환
 //->반환자료형 int 사용
 public int count() {
  int result = 0;
  
  Connection conn = null;
  Statement stmt = null;
  try {
   
   conn = DBConn.getConnection();
   
   //4. 출력 쿼리 준비 및 실행
   stmt = conn.createStatement();
   //주의. 문장 끝에 ;(semicolon) 없다.
   String sql = String.format("SELECT COUNT(*) AS \"count\" FROM memberList");
   //executeQuery() 메소드는 SELECT 쿼리 전용
   ResultSet rs = stmt.executeQuery(sql);
   while(rs.next()) {
    result = rs.getInt("count");
   }
   rs.close();
   
  }catch(Exception e){
   e.printStackTrace();
  }finally{
   //5. 마무리
   try {
    if (stmt != null) {
     stmt.close();
    }
   }catch(Exception e){
   }
   
   DBConn.close();
   
  }
  
  return result;
 }
 
 //출력 관련 메소드 -> 명단 반환
 //데이터베이스에서 읽어온 자료 전체를 하나의 자료형으로 반환
 //->반환자료형 컬렉션 자료형(ArrayList<Member>) 사용
 public ArrayList<Member> list() {
  ArrayList<Member> result = new ArrayList<Member>();
  
  Connection conn = null;
  Statement stmt = null;
  try {

   conn = DBConn.getConnection();
   
   //문제) 명단 출력 관련 쿼리 액션
   stmt = conn.createStatement();
   String sql = "SELECT mid, name, phone FROM memberList ORDER BY mid";
   ResultSet rs = stmt.executeQuery(sql);
   while(rs.next()) {
    
    String mid = rs.getString("mid");
    //int mid = rs.getInt("mid");
    String name = rs.getString("name");
    String phone = rs.getString("phone");
    
    Member member = new Member();
    member.setMid(mid);
    member.setName(name);
    member.setPhone(phone);
    
    result.add(member);
    
   }
   rs.close();
   
   
  }catch(Exception e){
   e.printStackTrace();
  }finally{
   try {
    if (stmt != null) {
     stmt.close();
    }
   }catch(Exception e){
   }
   
   DBConn.close();
   
  }
  
  return result;
 }
 
 //입력 관련 메소드
 //-> 반환 자료형 int 사용
 //-> 입력 실패시 예외 발생
 //-> 입력 데이터는 매개변수를 통해서 전달 받는다.
 public int add(Member member) {
  int result = 0;

  Connection conn = null;
  Statement stmt = null;
  try {

   conn = DBConn.getConnection();
   
   //문제) 입력 관련 쿼리 액션
   stmt = conn.createStatement();
   String sql = String.format("INSERT INTO memberList (mid, name, phone) VALUES (memberListSeq.nextval, '%s', '%s')"
     , member.getName(), member.getPhone());
   
   result = stmt.executeUpdate(sql);
   
  }catch(Exception e){
   e.printStackTrace();
  }finally{
   try {
    if (stmt != null) {
     stmt.close();
    }
   }catch(Exception e){
   }
   
   DBConn.close();
   
  }
  
  return result;
 }


}

 

 

 

---------------------------
Statement 객체 종류별 액션 처리(Statement)

1. Creating Statement Object

Statement stmt = conn.createStatement();

2. execute methods

- boolean execute(String SQL) : Returns a boolean value of true if a ResultSet object can be retrieved; otherwise, it returns false. Use this method to execute SQL DDL statements or when you need to use truly dynamic SQL.

- int executeUpdate(String SQL) : Returns the numbers of rows affected by the execution of the SQL statement. Use this method to execute SQL statements for which you expect to get a number of rows affected - for example, an INSERT, UPDATE, or DELETE statement.

- ResultSet executeQuery(String SQL) : Returns a ResultSet object. Use this method when you expect to get a result set, as you would with a SELECT statement.

3.Closing Statement Obeject

stmt.close();


-------------------------------------------
Employees 테이블의 자료 삭제 과정

DELETE FROM employees WHERE id=100;

SELECT * FROM employees;

ROLLBACK;
--COMMIT;


-----------------------------------------
Employees 테이블의 자료 삭제 과정(Statement 객체 이용)

//Sample06.java
package com.test;

import java.sql.*;
import java.util.*;

public class Sample06 {

 public static void main(String[] args) {
  
  Scanner sc = new Scanner(System.in);
  
  Connection conn = null;
  Statement stmt = null;
  try {
   
   //id 기준 삭제 데이터 입력 추가
   System.out.print("id(x exit)?");
   String id = sc.next();
   if (id.equalsIgnoreCase("x")) {
    return;
   }
   
   Class.forName("oracle.jdbc.driver.OracleDriver");
   
   String url = "jdbc:oracle:thin:아이디/패스워드@211.63.89.XX:1521:xe";
   conn = DriverManager.getConnection(url);
   
   stmt = conn.createStatement();
   String sql = String.format("DELETE FROM employees WHERE id=%s", id);
   int result = stmt.executeUpdate(sql);
   //auto COMMIT
   System.out.printf("%d개의 행이 삭제되었습니다. %n", result);
   
  }catch(Exception e){
   e.printStackTrace();
  }finally{
   try {
    if (stmt != null) {
     stmt.close();
    }
    if (conn != null) {
     conn.close();
    }
   }catch(Exception e){
    e.printStackTrace();
   }
  }

  sc.close();

 }

}

 


---------------------------
Statement 객체 종류별 액션 처리(PreparedStatement)

1. Creating PreparedStatement Object

String sql = "쿼리(데이터 바인딩 과정 필요-> ? 서식)";
PreparedStatement pstmt = conn.prepareStatement(sql);


2. 데이터 바인딩

pstmt.setXXX(인덱스, 값); //인덱스는 1부터 출발.


예를 들어,
String sql = "DELETE FROM employees WHERE id=?";
PreparedStatement pstmt = conn.prepareStatement(sql);
pstmt.setInt(1, id);


3. execute methods

- boolean execute() : Returns a boolean value of true if a ResultSet object can be retrieved; otherwise, it returns false. Use this method to execute SQL DDL statements or when you need to use truly dynamic SQL.

- int executeUpdate() : Returns the numbers of rows affected by the execution of the SQL statement. Use this method to execute SQL statements for which you expect to get a number of rows affected - for example, an INSERT, UPDATE, or DELETE statement.

- ResultSet executeQuery() : Returns a ResultSet object. Use this method when you expect to get a result set, as you would with a SELECT statement.

4. Closing PreparedStatement Obeject

pstmt.close();


-----------------------------------------
Employees 테이블의 자료 삭제 과정(PreparedStatement 객체 이용)

//JDBC06.java
package com.test;

import java.sql.*;

public class JDBC06 {

 public static void main(String[] args) {

  Connection conn = null;
  //Statement stmt = null;
  PreparedStatement pstmt = null;
  try {
   
   conn = DBConn.getConnection();
   
   String id = "104";
   String age = "20";
   String first = "Steven";
   String last = "King";
   
   //String sql1 = String.format("INSERT INTO employees (id, age, first, last) VALUES (%s, %s, '%s', '%s')", id, age, first, last);
   String sql2 = String.format("INSERT INTO employees (id, age, first, last) VALUES (?, ?, ?, ?)");
   //stmt = conn.createStatement();
   pstmt = conn.prepareStatement(sql2); //쿼리를 사전 분석한다.
   
   //int result = stmt.executeUpdate(sql1); //쿼리를 실행시 분석한다.
   pstmt.setInt(1, Integer.parseInt(id));
   pstmt.setInt(2, Integer.parseInt(age));
   pstmt.setString(3, first); //'(작은 따옴표) 추가
   pstmt.setString(4, last); //'(작은 따옴표) 추가
   int result = pstmt.executeUpdate();
   
   System.out.printf("%d개의 행이 삽입되었습니다.", result);
   
  }catch(Exception e){
   e.printStackTrace();
  }finally{
   try {
    /*
    if (stmt != null) {
     stmt.close();
    }
    */
    if (pstmt != null) {
     pstmt.close();
    }
   }catch(Exception e){
   }
   
   DBConn.close();
  }
  
  
 }

}

 


//JDBC07.java
package com.test;

import java.sql.*;

public class JDBC07 {

 public static void main(String[] args) {
  
  Connection conn = null;
  //Statement stmt = null;
  PreparedStatement pstmt = null;
  try {
   
   conn = DBConn.getConnection();
   
   String id = "104";
   
   //String sql1 = String.format("DELETE FROM employees WHERE id=%s", id);
   String sql2 = String.format("DELETE FROM employees WHERE id=?");
   //stmt = conn.createStatement();
   pstmt = conn.prepareStatement(sql2); //쿼리를 사전 분석한다.
   
   //int result = stmt.executeUpdate(sql1); //쿼리를 실행시 분석한다.
   pstmt.setInt(1, Integer.parseInt(id)); //바인딩 문자열 ? 와 데이터를 바인딩하는 과정
   int result = pstmt.executeUpdate();
   
   System.out.printf("%d개의 행이 삭제되었습니다.", result);
   
  }catch(Exception e){
   e.printStackTrace();
  }finally{
   try {
    /*
    if (stmt != null) {
     stmt.close();
    }
    */
    if (pstmt != null) {
     pstmt.close();
    }
   }catch(Exception e){
   }
   
   DBConn.close();
  }  
  

 }

}

 

 

--------------------------------
저장 프로시저 생성

CREATE OR REPLACE PROCEDURE 프로시저명
(
  매개변수 자료형,
  매개변수 자료형,
  ...
)
IS
  내부변수 자료형;
  ...
BEGIN
  PL/SQL 구문;
END;

EXECUTE 프로시저명(값, ....);

 

--employees 테이블 자료 삭제용 프로시저 작성
CREATE OR REPLACE PROCEDURE empDelete
(
 vid NUMBER
)
IS
BEGIN
 DELETE FROM employees WHERE id=vid;
 COMMIT;
END;

EXECUTE empDelete(100);
EXECUTE empDelete(101);

SELECT * FROM employees;

 


---------------------------
Statement 객체 종류별 액션 처리(CallableStatement)


1.Creating CallableStatement Object

String sql = "{call 프로시저명(바인딩 문자열 ?)}";
CallableStatement  cstmt = conn.prepareCall(sql);

2. 데이터 바인딩

cstmt.setXXX(인덱스, 값); //인덱스는 1부터 출발

3. execute methods

- boolean execute() : Returns a boolean value of true if a ResultSet object can be retrieved; otherwise, it returns false. Use this method to execute SQL DDL statements or when you need to use truly dynamic SQL.


4. Closing CallableStatement  Obeject

cstmt.close();

-----------------------------------------
Employees 테이블의 자료 삭제 과정(CallableStatement 객체 이용)

//Sample08.java
package com.test;

import java.sql.*;
import java.util.*;

public class Sample08 {

 public static void main(String[] args) {
  
  Scanner sc = new Scanner(System.in);
  
  Connection conn = null;
  CallableStatement cstmt = null;
  try {
   
   //id 기준 삭제 데이터 입력 추가
   System.out.print("id(x exit)?");
   String id = sc.next();
   if (id.equalsIgnoreCase("x")) {
    return;
   }
   
   Class.forName("oracle.jdbc.driver.OracleDriver");
   
   String url = "jdbc:oracle:thin:아이디/패스워드@211.63.89.XX:1521:xe";
   conn = DriverManager.getConnection(url);
   
   String sql = "{call empDelete(?)}";
   cstmt = conn.prepareCall(sql);
   cstmt.setInt(1, Integer.parseInt(id));

   //true -> SELECT 쿼리 실행시
   //false -> INSERT, UPDATE, DELETE 쿼리 실행시
   boolean result = cstmt.execute();
   if (!result) {
    System.out.println("empDelete 프로시저 실행 완료!");
   }    

  }catch(Exception e){
   e.printStackTrace();
  }finally{
   try {
    if (cstmt != null) {
     cstmt.close();
    }
    if (conn != null) {
     conn.close();
    }
   }catch(Exception e){
    e.printStackTrace();
   }
  }
  
  sc.close();

 }

}


--------------------------------------------------------------


 

 

'JDBC' 카테고리의 다른 글

6일차_성적관리_최종버전  (0) 2015.06.21
5일차_성적관리  (0) 2015.06.21
4일차_성적관리  (0) 2015.06.21
2일차_JDBC Connection 방법, 회원관리 JDBC 프로그램1  (0) 2015.06.21
1일차_JDBC 환경설정, Sample Code  (0) 2015.06.21
블로그 이미지

알 수 없는 사용자

,