当前位置: 首页 > 知识库问答 >
问题:

从MyBatis映射器获取SQL查询的字符串表示形式

孟谭三
2023-03-14

SearchRepository调用Mapper中的searchTmp方法,而Mapper从MyBatis XML文件调用并执行searchTmp方法。

在完美的世界中,我希望将searchTmp方法的void返回类型更改为字符串,并强制MyBatis将执行的SQL作为字符串返回。我有可能明白吗?

public class SearchRepository {

    private final SearchTmpMapper mapper;

    public void searchTmp() {
        SearchFilter filter = intializeFilter();
        mapper.searchTmp(filter);
}

public interface SearchTmpMapper {

    void searchTmp(
            @Param("filter") SearchFilter filter);
}

<select id="searchTmp">
        /* some SQL select */
</select>

共有1个答案

翁硕
2023-03-14

您可以使用Spring AOP来完成,但是需要在应用程序中添加一个额外的类,这个类将实现新的“方面”。见下文:

几年前,我实现了一个AOP方面(我使用的是Spring),它为我正在处理的HotRod ORM记录所有执行的SQL语句及其响应时间。

下面的代码(开源)记录了每个SQL语句及其响应时间。It内部类(此处未显示)将它们的执行从最重到最轻进行排序;REST API可以为应用程序的管理界面提供“最糟糕的违规者”。

@Aspect
@Component
public class SQLMetricsAspect {

  private ThreadLocal<String> sql = new ThreadLocal<String>();

  @Autowired
  private SQLMetrics sqlMetrics;

  @Around(value = "execution(* javax.sql.DataSource.getConnection())")
  public Object measureGetConnection(final ProceedingJoinPoint joinPoint) throws Throwable {
    try {
      Object conn = joinPoint.proceed();
      AspectJProxyFactory proxyFactory = new AspectJProxyFactory(conn);
      proxyFactory.addAspect(this);
      Object proxyConn = proxyFactory.getProxy();
      return proxyConn;
    } catch (Throwable e) { throw e; }
  }

  @Around(value = "execution(* java.sql.Connection.prepareStatement(..)) && args(sql)")
  public Object measurePrepareStatement(final ProceedingJoinPoint joinPoint, final String sql) throws Throwable {
    try {
      this.sql.set(sql);
      Object ps = joinPoint.proceed();
      AspectJProxyFactory proxyFactory = new AspectJProxyFactory(ps);
      proxyFactory.addAspect(this);
      PreparedStatement proxyPS = proxyFactory.getProxy();
      return proxyPS;
    } catch (Throwable e) { throw e; }
  }

  // Then advice each SQL execution method, as in:

  @Around(value = "execution(* java.sql.PreparedStatement.execute(..))")
  public Object adviceExecute(final ProceedingJoinPoint joinPoint) throws Throwable {
    return measureSQLExecution(joinPoint, this.sql.get());
  }

  // All other java.sql.PreparedStatement declared methods...
  @Around(value = "execution(* java.sql.PreparedStatement.executeLargeUpdate(..))")
  public Object adviceExecuteLargeUpdate(final ProceedingJoinPoint joinPoint) throws Throwable {
    return measureSQLExecution(joinPoint, this.sql.get());
  }

  @Around(value = "execution(* java.sql.PreparedStatement.executeQuery(..))")
  public Object adviceExecExecuteQuery(final ProceedingJoinPoint joinPoint) throws Throwable {
    return measureSQLExecution(joinPoint, this.sql.get());
  }

  @Around(value = "execution(* java.sql.PreparedStatement.executeUpdate(..))")
  public Object adviceExecuteUpdate(final ProceedingJoinPoint joinPoint) throws Throwable {
    return measureSQLExecution(joinPoint, this.sql.get());
  }

  // java.sql.Statement declared methods

  @Around(value = "execution(* java.sql.Statement.execute(..)) && args(sql)")
  public Object adviceExecute(final ProceedingJoinPoint joinPoint, final String sql) throws Throwable {
    return measureSQLExecution(joinPoint, sql);
  }

  @Around(value = "execution(* java.sql.Statement.execute(..)) && args(sql, autoGeneratedKeys)")
  public Object adviceExecute(final ProceedingJoinPoint joinPoint, final String sql, final int autoGeneratedKeys)
      throws Throwable {
    return measureSQLExecution(joinPoint, sql);
  }

  @Around(value = "execution(* java.sql.Statement.execute(..)) && args(sql, columnIndexes)")
  public Object adviceExecute(final ProceedingJoinPoint joinPoint, final String sql, final int[] columnIndexes)
      throws Throwable {
    return measureSQLExecution(joinPoint, sql);
  }

  @Around(value = "execution(* java.sql.Statement.execute(..)) && args(sql, columnNames)")
  public Object adviceExecute(final ProceedingJoinPoint joinPoint, final String sql, final String[] columnNames)
      throws Throwable {
    return measureSQLExecution(joinPoint, sql);
  }

  // TODO Check how batches work
  @Around(value = "execution(* java.sql.Statement.executeBatch(..))")
  public Object adviceExecuteBatch(final ProceedingJoinPoint joinPoint) throws Throwable {
    return measureSQLExecution(joinPoint, this.sql.get());
  }

  // TODO Check how batches work
  @Around(value = "execution(* java.sql.Statement.executeLargeBatch(..))")
  public Object adviceExecuteLargeBatch(final ProceedingJoinPoint joinPoint) throws Throwable {
    return measureSQLExecution(joinPoint, this.sql.get());
  }

