------------------------------------------------
회원관리 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 |