【问题标题】:Mybatis If statements using include propertiesMybatis If 语句使用包含属性
【发布时间】:2016-05-17 17:12:27
【问题描述】:

我正在尝试在 Mybatis 中创建一个通用 SQL 包含,它将应用给定特定值的比较器。这个想法是在多个映射器中重用这个 sql 代码 sn-p。我遇到的问题是在我的 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 sn-p 的属性?

【问题讨论】:

  • 我认为您应该使用参数标记#{comparator} 而不是字符串替换。
  • 我尝试使用 #{comparator} 但这使得 mybatis 在父查询中的 ServiceModelQueryHelper 上查找比较器字段,而不是在传递给 include 语句的对象上

标签: java postgresql mybatis dynamic-sql ognl


【解决方案1】:

哈哈,我现在也有同样的问题,但我找到了方法。
即使用bind。我知道我不能再用那种方式打电话给property。

<bind name="isGetList" value='"1"' />
<include refid="conditionSql" />

<sql id="conditionSql">
    <if test='isGetList == "1"'>
        for example.
    </if>
</sql>

【讨论】:

    【解决方案2】:

    我发现了一种肮脏的工作方式:

    您在 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 语句中使用。

    这是我发现创建可以在 IF 和 FOREACH 中使用参数的通用 SQL 包含的唯一方法

    【讨论】:

      【解决方案3】:

      看看mybatis docs。条件语句不需要 #,$ 样式引用。

      【讨论】:

      • 我知道条件语句不需要样式引用,但是要在包含中使用传入的属性,您需要使用 $ 表示法。不使用这些符号会导致查询再次查看父对象,我认为这违背了传递属性的目的(如果你想在包含中使用动态 sql)
      猜你喜欢
      • 2013-06-20
      • 1970-01-01
      • 1970-01-01
      • 2020-12-06
      • 1970-01-01
      • 2013-03-09
      • 1970-01-01
      • 1970-01-01
      • 2013-10-18
      相关资源
      最近更新 更多