찾기위해 여기저기 검색해보니 두가지가 있다.
1. DB연결 드라이버를 통해 확인하기
- 기존 DB연결 드라이버대신에 자체 드라이버를 사용하여 찾아내는 방법
- 개인적으로는 많이 사용되는 표준 드라이버를 사용하지 않는다는 면에서
안정성에 대한 의구심도 들고 회사에서 사용시 표준이 아니라서 거부되는 경우가
많을것 같다. 오류발생시 어디다가 문의할수도 없을테구...
- 참조 URL : http://log4sql.sourceforge.net/index_kr.html
2. preparedStatement로부터 상속받아 구현
- preparedStatement로부터 상속받아 그 위에 껍데기를 한겹 씌워준다고 보면 된다.
- 구현방법이라던가 함수 사용방법이 동일하기 때문에 쉽게 사용할 수 있다.
- 참조 URL : http://rookieceo.tistory.com/9
아래는 2번째 방법에 대한 참조URL의 원문이다. 링크만 걸어놓으면 해당 블로그의 글이
삭제되면 다시 찾아볼수 있는 방법이 없어 실례지만 본문을 퍼왔다.
보통의 PreparedStatement는 실제 어떤값이 SQL을 통해 실행되는지 알수가 없다. 이를 보완하기 Logging 이 가능한 LogPreparedStatement 를 구현해서 사용한다.
구현방법은 그다지 어렵지 않다. PreparedStatement 인터페이스를 Implement 하는 Class 를 선언하고, 필요한 부분만 구현해주면된다. PreparedStatement는 setXXX() 메소드를 이용해 해당 sql문의 '?'에 해당하는 위치에 값을 설정하는데, 이 SetXXX()로 들어온 인자값을 기억하고 있다가, 사용자가 원할때 값이 확정된 SQL문을 출력해주기만 하면 된다.
* 사용법
Connection con = DBService.getInstance().getConnection();
LogPreparedStatement pstmt = new LogPreparedStatement(con, query);
pstmt.setString (0, "Sokum");
logger.debug("registerTrxNoMaster sql = \n "+pstmt);
/*
* Loggable PreparedStatement
* @author : sokum
* @version : 2006-11-29
*/
1. java.sql.PreparedStatement 인터페이스 구현하기
public class LogPreparedStatement implements java.sql.PreparedStatement
{
2. 필요한 클래스변수를 선언한다.
// setString() 같은 값을 설정하는 메소드에 입력한 값을 저장할 용도로 ArrayList 객체를 선언한다.
private ArrayList parameterValues;
// preparedStatement sql문자열이 저장될 String 객체의 선언
private String sqlTemplate;
// 특별히 구현할 부분을 제외한 나머지 메소드들은 Connection 에서 얻은 PreparedStatement
// 객체로 메소드를 호출함으로,객체를 선언해준다.
private PreparedStatement wrappedStatement;
3. 생성자를 구현한다.
// 구현방법은 PreparedStatement의 생성자와 유사하게 구현하고, 여기서 PreparedStatement
// 객체를 실제로 생성하고, sql문저장, 파라메터의 ArrayList를 초기화 시켜준다.
public LogPreparedStatement(Connection connection, String sql) throws SQLException
{
wrappedStatement = connection.prepareStatement(sql);
sqlTemplate = sql;
parameterValues = new ArrayList();
}
// Sql문의 경우 StringBuffer를 사용하는 경우도 많으므로, StringBuffer를 사용할수 있는
// 생성자도 추가한다.
public LogPreparedStatement(Connection connection, StringBuffer sql) throws SQLException
{
this(connection, sql.toString());
}
4. PreparedStatement 인터페이스를 구현하였음으로, 정의돈 메소드들을 작성해준다.
// 메소드 작성은 특별히 사용자가 추가해주어야할 메소드를 제외하고는 아래의 방법과 같이
// 작성하면된다. 생성자에서 생성한 PreparedStatement 객체를 호출해 주기만 하면된다.
public void addBatch() throws java.sql.SQLException
{
wrappedStatement.addBatch();
}
...................... (이하생략) ....................
5. setXXX() 메소드들의 구현
// setXXX() 메소드를 이용해 설정한 SQL 컬럼의 값을 저장하기위해 saveQueryParamValue()
// 메소드를 호출해주면 끝이다. saveQueryParamValue() 메소드는 6번에 기술되어 있다.
// saveQueryParamValue() 는 2번째 Prameter를 기본자료형을 객체형으로 변환하는데,
// 그이유는 arrayList에는 기본자료형의 값을 저장할수 없기 때문이다.
// 여기 표시되지 않는 나머지 메소드들도 아래와 같은 방법으로 작성하면 된다.
public void setFloat(int parameterIndex, float x) throws java.sql.SQLException
{
wrappedStatement.setFloat(parameterIndex, x);
saveQueryParamValue(parameterIndex, new Float(x));
}
public void setInt(int parameterIndex, int x) throws java.sql.SQLException
{
wrappedStatement.setInt(parameterIndex, x);
saveQueryParamValue(parameterIndex, new Integer(x));
}
...................... (이하생략) ....................
6. LoggedPreparedStatement의 핵심 saveQueryParamValue() 메소드의 구현
// saveQueryParamValue() 메소드는 setXXX() 메소드를 이용해 설정된 값을 저장하기 위해
// 사용된다.
private void saveQueryParamValue(int position, Object obj)
{
String strValue;
// String이나 Date는 'value' 형태로, null값은 null로, 기타값은 value 형태로 변환해준다.
if (obj instanceof String || obj instanceof Date) {
strValue = "'" + obj + "'";
} else {
if(obj == null) {
strValue = "null";
} else {
strValue = obj.toString();
}
}
// 선택한 position 보다 ArrayList의 크기가 작은경우, ArrayList의 size를 추가한다.
while (position >= parameterValues.size()) {
parameterValues.add(null);
}
// arrayList에 값을 저장한 strValue 를 해당 index에 설정한다.
parameterValues.set(position, strValue);
}
7. 저장된 값을 조합해 String 형태로 뿌려줄 getQueryString() 메소드 구현
public String getQueryString()
{
StringBuffer buf = new StringBuffer();
int qMarkCount = 0;
ArrayList chunks = new ArrayList();
// PreparedStatement는 ?,?,? 형태로 작성됨으로, '?'를 기준으로 문자열을 분해한다.
StringTokenizer tok = new StringTokenizer(sqlTemplate+" ", "?");
while (tok.hasMoreTokens()) {
String oneChunk = tok.nextToken();
// 저장될 문자열 Buffer에 값부분의 '?'를 제외한 나머지 String을 buffer에 추가한다.
buf.append(oneChunk);
// parameterValues arrayList에 저장했던 값을 불러와 buffer에 추가한다.
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());
}
}
// 완성된 sql문을 리턴한다.
return buf.toString().trim();
}
8. 사용의 편의를 위해 toString() 메소드에 getQueryString() 호출부분을 삽입한다.
public String toString()
{
return this.getQueryString();
}
LogPreparedStatement.java