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

时间:2017-05-18 12:46:21

标签: 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查询中,它们被命名为参数,而不是位置)。

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

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

你可能已经注意到我对iBatis知之甚少。另外,请知道这很脏,而且我正在使用我不应该使用的课程,不需要指出这一点。

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

我已经解决了这个问题,我希望与未来可能存在相同问题的读者分享解决方案。在此之前,请记住,这不是您应该使用iBatis的方式,而只是获取基础SQL的一种肮脏的解决方法。

首先,我们需要在至少两组中对iBatis查询进行分组:

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

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

  3. 一旦你完成了这个差异,这里是获取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方法用对象数组替换查询中的问号。对于静态查询,您必须同时传递该数组,以便根据映射语句的Object来传递java.util.MapparameterClass的动态数据。 / p>

    这两种方法都使用显式子广播(我花了很多时间查看源代码,以便弄清楚如何使这项工作如你所想),所以你可能要注意调用正确的方法根据您正在处理的地图声明,或者您将获得ClassCastException

    同样,这不是推荐的方式,但如果你需要,它可以工作。