  @Around(value = "execution(* java.sql.Statement.executeLargeUpdate(..)) && args(sql)")
  public Object adviceExecuteLargeUpdate(final ProceedingJoinPoint joinPoint, final String sql) throws Throwable {
    return measureSQLExecution(joinPoint, sql);
  }

  @Around(value = "execution(* java.sql.Statement.executeLargeUpdate(..)) && args(sql, autoGeneratedKeys)")
  public Object adviceExecuteLargeUpdateAK(final ProceedingJoinPoint joinPoint, final String sql,
      final int autoGeneratedKeys) throws Throwable {
    return measureSQLExecution(joinPoint, sql);
  }

  @Around(value = "execution(* java.sql.Statement.executeLargeUpdate(..)) && args(sql, columnIndexes)")
  public Object adviceExecuteLargeUpdate(final ProceedingJoinPoint joinPoint, final String sql,
      final int[] columnIndexes) throws Throwable {
    return measureSQLExecution(joinPoint, sql);
  }

  @Around(value = "execution(* java.sql.Statement.executeLargeUpdate(..)) && args(sql, columnNames)")
  public Object adviceExecuteLargeUpdate(final ProceedingJoinPoint joinPoint, final String sql,
      final String[] columnNames) throws Throwable {
    return measureSQLExecution(joinPoint, sql);
  }

  @Around(value = "execution(* java.sql.Statement.executeQuery(..)) && args(sql)")
  public Object adviceExecuteQuery(final ProceedingJoinPoint joinPoint, final String sql) throws Throwable {
    return measureSQLExecution(joinPoint, sql);
  }

  @Around(value = "execution(* java.sql.Statement.executeUpdate(..)) && args(sql)")
  public Object adviceExecuteUpdate(final ProceedingJoinPoint joinPoint, final String sql) throws Throwable {
    return measureSQLExecution(joinPoint, sql);
  }

  @Around(value = "execution(* java.sql.Statement.executeUpdate(..)) && args(sql, autoGeneratedKeys)")
  public Object adviceExecuteUpdateAK(final ProceedingJoinPoint joinPoint, final String sql,
      final int autoGeneratedKeys) throws Throwable {
    return measureSQLExecution(joinPoint, sql);
  }

  @Around(value = "execution(* java.sql.Statement.executeUpdate(..)) && args(sql, columnIndexes)")
  public Object adviceExecuteUpdate(final ProceedingJoinPoint joinPoint, final String sql, final int[] columnIndexes)
      throws Throwable {
    return measureSQLExecution(joinPoint, sql);
  }

  @Around(value = "execution(* java.sql.Statement.executeUpdate(..)) && args(sql, columnNames)")
  public Object adviceExecuteUpdate(final ProceedingJoinPoint joinPoint, final String sql, final String[] columnNames)
      throws Throwable {
    return measureSQLExecution(joinPoint, sql);
  }
  private Object measureSQLExecution(final ProceedingJoinPoint joinPoint,
      final String sql) throws Throwable {
    long start = System.currentTimeMillis();
    try {
      Object ps = joinPoint.proceed();
      long end = System.currentTimeMillis();
      this.sqlMetrics.record(sql, end - start, null);
      return ps;

    } catch (Throwable t) {
      long end = System.currentTimeMillis();
      this.sqlMetrics.record(sql, end - start, t);
      throw t;
    }
  }
 类似资料:
  • 问题内容: 我需要从Hibernate查询中获取字符串,并稍后进行处理(因此无法使用来解决)。 我已经看过如何从HibernateCriteriaAPI(并非用于记录日志)中获取SQL,但是有了这种解决方法,我得到了SQL查询字符串,但是没有显示它显示’?’的参数值,有没有办法获得带有参数值的完整SQL字符串? 我的意思是,有了这种解决方案,我可以得到,但我需要得到… 有想法吗? 问题答案: 有一

  • 问题内容: 我有一个C python扩展名,我想打印一些诊断信息。 我收到一个字符串作为PyObject *。 获取此对象的字符串表示形式(使其可用作const char *)的规范方法是什么? 更新: 澄清以强调访问为const char *。 问题答案: 使用(模仿Python的函数)或(模仿),然后调用get (您可以并且通常应该将其用作,例如: 任何人都可以使用此方法。如果您完全确定是Py

  • 在mapper中,我调用了一个proc'xyz',它返回所查询的ProcessType表的行列表的光标。

  • 问题内容: 给出以下代码: 我想获取上面的数据库查询生成器将生成的原始SQL查询字符串。在此示例中,它将为。 我该怎么做呢? 问题答案: 要将最近运行的查询输出到屏幕,可以使用以下命令: 我相信最近的查询将在数组的底部。 您将拥有类似的东西:

  • 问题内容: 我需要的是将URL 的值转换成变量,然后在jQuery代码中使用它: 有谁知道如何使用JavaScript或jQuery来获取该价值? 问题答案: 这就是你所需要的:) 以下代码将返回一个包含URL参数的JavaScript对象: 例如,如果您具有URL: 此代码将返回: 您可以执行以下操作:

  • 问题内容: 假设我定义了以下类型: 我将如何以编程方式将类型作为字符串获取,因此以后可能很容易重构,而不是: 我不太喜欢,因为它实例化了它,也可以从Interface实例化。 问题答案: 您可以使用包装(包装也可以在内部使用)。您可以从 指向 该类型的 指针 开始,并使用没有分配的 类型化_指针值,并且可以使用来从其描述符导航到指针的 _基本 类型(或 元素 类型)的描述符。 例: 输出(在Go