Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MyBatis include same <sql> fragment multiple times for joined tables of same type

Tags:

mybatis

Update 2016-06-07 - see my answer below for solution

Trying to find out if there is a way to reuse same fragment in one query.

Consider this:

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

The "per." alias is used to avoid column name clashing when using in queries with muiltiple joined tables. It is included like this:

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

The problem is that it cannot be used more than once per query because we have the "per." alias.

Would be great to have something like this:

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

And include it like this:

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
like image 305
Vitali Carbivnicii Avatar asked Dec 04 '22 08:12

Vitali Carbivnicii


1 Answers

This is currently possible (not sure since what version):

Define it:

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

Select it:

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

Map it:

<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>
like image 113
Vitali Carbivnicii Avatar answered Jan 31 '23 07:01

Vitali Carbivnicii