我正在尝试在Mybatis中创建一个通用SQL包含,它将应用给定特定值的比较器。我们的想法是在几个映射器中重用这个sql代码段。我遇到的问题是在我的include中的if语句中使用字符串替换。
目前xml看起来像这样:
<select id="get" parameterType="ServiceModelQueryHelper" resultMap="ServiceRecordMap">
SELECT * from service
<if test="name.isApplicable()">
WHERE service.name
<include refid=comparatorMapper>
<property name="comparator" value="${name.comparator}"/>
<property name="value" value="${name.value}"/>
</include>
</if>
</select>
<sql id="comparatorMapper">
<if test="${comparator} == 'EQUALS'">
= ${value}
</if>
<if test="${comparator} == 'CONTAINS'">
~ ${value}
</if>
</sql>
在测试中使用$ {comparator}时,会在字符串替换发生之前评估OGNL表达式,从而导致ParseException,因为$不是有效的第一个字符。
有没有办法在OGNL表达式中引用sql片段的属性?
答案 0 :(得分:0)
看看mybatis docs。条件语句不需要#,$样式引用。
答案 1 :(得分:0)
我发现了一种肮脏的方式来完成这项工作:
在ServiceModelQueryHelper中添加一个包含参数的对象,然后可以在if语句中设置参数
前:
public class ServiceModelQueryHelper {
private ContainerForGenericSql containerForGenericSql = new ContainerForGenericSql();
...
}
public class ContainerForGenericSql {
private String parameterForGenericSql;
public String getParameterForGenericSql() {
return parameterForGenericSql;
}
public void setParameterForGenericSql(
String parameterForGenericSql) {
this.parameterForGenericSql = parameterForGenericSql;
}
public boolean setParameterForGenericSqlAndReturnTrue(
String parameterForGenericSql) {
this.parameterForGenericSql = parameterForGenericSql;
return true;
}
}
<select id="get" parameterType="ServiceModelQueryHelper" resultMap="ServiceRecordMap">
SELECT * from service
<if test="name.isApplicable()">
WHERE service.name
<if test="containerForGenericSql.setParameterForGenericSqlAndReturnTrue(name.comparator)">
</if>
<include refid=comparatorMapper>
<property name="value" value="${name.value}"/>
</include>
</if>
</select>
<sql id="comparatorMapper">
<if test="containerForGenericSql.parameterForGenericSql == 'EQUALS'">
= ${value}
</if>
<if test="containerForGenericSql.parameterForGenericSql == 'CONTAINS'">
~ ${value}
</if>
</sql>
parameterForGenericSql也可以是复杂类型,您可以在IF语句中使用它,它也可以是一个可以在FOREACH语句中使用的列表。
这是我发现创建通用SQL包含的唯一方法,它可以使用IF和FOREACH中的参数
答案 2 :(得分:0)
哈哈,我现在有同样的问题,但是我找到了解决方法。
那就是使用bind
。我知道我不再可以用这种方式打电话给property
。
<bind name="isGetList" value='"1"' />
<include refid="conditionSql" />
<sql id="conditionSql">
<if test='isGetList == "1"'>
for example.
</if>
</sql>