我正在使用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.0
和spring-ibatis 2.0.8
。
你可能已经注意到我对iBatis知之甚少。另外,请知道这很脏,而且我正在使用我不应该使用的课程,不需要指出这一点。
感谢您的帮助。
答案 0 :(得分:0)
我已经解决了这个问题,我希望与未来可能存在相同问题的读者分享解决方案。在此之前,请记住,这不是您应该使用iBatis的方式,而只是获取基础SQL的一种肮脏的解决方法。
首先,我们需要在至少两组中对iBatis查询进行分组:
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
方法用对象数组替换查询中的问号。对于静态查询,您必须同时传递该数组,以便根据映射语句的Object
来传递java.util.Map
或parameterClass
的动态数据。 / p>
这两种方法都使用显式子广播(我花了很多时间查看源代码,以便弄清楚如何使这项工作如你所想),所以你可能要注意调用正确的方法根据您正在处理的地图声明,或者您将获得ClassCastException
。
同样,这不是推荐的方式,但如果你需要,它可以工作。