Q. 저번 시간에는 JDBC에 대하여 배워보았다. 기억이 잘 나지 않는다. 리마인드 시켜달라.
JDBC는 DB에 있는 데이터를 JAVA를 거쳐 JSP까지 가져오기 위한 프로그래밍이다. JDBC을 사용하는
일반적인 순서는 다음과 같다.
일반적인 순서는 다음과 같다.
연결 - 명령어 전송 - 결과 전송 - 연결 종료.
각 과정에서의 키워드를 뽑아보겠다.
연결 - (1) 드라이버로드 (2)Connection 객체
명령어 전송 - (1)Statement (2)Preparement
결과 전송 - (1)ResultSet (2) Int
연결종료 - Close 메서드
JDBC의 주요 강점은 데이터베이스 종류에 영향을 받지 않는다는 것이다. 어떤 종류의 데이터베이스던지
공통의 API를 사용한다.
공통의 API를 사용한다.
그러나 여기서 주의해야 할 점은 jar 형태로 제공되는 JDBC 드라이버는 각 DBMS에 알맞은 클라이언트를
사용해야 한다는 것이다. 코드를 보면 Class.forName(“ “) 안에 어떠한 라이브러리를 사용할 것인가 선언(로딩)하는
부분이 있지 않은가. 이때, MySQL, 오라클, MS SQL 등 어떤 DBMS를 사용할 건 가에 따라 이 부분을 달리해야 한다.
사용해야 한다는 것이다. 코드를 보면 Class.forName(“ “) 안에 어떠한 라이브러리를 사용할 것인가 선언(로딩)하는
부분이 있지 않은가. 이때, MySQL, 오라클, MS SQL 등 어떤 DBMS를 사용할 건 가에 따라 이 부분을 달리해야 한다.
Q. 구체적으로 코드를 사용하여 설명해 줄 수 있겠는가?
알겠다. 여전히 싸갈쓰가 바갈쓰다.
// 1. JDBC 드라이버 로딩
Class.forName("com.mysql.jdbc.Driver"*); // mysql
// oracle.jdbc.driver.OracleDriver
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try {
// 2. 데이터베이스 커넥션 생성
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/chap12*", "user", "pass");
// 3. Statement 생성
stmt = conn.createStatement();
// 4. 쿼리 실행
rs = stmt.executeQuery("select * from MEMBER order by MEMBERID")*;
// 5. 쿼리 실행 결과 출력
while(rs.next())* {
String name = rs.getString(1);
}
} catch(SQLException ex) {
ex.printStackTrace();
} finally* {
// 6. 사용한 Statement 종료
if (rs != null) try { rs.close(); } catch(SQLException ex) {}
if (stmt != null) try { stmt.close(); } catch(SQLException ex) {}
// 7. 커넥션 종료
if (conn != null) try { conn.close(); } catch(SQLException ex) {}
}
* 클라이언트의 종류에 따른 JDBC 드라이버는 다음과 같다.
• MySQL - com.mysql.jdbc.Driver
• 오라클 - oracle.jdbc.driver.OracleDriver
• MS SQL 서버 - com.microsoft.sqlserver.jdbc.SQLServerDriver
*JDBC URL 구성은 다음과 같다.
– MySQL : jdbc:mysql://HOST[:PORT]/DBNAME[?param=value&par am1=value2&...]
– Oracle: jdbc:oracle:thin:@HOST:PORT:SID
– MS SQL : jdbc:sqlserver://HOST[:PORT];databaseName=DB
*때에 따라서는
String jdbcDriver = "jdbc:mysql://localhost:3306*/chap11?" + "useUnicode=true&characterEncoding=utf-8"
이런 식으로 고대 문자들의 모음 처럼 있는 경우도 있다. 첫 번째 부분은 본인이 저번 시간에 주석처리로
설명했다. 두 번째 부분은 버전(Version)을 명시하는 것이다.
설명했다. 두 번째 부분은 버전(Version)을 명시하는 것이다.
*Oracle 1521, MySQL 3306, FTP 21, HTTP 80, Tomcate 8080 이 포트번호들은 외워두는 것이 좋다.
포트 번호 변경 사용 가능하다.
포트 번호 변경 사용 가능하다.
*finally는 무조건 실행해야 하는 부분을 감싸 주는 것이다. Must do it part.
*너무 중요해서, 다시한번 리마인드 시켜준다. 💀💀💀
Statement가 제공하는 메서드로 쿼리 실행
– ResultSet executeQuery(String query) : SELECT 쿼리를 실행
– int executeUpdate(String query) : INSERT, UPDATE, DELETE 쿼리 를 실행
Statement stmt = null;
ResultSet rs = null;
try {
stmt = conn.createStatement();
int insertedCount = stmt.executeUpdate("insert …..");
rs = stmt.executeQuery("select * from ….");
…
} catch(SQLException ex) {
… } finally {
if (rs != null) try { rs.close(); } catch(SQLException ex) {}
if (stmt != null) try { stmt.close(); } catch(SQLException ex) {}
}
* While(rs.next()) 원리를 설명하기 위해, 그림을 불펌했다.
화살표를 잘 보아라.
While(rs.next())는 ‘나 지금 행 읽는 거 끝나고 다음 행 읽는 거 반복 할 건데, 다음에 읽을 꺼 있어?’라고
확인하고 반복하는 부분이다.
확인하고 반복하는 부분이다.
혹시나 해서 말하는 것인데, 아시다 시피 행이 하나 일 경우에는
while(rs.next()) 대신에 if(rs.next()) 를 통해서 처리한다.
Q. 궁금한 부분이 생겼다. JDBC는 주로 java 파일에서 처리했다. 그러나 내가 DB에서 받은 값을 웹
상에서 출력하고 싶으면 어떻게 해야 하는가?
상에서 출력하고 싶으면 어떻게 해야 하는가?
JSP 파일을 이용하면 된다. 커넥션을 받고 값을 받고 이것을 출력하기 까지를 <%%>로 처리하면 된다.
다만, 주의해야 할 부분은 읽어오는 문법은 다음과 같다.
// 4. 쿼리 실행
rs = stmt.executeQuery(query);
// 5. 쿼리 실행 결과 출력
while(rs.next()) { %>
<%= rs.getString("ENAME") %>
<%= rs.getString("EMPNO") %>
<%= rs.getString("JOB") %>
<% }
} catch(SQLException ex) {
out.println(ex.getMessage());
ex.printStackTrace();
}
Q. 오늘은 어떤 새로운 내용을 신나고 재미나게 배울 것인가?
오늘의 새로운 내용은 앞서 말했던 JDBC 내용과 연결된다. 이번에는 JDBC 드라이버를 선언하는 또
다른 방법을 알아 보도록 하겠다.
다른 방법을 알아 보도록 하겠다.
JDBC에서 앞 부분에 드라이버를 선언해 주지 않는가. 앞서 말했듯, DBMS의 종류에 따라 선언 내용이
달라지며, 이 부분이 라이브러리에 서 파일을 불러와 DB 연결/사용하겠다고 알리는 부분이다.
달라지며, 이 부분이 라이브러리에 서 파일을 불러와 DB 연결/사용하겠다고 알리는 부분이다.
그런데, 여기서 참고해야 할 것은, Web.xml 파일에 JDBC 드라이버를 먼저 선언해 두고, 우리가
getInitParameter(“”) 메서드로 불러올 수 있다는 것이다.
getInitParameter(“”) 메서드로 불러올 수 있다는 것이다.
이 방법을 이용할 때 염두해 두어야 하는 점은 web.xml에 추가한 후 서버를 종료했다가 재시작 해야한다.
예시를 보여주도록 하겠다.
[src/Jdbc/Loader.java ]
package Jdbc;
import javax.servlet.http.HttpServlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import java.util.StringTokenizer;
public class Loader extends HttpServlet {
public void init(ServletConfig config) throws ServletException {
try {
String drivers = config.getInitParameter("jdbcdriver");
StringTokenizer st = new StringTokenizer(drivers, ",");
while (st.hasMoreTokens())* {
String jdbcDriver = st.nextToken();
Class.forName(jdbcDriver);
}
} catch(Exception ex) {
throw new ServletException(ex);
}
}
}
[web.xml ]
<servlet>
<servlet-name>JDBCDriverLoader</servlet-name>
<servlet-class>Jdbc.Loader</servlet-class>
<init-param>
<param-name>jdbcdriver</param-name>
<param-value>oracle.jdbc.driver.OracleDriver</param-value>*
</init-param>
<load-on-startup>1</load-on-startup>*
</servlet>
*여기서 가장 핵심은 config.getInitParameter(“”) 메서드 이다.
*StringTokenizer를 이용해서 “,”를 기준으로 jdbcdriver를 잘라 사용한다.
이는 <param-value>에 여러 개의 드라이버가 있을 경우를 대비하는 것이다.
예를 들어,
<param-value>oracle.jdbc.driver.OracleDriver, MysqlDriver </param-value>
이렇게 있다면, (1) oracle.jdbc.driver.OracleDriver (2) MysqlDriver 이렇게 잘라서, (1)을 먼저 실행하고,
그 후에 (2)를 실행한다.
그 후에 (2)를 실행한다.
StringTokenizer 부분은 생략 가능하다. 생략한 코드는 다음과 같다.
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
public class Loader extends HttpServlet {
public void init(ServletConfig config) throws ServletException {
String drivers = config.getInitParameter("jdbcdriver");
try {
Class.forName(drivers);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
*<load-on-startup>1</load-on-startup>은 실행 횟수이다.
Q. 별로 재미가 없다. 새로운 또 다른 것을 가르쳐 달라.
그럼 이번에는 커밋(Commit)과 롤백(Rollback)에 대해 알아보도록 하겠다.
커밋을 해야하는 시간은, 하나의 트랜잭션이 끝나고이다. 트랜잭션*은 저번에 배웠다. 이 문답
끝 부분에 다시 요약 추가 하겠다 .
끝 부분에 다시 요약 추가 하겠다 .
커밋을 하는 방법은 Connection에 있는 setAutoCommit(false) 메서드를 사용하는 것이다.
커밋을 하기 위하여 setAutoCommit(false)를 시발점으로 선언하고, conn.commit() 메서드가
실행 결과를 커밋한다. 예시 코드는 다음과 같다.
커밋을 하기 위하여 setAutoCommit(false)를 시발점으로 선언하고, conn.commit() 메서드가
실행 결과를 커밋한다. 예시 코드는 다음과 같다.
<Connection.setAutoCommit(false)>
try {
conn = DriverManager.getConnection(...);
// 트랜잭션 시작
conn.setAutoCommit(false);
... // 쿼리 실행
... // 쿼리 실행
// 트랜잭션 커밋
conn.commit();
} catch(SQLException ex) {
if (conn != null) {
// 트랜잭션 롤백
conn.rollback();
}
} finally {
if (conn != null) {
try {
conn.close();
} catch(SQLException ex) {}
}
}
만약 내가 적어놓은 코드를 정상 실행 했다면, conn.commit()메서드가 정상적으로 커밋한다.
그러나, 코드들이 정상 실행 되지 못하고 예외가 발생했다면, 예외 안에 있는 conn.rollback();이
입력된 실행문들과 그 결과값을 취소해버리고 setAutoCommit(false); 때의 데이터 값으로 다시
돌아간다. Reset의 개념과 같다.
입력된 실행문들과 그 결과값을 취소해버리고 setAutoCommit(false); 때의 데이터 값으로 다시
돌아간다. Reset의 개념과 같다.
*본인 스스로 트랜잭션의 개념을 리마인드 하기 위해, 드라이브에서 가져왔다.
트랜잭션 = 여러 개의 SQL 명령문들을 하나의 논리적인 작업 단위로 처리하는 것.
All-OR-Nothing 방식*으로 처리
트랜젝션은 데이터의 일관성을 유지하기 위해 고안.
*한꺼번에 모든 sql문을 처리하거나 모두 하지 않거나. 명령어 처리 도중 하나의 명령어라도
잘못 되면 전체 실행 취소해버림. 모두 실행 후에는 정상 종료.
잘못 되면 전체 실행 취소해버림. 모두 실행 후에는 정상 종료.
ex) 은행 atm의 트랜젝션
현금인출 신청
현금카드 삽입 후 본인 인증
인출금액 선택
atm에서 현금 습득
계좌에 인출 금액 만큼 차감
만약 중간 과정에서 오류 발생이 되면, 전체 취소
작성자가 댓글을 삭제했습니다.
답글삭제블로그 보기가 불편해요
삭제저도 보기 불편해요
삭제