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



我正在开发一个带有 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,但没有成功。我不确定如何使用内联参数。

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

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

谢谢你的帮助。

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

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

  1. 静态查询,它们是没有任何条件元素的简单映射语句。

  2. 动态查询,它们是带有条件元素的映射语句(例如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方法将查询中的问号替换为对象数组。对于静态查询,您必须传递该数组,同时对于动态数组,您可以传递Objectjava.util.Map,具体取决于您对映射语句的parameterClass

这两种方法都使用显式子转换(我花了很多时间查看源代码以弄清楚如何使这项工作可以想象),因此您可能需要注意根据您正在处理的映射语句调用正确的方法,否则您将获得ClassCastException

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

最新更新