我正在开发一个带有 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.0
和 spring-ibatis 2.0.8
。
正如您可能已经注意到的,我对 iBatis 知之甚少甚至一无所知。另外,我知道这很脏,而且我正在使用不应该使用的类,无需指出这一点。
感谢您的帮助。
最佳答案
我已经解决了这个问题,我想与 future 可能遇到相同问题的读者分享解决方案。在此之前,请记住,这不是您应该使用 iBatis 的方式,而只是获取底层 SQL 的一种肮脏的解决方法。
首先,我们需要将 iBatis 查询分为至少 2 组:
Static queries ,它们是简单的映射语句,没有任何条件元素。
Dynamic queries ,它们是带有条件元素的映射语句(例如
isEqual
、isGreaterThan
、isNull
...)。
完成此差异后,下面是获取 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
传递一个 Object
或 java.util.Map
。
这两种方法都使用显式子转换(我花了很多时间查看源代码来弄清楚如何使这个工作如您所想象的那样),因此您可能需要注意根据您正在处理的 Mapped Statement 调用正确的方法,否则您将得到一个 ClassCastException
。
同样,这不是推荐的方法,但如果您需要它,它是可行的。
关于java - 如何使用 iBatis-Spring 获取参数化查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44048186/