반응형
JDBC 단계별 로직
JDBC를 이용하여 DB 연결시 아래로직처럼 작성하여 사용한다.
package com.clt;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Test {
public static void main(String[] args) throws Exception {
// Driver 로딩
Class.forName("oracle.jdbc.driver.OracleDriver");
// 커넥션 연결
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:xe", "hangang", "victory123");
// 쿼리 셋팅
PreparedStatement ps = conn.prepareStatement("INSERT INTO TEST_USER (USER_ID, USER_PASS) VALUES (? ,?)");
ps.setString(1, "User");
ps.setString(2, "1234");
System.out.println("bind param sql :" + ps.toString());
// 쿼리 실행
int resultRow = ps.executeUpdate();
System.out.println("resultRow : " + resultRow);
}
}
그런데 이로직은 쿼리의 수행 결과는 아래와 같이 보이지 않을 것이다.
log4j:WARN No appenders could be found for logger (log4jdbc.debug).
log4j:WARN Please initialize the log4j system properly.
bind param sql :oracle.jdbc.driver.OraclePreparedStatementWrapper@2ed0fbae
resultRow : 1
파라미터보기 찍어서 보여주기
package com.clt;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class Test {
public static void main(String[] args) throws Exception {
// Driver 로딩
Class.forName("oracle.jdbc.driver.OracleDriver");
// 커넥션 연결
Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:xe", "hangang", "victory123");
// 쿼리 셋팅
// PreparedStatement ps = conn.prepareStatement("INSERT INTO TEST_USER (USER_ID, USER_PASS) VALUES (? ,?)");
LogPreparedStatement ps = new LogPreparedStatement(conn, "INSERT INTO TEST_USER (USER_ID, USER_PASS) VALUES (? ,?)");
ps.setString(1, "UserName3");
ps.setString(2, "1234");
System.out.println("bind param sql :" + ps.toString());
// 쿼리 실행
int resultRow = ps.executeUpdate();
System.out.println("resultRow : " + resultRow);
}
}
LogPreparedStatement를 구현해서 출력하면 아래와 같이 바인드된 쿼리를 볼수 있다.
log4j:WARN No appenders could be found for logger (log4jdbc.debug).
log4j:WARN Please initialize the log4j system properly.
bind param sql :INSERT INTO TEST_USER (USER_ID, USER_PASS) VALUES ('UserName3' ,'1234')
resultRow : 1
LogPreparedStatement
LogPreparedStatement의 주요 기능은 PreparedStatement의 기능을 그대로 받아 로그를 찍는 로직만 추가하여 주는 것이다.
public class LogPreparedStatement implements java.sql.PreparedStatement {
private ArrayList parameterValues;
private String sqlTemplate;
private PreparedStatement wrappedStatement;
//생성자
public LogPreparedStatement(Connection connection, String sql) throws SQLException {
wrappedStatement = connection.prepareStatement(sql);
sqlTemplate = sql;
parameterValues = new ArrayList();
}
....
@Override
public void setString(int parameterIndex, String x) throws SQLException {
wrappedStatement.setString(parameterIndex, x);
saveQueryParamValue(parameterIndex, x);
}
....
private void saveQueryParamValue(int position, Object obj) {
String strValue;
if (obj instanceof String || obj instanceof Date) {
strValue = "'" + obj + "'";
} else {
if (obj == null) {
strValue = "null";
} else {
strValue = obj.toString();
}
}
while (position >= parameterValues.size()) {
parameterValues.add(null);
}
parameterValues.set(position, strValue);
}
public String toString() {
return this.getQueryString();
}
public String getQueryString() {
StringBuffer buf = new StringBuffer();
int qMarkCount = 0;
ArrayList chunks = new ArrayList();
StringTokenizer tok = new StringTokenizer(sqlTemplate + " ", "?");
while (tok.hasMoreTokens()) {
String oneChunk = tok.nextToken();
buf.append(oneChunk);
try {
Object value;
if (parameterValues.size() > 1 + qMarkCount) {
value = parameterValues.get(1 + qMarkCount++);
} else {
if (tok.hasMoreTokens()) {
value = null;
} else {
value = "";
}
}
buf.append("" + value);
} catch (Throwable e) {
buf.append("Error : " + e.toString());
}
}
return buf.toString().trim();
}
}
파라미터를 set할때 파라미터가 저장되고 toString을 오버라이드 해서 저장된 파라미터가 출력되도록 구현 되어 있다.
LogPreparedStatement를 첨부하겠다.
반응형