java - 如何使用 iBatis-Spring 获取参数化查询

标签 java sql spring ibatis

我正在开发一个带有 spring-ibatis 集成的应用程序,我必须在其中记录一些执行的查询。所以我想做的基本上是从 XML 配置文件中的 ibatis 映射语句获取 SQL,然后以某种方式添加参数。我已经能够使用以下代码行获取查询:

MappedStatement ms = (MappedStatement) ((SqlMapClientImpl) sqlMapClient)
    .getDelegate().getMappedStatement(queryId);

ms.setParameterClass(HashMap.class);
RequestScope scope = new RequestScope();
scope.setStatement(ms);

String sql = ((DynamicSql) ms.getSql()).getSql(scope, params);

因此,在第一行中我得到了 MappedStatement,在最后一行中我得到了原始查询。问题是,即使我将带有查询参数的对象传递给它,SQL 仍然具有参数占位符“?” (在 XML 查询中,它们是命名参数,而不是位置)。

我尝试按照建议设置 parameterClass 字段而不是 parameterMap here但没有成功。我不确定如何使用内联参数。

我正在使用 ibatis-sqlmap 2.3.0spring-ibatis 2.0.8

正如您可能已经注意到的,我对 iBatis 知之甚少甚至一无所知。另外,我知道这很脏,而且我正在使用不应该使用的类,无需指出这一点。

感谢您的帮助。

最佳答案

我已经解决了这个问题,我想与 future 可能遇到相同问题的读者分享解决方案。在此之前,请记住,这不是您应该使用 iBatis 的方式,而只是获取底层 SQL 的一种肮脏的解决方法。

首先,我们需要将 iBatis 查询分为至少 2 组:

  1. Static queries ,它们是简单的映射语句,没有任何条件元素。

  2. Dynamic queries ,它们是带有条件元素的映射语句(例如 isEqualisGreaterThanisNull...)。

完成此差异后,下面是获取 SQL 的代码:

public static String getSQLFromDynamicQuery(SqlMapClient sqlMapClient,
        String queryId, Object paramObject) {

    // Gets the SQL and parameters.
    MappedStatement ms = ((SqlMapClientImpl) sqlMapClient).getDelegate()
            .getMappedStatement(queryId);
    RequestScope scope = new RequestScope();
    scope.setStatement(ms);
    String sql = ((DynamicSql) ms.getSql()).getSql(scope, paramObject);
    Object[] params = ms.getSql().getParameterMap(scope, paramObject)
            .getParameterObjectValues(scope, paramObject);

    // Adds params to the query.
    return bindQueryParam(sql, params);
}

public String getSQLFromStaticQuery(SqlMapClient sqlMapClient,
        String queryId, Object... params) {

    // Gets the SQL.
    String sql = ((StaticSql) ((SqlMapClientImpl) sqlMapClient)
            .getDelegate().getMappedStatement(queryId).getSql()).getSql(
            null, null);

    // Adds params to the query.
    if (params != null) {
        sql = bindQueryParam(sql, params);
    }

    return sql;
}

public static String bindQueryParam(String sql, Object... params) {
    String result = sql;
    for (Object param : params) {
        result = result.replaceFirst("\\?",
                param == null ? "null" : param.toString());
    }
    return result;
}

bindQueryParam 方法用对象数组替换查询中的问号。对于静态查询,您必须传递该数组,同时对于动态查询,您可以根据映射语句的 parameterClass 传递一个 Objectjava.util.Map

这两种方法都使用显式子转换(我花了很多时间查看源代码来弄清楚如何使这个工作如您所想象的那样),因此您可能需要注意根据您正在处理的 Mapped Statement 调用正确的方法,否则您将得到一个 ClassCastException

同样,这不是推荐的方法,但如果您需要它,它是可行的。

关于java - 如何使用 iBatis-Spring 获取参数化查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44048186/

相关文章:

java - 我的 AppCompatActivity 无法正常工作。为什么这样?

java - 接受大写字符串输入

sql - 使用SQL查找不匹配的记录

spring - 如何测试 'dirty' 一个 spring 应用程序上下文?

spring - 如何在 spring boot 中为 mongodb 存储库进行自定义排序查询?

java - 为什么向 User-B 注册的数据包监听器不起作用?

java - SQLQuery.list() 返回相同的条目

mysql - 需要用两个不同的 where 子句返回两组数据

java - Java synchronized关键字与Spring @Transactional注解的逻辑对比

java - 在java中传递XML请求时出现问题