Mybatis If语句使用include属性

时间:2016-02-08 05:30:18

标签: java postgresql mybatis dynamic-sql ognl

我正在尝试在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片段的属性?

3 个答案:

答案 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>