如何使用iBatis获取参数化查询-Spring
How to get parameterized query with 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
字段而不是 here 建议的 parameterMap
但没有成功。我不确定如何使用内联参数。
我正在使用 ibatis-sqlmap 2.3.0
和 spring-ibatis 2.0.8
。
您可能已经注意到,我对 iBatis 知之甚少。另外,我知道这很脏,我正在使用我不应该使用的 类,无需指出这一点。
感谢您的帮助。
我已经解决了这个问题,我想与未来可能遇到相同问题的读者分享解决方案。在这样做之前,请记住这不是您应该使用 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
方法将查询中的问号替换为对象数组。对于静态查询,您必须同时传递该数组,对于动态查询,您可以传递 Object
或 java.util.Map
,具体取决于映射语句的 parameterClass
。
这两种方法都使用显式子转换(我花了很多时间查看源代码来弄清楚如何使它像你想象的那样工作),所以你可能要注意调用正确的方法根据您正在处理的映射语句,否则您将得到 ClassCastException
.
同样,这不是推荐的方法,但如果您需要它,它会起作用。
我正在开发一个集成了 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
字段而不是 here 建议的 parameterMap
但没有成功。我不确定如何使用内联参数。
我正在使用 ibatis-sqlmap 2.3.0
和 spring-ibatis 2.0.8
。
您可能已经注意到,我对 iBatis 知之甚少。另外,我知道这很脏,我正在使用我不应该使用的 类,无需指出这一点。
感谢您的帮助。
我已经解决了这个问题,我想与未来可能遇到相同问题的读者分享解决方案。在这样做之前,请记住这不是您应该使用 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
方法将查询中的问号替换为对象数组。对于静态查询,您必须同时传递该数组,对于动态查询,您可以传递 Object
或 java.util.Map
,具体取决于映射语句的 parameterClass
。
这两种方法都使用显式子转换(我花了很多时间查看源代码来弄清楚如何使它像你想象的那样工作),所以你可能要注意调用正确的方法根据您正在处理的映射语句,否则您将得到 ClassCastException
.
同样,这不是推荐的方法,但如果您需要它,它会起作用。