2/23(화) JDBC(3)/Service(1)

민국·2021년 2월 23일
0

6. 회원탈퇴 JDBC

1) View - MemberMenu

Prepared Statement

Statement(부모) 와 PreparedStatement(자식)의 차이점

(1) Statement

: 같은 경우 완성된 sql문을 바로 실행하는 객체
(sql문이 완성된 형태로 세팅되어있어야 함 == 사용자가 입력했던 값들이 다 채워진 채로)

Connection 객체를 가지고 Statement 객체 생성
: stmt = conn.createStatement();
executeXXXX 메소드를 이용해서 sql문을 전달하면서 실행 : stmt.executeXXX(sql);

(2) PreparedStatement

: 같은 경우 sql문을 바로 실행하지 않고 잠시 보관을 해 둘 수 있음
( == 미완성된 sql문을 잠시 보관해둘수 있음!)

단, 사용자가 입력한 값들이 들어갈 수 있는 공간을 확보(? == 폴더)만 해줘도 됨!
해당 sql문을 실행하기 전에 완성형태로 만든 후 실행만 하면 됨!

Connection 객체를 가지고 PreparedStatement 객체 생성(단, sql문을 담은 채로 생성)
: pstmt = conn.prepareStatement(sql);
현재 담긴 sql문이 미완성된 sql문일 경우 빈 공간들을 실제 값으로 채워주는 과정
: pstmt.setString(1, "실제값"); or pstmt.setInt(2, 실제 값);
executeXXXX 메소드를 이용해서 실행만 하면 됨 : 결과 = pstmt.executeXXX();

  • JDBC 처리 순서
    1) jdbc driver 등록 : 해당 DBMS가 제공하는 클래스 등록
    2) Connection 생성 : 접속하고자 하는 DB정보를 입력해서 DB에 접속하면서 생성
    3_1) PrepareStatement 생성 : Connection 객체를 이용해서 생성(애초에 sql문을 담은채로 생성)
    [3_2) 미완성된 sql문을 완성형태로 채우는 과정]

    4,5) pstmt.executeXXX(); => 매개변수 sql 넣어주면 안됨!!!
    이 후 순서 동일.
<예시>
<Stmt 방식>
int result = 0;			// 처리된 결과(처리된 행수)를 담아줄 변수
Connection conn = null; // 접속된 DB의 연결정보를 담는 변수
Statement stmt = null;	// sql문 실행 후 결과를 받기 위한 변수
		
// 실행할 sql문(완성형태로 만들어둘것!!) => 끝에 세미콜론 있으면 안됨!!
// INSERT INTO MEMBER VALUES(SEQ_USERNO.NEXTVAL, 
			    'XXX', 'XXXX', 'XXX', 'X', XX, 'XXXX', 'XXXX', 'XXXX', 'XXXX', SYSDATE)

String sql = "INSERT INTO MEMBER VALUES(SEQ_USERNO.NEXTVAL, "
				   	+ "'" + m.getUserId() 	+ "', "
				   	+ "'" + m.getUserPwd() 	+ "', "
				   	+ "'" + m.getUserName() + "', "
				   	+ "'" + m.getGender() 	+ "', "
				   	+ "'" + m.getAge()	+  ", "
				   	+ "'" + m.getEmail()	+ "', "
				   	+ "'" + m.getPhone()	+ "', "
				   	+ "'" + m.getAddress() 	+ "', "
				   	+ "'" + m.getHobby()	+ "', SYSDATE)";
                    
 try {
// 1) jdbc driver 등록
Class.forName("oracle.jdbc.driver.OracleDriver"); 
			
// 2) Connection 객체 생성 (DB와 연결 --> url, 계정명, 비밀번호)
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "JDBC", "JDBC");
			
// 3) Statement 객체 생성
stmt = conn.createStatement();
			
// 4, 5) DB에 완성된 sql문 전달하면서 실행 후 결과(처리된행수) 받기
result = stmt.executeUpdate(sql);


<Pstmt 방식>
int result = 0;		// 처리된 결과(처리된 행수)를 담아줄 변수
Connection conn = null; // 접속된 DB의 연결정보를 담는 변수
Statement stmt = null;	// sql문 실행 후 결과를 받기 위한 변수
		
// 실행할 sql문(완성형태로 만들어둘것!!) => 끝에 세미콜론 있으면 안됨!!
// INSERT INTO MEMBER VALUES(SEQ_USERNO.NEXTVAL, 
			   'XXX', 'XXXX', 'XXX', 'X', XX, 'XXXX', 'XXXX', 'XXXX', 'XXXX', SYSDATE)
String sql = "INSERT INTO MEMBER VALUES(SEQ_USERNO.NEXTVAL, ?, ?, ?, ?, ?, ?, ?, ?, ?, SYSDATE)";


