1) View - MemberMenu
: 같은 경우 완성된 sql문을 바로 실행하는 객체
(sql문이 완성된 형태로 세팅되어있어야 함 == 사용자가 입력했던 값들이 다 채워진 채로)
Connection 객체를 가지고 Statement 객체 생성
: stmt = conn.createStatement();
executeXXXX 메소드를 이용해서 sql문을 전달하면서 실행 : stmt.executeXXX(sql);
: 같은 경우 sql문을 바로 실행하지 않고 잠시 보관을 해 둘 수 있음
( == 미완성된 sql문을 잠시 보관해둘수 있음!)
단, 사용자가 입력한 값들이 들어갈 수 있는 공간을 확보(? == 폴더)만 해줘도 됨!
해당 sql문을 실행하기 전에 완성형태로 만든 후 실행만 하면 됨!
Connection 객체를 가지고 PreparedStatement 객체 생성(단, sql문을 담은 채로 생성)
: pstmt = conn.prepareStatement(sql);
현재 담긴 sql문이 미완성된 sql문일 경우 빈 공간들을 실제 값으로 채워주는 과정
: pstmt.setString(1, "실제값"); or pstmt.setInt(2, 실제 값);
executeXXXX 메소드를 이용해서 실행만 하면 됨 : 결과 = pstmt.executeXXX();
<예시>
<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문의 형태를 볼 수 없다.
: Dao 의 역할이 너무 많기때문에 업무분배!
: JDBC 과정 중 반복적으로 쓰이는 구문들을 각각의 메소드로 정의해둘 것
재사용할 목적으로 공통 템플릿 작업진행!
Connection , Statement, Resultset, 트랜잭션 처리를 해주는 class
이 클래스에서의 모든 메소드들 다 static 메소드(메모리 영역에 올려두고 공유하는 개념)
싱글톤 패턴 : 메모리 영역에 단 한번만 올라간 것을 재사용하는 개념
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;
}
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();
}
}
<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();
}
}