01. JSP에서 JDBC 프로그래밍 하기
1.1 JDBC의 구조
자바 웹 어플리케이션 => JDBC API => JDBC 드라이버
1.2 JDBC 프로그래밍의 코딩 스타일
1. JDBC 드라이버 로딩
2. 데이터베이스 커넥션 구함
3. 쿼리 실행을 위한 statement 객체 생성
4. 쿼리 실행
5. 쿼리 실행 결과 사용
6. statement 종료
7. 데이터베이스 커넥션 사용
1.3
<%@ page import = “java.sql.DriverManager”%>
<%@ page import = “java.sql.Connection”%>
<%@ page import = “java.sql.Statement”%>
<%@ page import = “java.sql.ResultSet”%>
<%@ page import = “java.sql.SQLException”%>
<%
Class.forName(“com.mysql.jdbc.Driver”);
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
String jdbcDriver = “jdbc:mysql://localhost:3306/chap12?” +
String dbpass = “sa”;
String query = “select * from MEMBER order by MEMBERID”;
conn = DriverManager.getConnection(jdbcDriver, dbuser, dbPass);
stmt = conn.create.Statement();
rs=stmt.executeQuery(query);
while(rs.next()){
%>
<%= rs.getString(“NAME”)%>
<%
}
} catch(SQLException ex){
out.println(ex.getMessage());
ex.printStackTrace();
}
finally{
if(rs != null) try {rs.close();} catch(SQLException ex){}
if(stmt != null) try{ stmt.close();} catch(SQLException ex){}
if(conn != null) try{ conn.close();} catch(SQLException ex){}
}
%>
1.4 DBMS와 통신을 위한 JDBC 드라이버
MySQL : com.mysql.jdbc.Driver
오라클 : oracle.jdbc.driver.OracleDriver
MS SQL 서버 : com.microsoft.sqlserver.jdbc.SQLServerDriver
1.5 ResultSet에서 값 읽어 오기
rs.next : ture
– > 1행 -> 2행 -> 3행 으로 커서는 이동한다.
ResultSet 클래스의 주요 데이터 읽기 매소드
getString(String name) : 지정한 컬럼의 값을 String 으로 읽어 온다.
getString(int index)
getCharacterStream(String name) : 지정한 컬람의 값을 스틸힘으로 읽어 온다. Long Varchar 타입을 읽어올 떄 사용
getCharacterString(int index)
getInt(String name) : 지정한 컬럼의 값을 int 타입으로 읽어온다.
getInt(int index)
getLong(String name) : 지정한 컬럼의 값을 long 타입으로 읽어온다.
getLong(int index)
getDouble(String name) : 지정한 컬럼의 값을 double타입으로 읽어온다.
getDouble(int index)
getFloat(String name) : 지정한 컬럼의 값을 float타입으로 읽어온다.
getFloat(int index)
getTimestamp(String name) : 지정한 컬럼의 값을 timestamp 타입으로 읽어온다.
getTimestamp(int index)
getDate(String name) : 지정한 컬럼의 값을 date 타입으로 읽어온다
getDate(int index)
getTime(String name) : 지정한 컬럼의 값을 time 타입으로 읽어온다.
getTime(int index)
1.6 ResultSet에서 LONG VARCHAR 타입 값 읽어오기
대량의 덱스트 데이터를 저장할때 사용되며, Resultset에서 LONG VARCHAR 타입의 데이터를 읽어 오기 위해서는 getCharacterStream() 메서드를 사용해야 한다. ResultSet.getCharacterStream(메서드의 리턴 타입이 java.io.Reader 타입이다
– 코드:
String data = null;
java.io.Reader reader = null;
try{
reader = rs.getCharacterStream(“FIELD”);
if(reader != null){
StringBuffer buff = new StringBuffer();
char[] ch = new char[512];
int len = -1;
while((len=reader.read(ch))!= -1){
buff.append(ch, -, len);
}
data = buff.toStirng();
}
chatch(IOException ex){
}finally{
if(reader != null) try{reader.close();} chatch(IOException ex){}
}
1.7 PreparedStatement를 사용한 쿼리 실행
java.sql.PreparedStatement는 java.sql.Statement와 동일한 기능을 제공 , 차이가 있다면 SQL 쿼리의 틀을 미리 생성해 놓고 값을 나중에 지정한느것
순서 :
1. Connectin.prepareStatement() 메서드를 사용하여 preparedStatement 생성
2. PreparedStatement의 set 메서드를 사용하여 필요한 값 지정
3. PreparedStatement의 executeQuery() 또는 executeUpdate() 메서드를 사용하여 쿼리를 실행
4. finally 블록에서 사용한 PreparedStatement를 닫는다. (close() 메서드 사용)
PreparedStatement를 생설할때 실행할 쿼리를 입력해야 하는데 다음과 같이 사용한다.
PreparedStatement pstmt = null;
pstmt = conn.prepareStatement( “insert into member(memberid, name, email) values(?,?,?)”);
pstmt.setString(1,”starstroy”);
pstmt.setString(2,”홍길동”);
pstmt.setString(3,a@a.com);
pstmt.executeUpdate();
ResultSet의 메서드들
setString(int index, String x) : 지정한 인덱스의 파라미터 값을 x로 지정한다.
setCharacterStream(int index, Reader reader, int length) : 지정한 인덱스의 값이 long varchar 타입의 값으로 지정할때 사용한다.
setInt(int index, int x) : 지정한 인덱스의 타파라미터 값을 int 값 x 로 지정한다.
setLong(int index, long x) : 지정한 인덱스의 타파라미터 값을 long 값 x 로 지정한다.
setDouble(int index, double x) : 지정한 인덱스의 타파라미터 값을 double값 x 로 지정한다.
setFloat(int index, float x) : 지정한 인덱스의 타파라미터 값을 float 값 x 로 지정한다.
setTimestamp(int index, Timesetamp x) : 지정한 인덱스의 값을 SQL TIMESTAMP 타입을 나타내는 java.sql.TimeStamp 타입으로 지정한다.
setDate(int index Date x) : 지정한 인덱스의 값을 SQL DATE 타입을 나타내는 java.sql.date 타입으로 지정한다.
setTime(int index, Time x) : 지정한 인덱스의 값을 SQL TIME 타입을 나타내는 java.sql.time 타입으로 지정한다.
setCharacterStream(int index, Reader reader, int length)
Reader로 부터 length 클자 수만큼 데이터를 읽어와 저장ㅎ나다. Reader에는 String으로 부터 데이터를 읽어 오는 Reader와 파일로 부터 읽어 오는 Reader등 다양한 Reader 가 존재한다.
코드 :
PreapredStatement pstmt = null;
try{
String value = “….”;
pstmt = conn.prepareStatement(…);
java.io.StirngReader reader = new java.io.StringReader(value);
pstmt.setCharacterStream(1, reader, value.length());
..
} catch(SQLException ex){
}finally{
if(pstmt != null) try{pstmt.close(); } catch(SQLException ex){}
1.9 PreparedStatement 쿼리를 사용하는 이유
2. 값 변환을 자동으로 하기 위해
3. 간결한 코드를 위해
1.10 웹 어플리케이션 구동시 JDBC 드라이버 로딩하기
Class.forName(JDBCDriverClass);
웹 어플리케이션이 시작될때 자동으로 JDBC 드라이버를 로딩하도록 만드려면 서블릿 클래스를 사용해야 한다.
package kame.jdbc.loader;
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 dervers = config.getInitParameter(“jdbcdriver”);
String Tokenizer st = new StringTokenizer(drivers,”,”);
while(st.hasMoreTokens()){
String jdbcDriver = st.nextToken();
Class.forName(jdbcDriver);
}
}catch(Exception ex){
throw new ServletException(ex);
}
}
}
Loader.java 를 컴파일 한 다음에는 웹 어플리케이션이 시작될때 자동으로 Loader 서블릿 클래스가 실행되도록 설정해 주어야 한다. web.xml파일에 <servlet> 태그를 추가해주면 된다.
<servlet>
<servlet-name> JDBCDriverLoader</servlet-name>
<servlet-class>kame.jdbc.loader.Loader</servlet-class>
<init-param>
<param-name>jdbcdriver</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
2. JDBC에서 트랜잭션 처리
트랜잭션 시작 : 트랜잭션 시작 이후 실행되는 쿼리를 하나의 작업으로 처리
..
..
..
트랜잭션 커밋 : 트랜잭션 시작 이후 에러가 발생하지 않으면 쿼리 결과를 DB에 반영
트랜잭션 롤백 : 에러가 발생하면 실행된 쿼리 결과를 DB에 반영하지 않고 취소함
try{
conn=DriverManager.getConnection(…);
conn.setAutoCommit(false);
conn.commit();
}
catch(SQLException ex){
if(conn != null){
conn.rollback();
}
}
finally{
if(conn != null){
try{conn.colse();}catch(SQLException ex){}}}
3. 커넥션 풀
: 커넥션 풀 기법에서는 풀속에 데이터베이스와 연결된 커넥션을 미리 생성해 놓는다. 데이터베이스 커넥션이 필요할 경우, 커넥션을 새로 생성하는 것이 아니라 풀속에 미리 생성되어 있는 커넥션을 가져다가 사용하고, 사용이 끝나면 커넥션을 풀에 반환한다. 풀에 반호나된 커넥션은 다음에 다시 사용된다.
풀속에 미리 커넥션이 생성되어 있기 때문에 커넥션을 생성하는데 드는 연결시간이 소비 되지 않는다.
커넥션을 계속 해서 재사용하기 때문에 생성되는 커넥션 수가 많지 않다.
3.1 DBCP를 이용해서 커넥션 풀 사용하기
– DBCP 관련 jar 파일 및 JDBC 드라이버 jar 파일 설치하기
– 커넥션 풀 관련 설정 파일 초기화 하기
: DBMS에 연결할때 사용될 JDBC 드라이버
: org.apache.commons.dbcp.PoolingDriver : DBCP API의 JDBC 드라이버
web.xml 파일을 사용한 DB초기화
<servlet>
<servlet-name> DBCPInit</servlet-name>
<servlet-class>madvires.jdbcdriver.DBCPInit</servlet-class>
<init-param>
<param-name>jdbcdriver</param-name>
<param-value>com.mysql.jdbc.Driver</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
—- 웹 어플리케이션이 시작할때 DBCPInit 서블릿 클래스가 자동으로 시작되고 init() 메서드가 호출된다.
– 커넥션 풀 관련 드라이버 로딩하기
– 커넥션 풀로 부터 커넥션 사용하기
Connection conn = null;
try{
Stirng jdbcDriver = “jdbc:apache:commons:dbcp:/pool”;
conn = DriverManager.getConnection(jdbcDriver);
}finally{
if(conn != null) try{conn.close(); } catch(SQLException ex) {}
}