PreparedStatementLogger.java

  1. /*
  2.  *    Copyright 2009-2023 the original author or authors.
  3.  *
  4.  *    Licensed under the Apache License, Version 2.0 (the "License");
  5.  *    you may not use this file except in compliance with the License.
  6.  *    You may obtain a copy of the License at
  7.  *
  8.  *       https://www.apache.org/licenses/LICENSE-2.0
  9.  *
  10.  *    Unless required by applicable law or agreed to in writing, software
  11.  *    distributed under the License is distributed on an "AS IS" BASIS,
  12.  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13.  *    See the License for the specific language governing permissions and
  14.  *    limitations under the License.
  15.  */
  16. package org.apache.ibatis.logging.jdbc;

  17. import java.lang.reflect.InvocationHandler;
  18. import java.lang.reflect.Method;
  19. import java.lang.reflect.Proxy;
  20. import java.sql.CallableStatement;
  21. import java.sql.PreparedStatement;
  22. import java.sql.ResultSet;

  23. import org.apache.ibatis.logging.Log;
  24. import org.apache.ibatis.reflection.ExceptionUtil;

  25. /**
  26.  * PreparedStatement proxy to add logging.
  27.  *
  28.  * @author Clinton Begin
  29.  * @author Eduardo Macarron
  30.  */
  31. public final class PreparedStatementLogger extends BaseJdbcLogger implements InvocationHandler {

  32.   private final PreparedStatement statement;

  33.   private PreparedStatementLogger(PreparedStatement stmt, Log statementLog, int queryStack) {
  34.     super(statementLog, queryStack);
  35.     this.statement = stmt;
  36.   }

  37.   @Override
  38.   public Object invoke(Object proxy, Method method, Object[] params) throws Throwable {
  39.     try {
  40.       if (Object.class.equals(method.getDeclaringClass())) {
  41.         return method.invoke(this, params);
  42.       }
  43.       if (EXECUTE_METHODS.contains(method.getName())) {
  44.         if (isDebugEnabled()) {
  45.           debug("Parameters: " + getParameterValueString(), true);
  46.         }
  47.         clearColumnInfo();
  48.         if ("executeQuery".equals(method.getName())) {
  49.           ResultSet rs = (ResultSet) method.invoke(statement, params);
  50.           return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
  51.         } else {
  52.           return method.invoke(statement, params);
  53.         }
  54.       }
  55.       if (SET_METHODS.contains(method.getName())) {
  56.         if ("setNull".equals(method.getName())) {
  57.           setColumn(params[0], null);
  58.         } else {
  59.           setColumn(params[0], params[1]);
  60.         }
  61.         return method.invoke(statement, params);
  62.       } else if ("getResultSet".equals(method.getName())) {
  63.         ResultSet rs = (ResultSet) method.invoke(statement, params);
  64.         return rs == null ? null : ResultSetLogger.newInstance(rs, statementLog, queryStack);
  65.       } else if ("getUpdateCount".equals(method.getName())) {
  66.         int updateCount = (Integer) method.invoke(statement, params);
  67.         if (updateCount != -1) {
  68.           debug("   Updates: " + updateCount, false);
  69.         }
  70.         return updateCount;
  71.       } else {
  72.         return method.invoke(statement, params);
  73.       }
  74.     } catch (Throwable t) {
  75.       throw ExceptionUtil.unwrapThrowable(t);
  76.     }
  77.   }

  78.   /**
  79.    * Creates a logging version of a PreparedStatement.
  80.    *
  81.    * @param stmt
  82.    *          - the statement
  83.    * @param statementLog
  84.    *          - the statement log
  85.    * @param queryStack
  86.    *          - the query stack
  87.    *
  88.    * @return - the proxy
  89.    */
  90.   public static PreparedStatement newInstance(PreparedStatement stmt, Log statementLog, int queryStack) {
  91.     InvocationHandler handler = new PreparedStatementLogger(stmt, statementLog, queryStack);
  92.     ClassLoader cl = PreparedStatement.class.getClassLoader();
  93.     return (PreparedStatement) Proxy.newProxyInstance(cl,
  94.         new Class[] { PreparedStatement.class, CallableStatement.class }, handler);
  95.   }

  96.   /**
  97.    * Return the wrapped prepared statement.
  98.    *
  99.    * @return the PreparedStatement
  100.    */
  101.   public PreparedStatement getPreparedStatement() {
  102.     return statement;
  103.   }

  104. }