SQL 片段的使用—— SQL 标签引用类型传参

390 阅读2分钟

SQL 片段的使用—— SQL 标签

MyBatis 的 Mapper.xml 提供了一些 SQL 标签,但是一般用 <if>、<foreach>、<set>、<where> 居多,偶尔用 <sql>、<include> 标签搭配引入公共的 SQL 片段。但是前段时间碰到了一大段 SQL 语句的编写,其中有很多是类似的,所以使用了 <sql> 标签,但是涉及到了一些判断之类的所以就在这里记录一下。

引用类型参数传递

Mapper 接口:

@Param("name") 注解就不再重复写了

List<Item> findItem(@Param("req") ParamValue req);

假设现在需要进行多表以上的复杂查询,其中会有以两张表的查询结果作为子查询的 sql 片段,并且可能会有另外的表基于这个 SQL 片段进行一些片段之类的。

这个时候为了避免写大量重复的片段条件,可以使用 <sql> + <include> 编写公共 SQL。

<!-- FL1 统计表 -->
<sql id="fL1">
    SELECT companyId, deptId, type, COUNT(*) num
    FROM table_1 A, table_3 B
    WHERE date &gt;= STR_TO_DATE(#{req.startDate}, '%Y%m%d')
    AND date &lt; STR_TO_DATE(#{req.endDate}, '%Y%m%d')
    <include refid="queryCriteria">
        <property name="req" value="req"/>
    </include>
</sql>

<!-- FL2 统计表 -->
<sql id="fL2">
    SELECT companyId, deptId, type, COUNT(*) num
    FROM table_2 A, table_3 B
    WHERE date &gt;= STR_TO_DATE(#{req.startDate}, '%Y%m%d')
    AND date &lt; STR_TO_DATE(#{req.endDate}, '%Y%m%d')
    <include refid="queryCriteria">
        <property name="req" value="req"/>
    </include>
</sql>

<!-- 公共的 sql 判断片段 -->
<sql id="queryCriteria">
    <if test="req.type == 'FL1'">
        AND A.PROJECT = B.CODE AND B.TYPE = 'FL1'
    </if>
    <if test="req.type == 'FL2'">
        AND A.INNOVATION = B.CODE AND B.TYPE = 'FL2'
    </if>
    <if test="req.companyId!=null and req.companyId!=''">
        AND A.companyId = #{req.companyId}
    </if>
    <if test="req.deptId!=null and req.deptId!=''">
        AND A.deptId = #{req.deptId}
    </if>
    GROUP BY companyId, A.deptId,
    <if test="req.type == 'FL1'">
        PROJECT
    </if>
    <if test="req.type == 'FL2'">
        INNOVATION
    </if>
</sql>

<!-- 查询语句 -->
<select>
    select ... from
    (<include refid="fL1">
    	<property name="req" value="req"/>
    </include>) as a
    left join 
    (<include refid="fL2">
    	<property name="req" value="req"/>
    </include>) as b
    ...
</select>

这里不需要关注具体 SQL 是啥,因为自己在找的时候网上资料也可能是自己没有搜索正确,所以没有看到 sql 标签关于引用类型的传递,只有多个基本类型和 String 传递(所以这里就没写了),而使用引用类型传递是,只需要将引用参数整体传入即可,如果是只传引用类型的单个属性例如传:

<include refid="fL1">
    <property name="type" value="req.type"/>
</include>

<if test="type == 'FL1'">
    AND A.PROJECT = B.CODE AND B.TYPE = 'FL1'
</if>

这种情况我自己是会报错的,找不到这个 type 参数,不知道是不是 value="req.type" 取值有问题,反正也没深究。

但是一般情况下只要传递了引用类型,那肯定参数起码也有3个以上,所以还是直接传整体算了...

好像貌似在 sql 判断中,取参时并不需要 ${},该怎么取还是怎么取,也可能是 MyBatis 版本不一样,具体也不清楚,反正用 #{} 取值 SQL 打印出来也是用占位符。

总结

能把 SQL 语句在不影响结果的情况下尽量简化,然后如果有公共部分可以在 Mapper.xml 进行抽象成 SQL 片段(即使是公共判断)

还是得学好 SQL!