본문 바로가기
java

jdbc로 쿼리 로깅하기(jdbc 쿼리 출력)

by chunkind 2018. 9. 6.
반응형
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를 첨부하겠다.

 

LogPreparedStatement.java
0.02MB

반응형