try {
			```
// 1) jdbc driver 등록
Class.forName("oracle.jdbc.driver.OracleDriver"); 

			
// 2) Connection 객체 생성 (DB와 연결 --> url, 계정명, 비밀번호)
conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "JDBC", "JDBC");
			
// 3_1) Statement 객체 생성
pstmt = conn.prepareStatement(sql);
			
// 3_2) 내가 담은 sql문이 미완성된 sql문일 경우 값 채우기 (pstmt.setXXX(홀더순번, 대체할 값);)
//      pstmt.setString(홀더순번, 대체할 값); 
--> '대체할 값'(양 옆에 홑따옴표 붙어서 들어감-> 즉, 따로 적어줄 필요 없음)
//      pstmt.setInt(홀더순번, 대체할 값); 
--> 대체할 값(양 옆에 홑따옴표 안 들어감)

	pstmt.setString(1, m.getUserId());
	pstmt.setString(2, m.getUserPwd());
	pstmt.setString(3, m.getUserName());
	pstmt.setString(4, m.getGender());
	pstmt.setInt(5, m.getAge());
	pstmt.setString(6, m.getEmail());
	pstmt.setString(7, m.getPhone());
	pstmt.setString(8, m.getAddress());
	pstmt.setString(9, m.getHobby());
    
// 4, 5) DB에 완성된 sql문 전달하면서 실행 후 결과(처리된행수) 받기
result = pstmt.executeUpdate(); 

PreparedStatement의 최대 단점
: 완성된 sql문의 형태를 볼 수 없다.

Service

: Dao 의 역할이 너무 많기때문에 업무분배!

JDBCTemplate class

: JDBC 과정 중 반복적으로 쓰이는 구문들을 각각의 메소드로 정의해둘 것
재사용할 목적으로 공통 템플릿 작업진행!

  • Connection , Statement, Resultset, 트랜잭션 처리를 해주는 class

  • 이 클래스에서의 모든 메소드들 다 static 메소드(메모리 영역에 올려두고 공유하는 개념)

  • 싱글톤 패턴 : 메모리 영역에 단 한번만 올라간 것을 재사용하는 개념

(1) DB와 접속된 Connection 객체 생성해서 반환시켜주는 메소드

public static Connection getConnection() {
		
	Connection conn = null;
		
	try {
		Class.forName("oracle.jdbc.drvier.OracleDriver");
		conn = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "JDBC", "JDBC");	
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return conn;
	}

(2) 전달받은 JDBC용 객체를 반납시켜주는 메소드

finally - conn.close() 또는 stmt.close() 의 정석방식

원래 이 과정이 아니라,

<올바르지 않은 예시>
finally {
		
	pstmt.close();
	conn.close();
}

이 과정임!

<정석>

try {
	if((p)stmt != null && !(p)stmt.isClosed()) {
		(p)stmt.close();
	}
    } catch (SQLException e) {
	e.printStackTrace();
    	}

try {
	if(conn != null && !conn.isClosed()) {
		conn.close();
	}
     } catch (SQLException e) {
		e.printStackTrace();
	}

원래는 이렇게 자원반납 해야하는 거임
왜? 조건 기술해주냐
-> 앞서서 conn 또는 stmt가 작동도중 오류생겨서 catch에 걸릴경우,
conn, stmt 값은 null로 초기화되어버려서
나중에 close되는 저 구문이 제대로 동작하지 않기때문!

<Connection 객체 전달받아서 반납시켜주는 메소드>
	
public static void close(Connection conn) {
	try {
		if(conn != null && !conn.isClosed()) {
			conn.close();
		}
	} catch (SQLException e) {
		e.printStackTrace();
	  }
}
	
<Statement 객체 전달받아서 반납시켜주는 메소드>
public static void close(Statement stmt) {
	try {
		if(stmt != null && !stmt.isClosed()) {
			stmt.close();
		}
	} catch (SQLException e) {
		e.printStackTrace();
	  }
}

<ResultSet 객체 전달 받아서 반납시켜주는 메소드>
public static void close(ResultSet rset) {
	try {
		if(rset != null && !rset.isClosed()) {
			rset.close();
		}
	} catch (SQLException e) {
		e.printStackTrace();
	  }
}

(3) 전달받은 Connection 객체를 가지고 트랜잭션 처리해주는 메소드

<Commit: 전달받은 Connection 객체를 가지고 commit 시켜주는 메소드>
	
	public static void commit(Connection conn) {
		
		try {
			if(conn != null && !conn.isClosed()) {
				conn.commit();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	
<Rollback: 전달받은 Connection 객체를 가지고 rollback 시켜주는 메소드>
	public static void rollback(Connection conn) {
		try {
			if(conn != null && !conn.isClosed()) {
				conn.rollback();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
profile
새싹개발자

0개의 댓글

관련 채용 정보