9

我想知道 jdbi sql api 出于调试目的究竟处理了什么 sql 查询。我的接口类如下

public inteface myinteface{
    @SqlQuery("select :c1 from tablename where cond = :cd")
    String returnMeValue(@Bind("c1") String c1, @Bind("cd") Integer cd);
}

后来在另一个班级中称为String result = myinterfaceclassobject.returnMeValue("Name",1);

我没有得到预期的答案,所以我想看看 sql 查询的实际情况。那么有什么方法可以获得最终处理的查询吗?

4

3 回答 3

12

您可以通过编写 SqlCustomizer 来记录 sql。

import org.skife.jdbi.v2.StatementContext;
import org.skife.jdbi.v2.sqlobject.SqlStatementCustomizer;
import org.skife.jdbi.v2.sqlobject.SqlStatementCustomizerFactory;
import org.skife.jdbi.v2.sqlobject.SqlStatementCustomizingAnnotation;
import org.skife.jdbi.v2.tweak.StatementCustomizer;

import java.lang.annotation.*;
import java.lang.reflect.Method;
import java.sql.PreparedStatement;
import java.sql.SQLException;

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@SqlStatementCustomizingAnnotation(LogSqlFactory.Factory.class)
public @interface LogSqlFactory {

    static class Factory implements SqlStatementCustomizerFactory {

        @Override
        public SqlStatementCustomizer createForMethod(Annotation annotation, Class sqlObjectType, Method method) {
            return null;
        }

        @Override
        public SqlStatementCustomizer createForType(Annotation annotation, Class sqlObjectType) {
            return q -> q.addStatementCustomizer(new StatementCustomizer() {
                @Override
                public void beforeExecution(PreparedStatement stmt, StatementContext ctx) throws SQLException {
                    System.out.println(stmt.toString());
                }

                @Override
                public void afterExecution(PreparedStatement stmt, StatementContext ctx) throws SQLException { }

                @Override
                public void cleanup(StatementContext ctx) throws SQLException { }
            });
        }

        @Override
        public SqlStatementCustomizer createForParameter(Annotation annotation, Class sqlObjectType, Method method, Object arg) {
            return null;
        }
    }

}

只需包含此注释并在 SqlObject 中使用它。在您的情况下,像这样使用此注释,

@LogSqlFactory 
public inteface myinteface{
@SqlQuery("select :c1 from tablename where cond = :cd")
    String returnMeValue(@Bind("c1") String c1, @Bind("cd") Integer cd);
}

如果您使用自定义记录器进行记录,则使用 beforeExecution 方法。

于 2015-05-30T18:01:33.327 回答
2

基于@Manikandan 的回答,我发现它不适用于 Jdbi >= 3.10,我已经调整LogSqlFactory如下:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@SqlStatementCustomizingAnnotation(LogSqlFactory.Factory.class)
public @interface LogSqlFactory {

  class Factory implements SqlStatementCustomizerFactory {
    @Override
    public SqlStatementCustomizer createForType(Annotation annotation, Class sqlObjectType) {
      SqlLogger sqlLogger = new SqlLogger() {
        @Override
        public void logBeforeExecution(StatementContext context) {
          logSql(context);
        }
      };
      return statement -> statement.setSqlLogger(sqlLogger);
    }

    private static void logSql(StatementContext context) {
      System.out.println("Raw SQL:\n" + context.getRawSql());
      System.out.println("Parsed SQL:\n" + context.getParsedSql().getSql());
      System.out.println("Rendered SQL:\n" + context.getRenderedSql());
    }
  }
}

用 注释您的 SqlObject 接口LogSqlFactory以查看 SQL 语句:

@LogSqlFactory 
public interface Dao {
  @SqlQuery("select * from t")
  List<?> selectAll();
}
于 2019-11-08T08:54:46.137 回答
0

使用 log4jdbc 之类的东西要容易得多,使用 Manikandan 的方法也会大大降低您的代码速度。

但是,如果您仍然想使用它并且您的项目语言级别不支持 lambda,您可以使用以下修改:

  @Override
  public SqlStatementCustomizer createForType(Annotation annotation, final Class sqlObjectType) {

     return new SqlStatementCustomizer() {
        @Override
        public void apply(SQLStatement sqlStatement) throws SQLException {
           sqlStatement.addStatementCustomizer(new StatementCustomizer() {
              @Override
              public void beforeExecution(PreparedStatement stmt, StatementContext ctx) throws SQLException {
                 System.out.println(stmt.toString());
              }

              @Override
              public void afterExecution(PreparedStatement stmt, StatementContext ctx) throws SQLException {
              }

              @Override
              public void cleanup(StatementContext ctx) throws SQLException {
              }
           });
        }
     };

  }

但是 stmt.toString() 不保证返回 SQL 语句,它取决于实现。这不适用于 SQLite。

于 2015-06-13T21:43:58.653 回答