【问题标题】:How to print the @SqlQuery annotation in JDBI sql api如何在 JDBI sql api 中打印@SqlQuery 注释
【发布时间】:2014-05-09 12:12:46
【问题描述】:

我想知道 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 查询的实际情况。那么有没有什么方法可以得到最终处理的查询呢?

【问题讨论】:

  • 有同样的问题。你知道怎么做吗?

标签: java sql sql-server jdbi


【解决方案1】:

您可以通过编写 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 方法。

【讨论】:

  • 我试过这个但没有用。有什么先决条件吗?
  • @Manikandan 我发现您的答案不适用于较新版本的 Jdbi,并在此处调整了您的解决方案:stackoverflow.com/a/58763295/2986905 随时将我的返工整合到您的答案中,我将删除我的。
【解决方案2】:

基于@Manikandan's answer,我发现它不适用于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());
    }
  }
}

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

@LogSqlFactory 
public interface Dao {
  @SqlQuery("select * from t")
  List<?> selectAll();
}

【讨论】:

    【解决方案3】:

    使用 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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-27
      • 2019-09-26
      • 1970-01-01
      • 2020-12-06
      • 1970-01-01
      • 2018-10-07
      • 2023-03-07
      • 1970-01-01
      相关资源
      最近更新 更多