对于相同类型的连接表,MyBatis多次包含相同的<sql>片段</sql>

时间:2014-01-03 23:15:58

标签: mybatis

更新2016-06-07 - 请参阅下面的解决方案

试图找出是否有办法在一个查询中重用相同的片段。

考虑一下:

<sql id="personFields">
    per.id                  person_id,
    per.created_at          person_created_at,
    per.email_address       person_email_address,
    per.first_name          person_first_name,
    per.last_name           person_last_name,
    per.middle_name         person_middle_name
</sql>

“per。”别名用于在使用多个连接表的查询中使用时避免列名冲突。 它包括在内:

SELECT
<include refid="com.acme.data.mapper.PersonMapper.personFields"/>
FROM Person per

问题是每个查询不能多次使用它,因为我们有“per”。别名。

拥有这样的东西会很棒:

<sql id="personFields">
    #{alias}.id                  #{alias}_person_id,
    #{alias}.created_at          #{alias}_person_created_at,
    #{alias}.email_address       #{alias}_person_email_address,
    #{alias}.first_name          #{alias}_person_first_name,
    #{alias}.last_name           #{alias}_person_last_name,
    #{alias}.middle_name         #{alias}_person_middle_name
</sql>

并将其包括在内:

SELECT
<include refid="com.acme.data.mapper.PersonMapper.personFields" alias="per1"/>,
<include refid="com.acme.data.mapper.PersonMapper.personFields" alias="per2"/>
FROM Person per1
JOIN Person per2 ON per2.parent_id = per1.id

3 个答案:

答案 0 :(得分:6)

这是目前可行的(不确定自哪个版本):

定义它:

<sql id="AddressFields">
    ${alias}.id                 ${prefix}id,
    ${alias}.created_at         ${prefix}created_at,
    ${alias}.street_address     ${prefix}street_address,
    ${alias}.street_address_two ${prefix}street_address_two,
    ${alias}.city               ${prefix}city,
    ${alias}.country            ${prefix}country,
    ${alias}.region             ${prefix}region,
    ${alias}.sub_region         ${prefix}sub_region,
    ${alias}.postal_code        ${prefix}postal_code
</sql>

选择它:

<sql id="PurchaseSelect">
SELECT
purchase.*,
<include refid="foo.bar.mapper.entity.AddressMapper.AddressFields">
    <property name="alias" value="billing_address"/>
    <property name="prefix" value="billing_address_"/>
</include>,
<include refid="foo.bar.mapper.entity.AddressMapper.AddressFields">
    <property name="alias" value="shipping_address"/>
    <property name="prefix" value="shipping_address_"/>
</include>
FROM purchase
LEFT JOIN address billing_address ON purchase.billing_address_id = billing_address.id
LEFT JOIN address shipping_address ON purchase.shipping_address_id = shipping_address.id

</sql>

映射:

<resultMap id="PurchaseResult" type="foo.bar.entity.sales.Purchase">    
    <id property="id" column="id"/>
    <!-- any other purchase fields -->
    <association property="billingAddress" columnPrefix="billing_address_" resultMap="foo.bar.mapper.entity.AddressMapper.AddressResult"/>
    <association property="shippingAddress" columnPrefix="shipping_address_" resultMap="foo.bar.mapper.entity.AddressMapper.AddressResult"/>    
</resultMap>

答案 1 :(得分:5)

很遗憾,你不能这样做,其他人已经尝试过(请参阅一些问题herehere)。包含内联并且不带参数。

我头顶的一个解决方案就是这样:

<sql id="fragment">
  <foreach collection="list" separator="," item="alias">
    ${alias}.id                  ${alias}_person_id,
    ${alias}.created_at          ${alias}_person_created_at,
    ${alias}.email_address       ${alias}_person_email_address,
    ${alias}.first_name          ${alias}_person_first_name,
    ${alias}.last_name           ${alias}_person_last_name,
    ${alias}.middle_name         ${alias}_person_middle_name
  </foreach>
</sql>

只包括一次:

<select id="getPersons" parameterType="java.util.List" ... >
  SELECT
  <include refid="fragment"/>
  FROM Person per1
  JOIN Person per2 ON per2.parent_id = per1.id
</select>

并从映射器界面发送parameterType="java.util.List"

public interface PersonMapper {
  public List<String> getPersons(List<String> aliases); 
  // called with aliases = ["per1", "per2"]
}

这很难看,因为你的(更高级别)代码必须知道(下层)查询中使用的别名,并且还使用字符串替换片段(${...}而不是#{...})如果处理不当会很危险......但如果你能忍受......

答案 2 :(得分:3)

此功能要求实施超过2年(https://code.google.com/p/mybatis/issues/detail?id=652)。

可以在此fork中找到include中的静态参数:https://github.com/kmoco2am/mybatis-3

它完全正常工作,它具有与标准配置参数或静态变量相同的语法:

<sql id="sometable">
  ${prefix}Table
</sql>

<select id="select" resultType="map">
    select 
        field1, field2, field3
    from
    <include refid="sometable">
        <placeholder name="prefix" value="Some"/>
    </include>
</select>

希望很快就会接受主要的源代码库。