package org.apache.ibatis.logging.jdbc;
import org.apache.ibatis.logging.Log;
import org.apache.ibatis.logging.LogFactory;
import org.apache.ibatis.reflection.ExceptionUtil;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
/**
* PreparedStatement proxy to add logging
*/
public class PreparedStatementLogger extends BaseJdbcLogger implements InvocationHandler {
private static final Log log = LogFactory.getLog(PreparedStatement.class);
private PreparedStatement statement;
private String sql;
private PreparedStatementLogger(PreparedStatement stmt, String sql) {
this.statement = stmt;
this.sql = sql;
}
public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
try {
if (EXECUTE_METHODS.contains(method.getName())) {
if (log.isDebugEnabled()) {
log.debug("==> Executing: " + removeBreakingWhitespace(sql));
log.debug("==> Parameters: " + getParameterValueString());
}
clearColumnInfo();
if ("executeQuery".equals(method.getName())) {
ResultSet rs = (ResultSet) method.invoke(statement, params);
if (rs != null) {
return ResultSetLogger.newInstance(rs);
} else {
return null;
}
} else {
return method.invoke(statement, params);
}
} else if (SET_METHODS.contains(method.getName())) {
if ("setNull".equals(method.getName())) {
setColumn(params[0], null);
} else {
setColumn(params[0], params[1]);
}
return method.invoke(statement, params);
} else if ("getResultSet".equals(method.getName())) {
ResultSet rs = (ResultSet) method.invoke(statement, params);
if (rs != null) {
return ResultSetLogger.newInstance(rs);
} else {
return null;
}
} else if ("equals".equals(method.getName())) {
Object ps = params[0];
return ps instanceof Proxy && proxy == ps;
} else if ("hashCode".equals(method.getName())) {
return proxy.hashCode();
} else {
return method.invoke(statement, params);
}
} catch (Throwable t) {
throw ExceptionUtil.unwrapThrowable(t);
}
}
/**
* Creates a logging version of a PreparedStatement
*
* @param stmt - the statement
* @param sql - the sql statement
* @return - the proxy
*/
public static PreparedStatement newInstance(PreparedStatement stmt, String sql) {
InvocationHandler handler = new PreparedStatementLogger(stmt, sql);
ClassLoader cl = PreparedStatement.class.getClassLoader();
return (PreparedStatement) Proxy.newProxyInstance(cl, new Class[]{PreparedStatement.class, CallableStatement.class}, handler);
}
/**
* Return the wrapped prepared statement
*
* @return the PreparedStatement
*/
public PreparedStatement getPreparedStatement() {
return statement;
}
}
|