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 に答える
0

log4jdbc のようなものを使用する方がはるかに簡単です。マニカンダンの方法を使用すると、コードもかなり遅くなります。

ただし、それでも使用したいが、プロジェクトの言語レベルがラムダをサポートしていない場合は、次の変更を使用できます。

  @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 に答える