Hei那里,我正在开发一个Primefaces应用程序,作为一个持久层,我选择了Mybatis。
这是常规sql在我的mapper中的样子:
<select id="getAllTransportUnit" resultMap="TransportUnitMap">
SELECT * FROM SSLS_GUI.VW_TU
<if test="( hasFilters == 'yes' ) and ( parameters != null )">
<where>
<foreach item="clause" collection="parameters" separator=" AND "
open="(" close=")">
UPPER(${clause.column}) ${clause.operator} #{clause.value}
</foreach>
</where>
</if>
<if test="sort == 'true'">
ORDER BY ${sortField}
<if test="sortOrder == 'DESC'"> DESC</if>
<if test="sortOder == 'ASC'"> ASC</if>
</if>
</select>
我的几乎所有查询都使用从<if test...>
开始的动态sql部分。是否可以将它放在一个单独的文件中,然后在我的查询中重复使用它?
答案 0 :(得分:10)
如何重用sql片段有几种选择。
第一个使用include
。创建单独的映射器Common.xml:
<mapper namespace="com.company.project.common">
<sql id="orderBy>
<if test="sort == 'true'">
ORDER BY ${sortField}
<if test="sortOrder == 'DESC'"> DESC</if>
<if test="sortOder == 'ASC'"> ASC</if>
</if>
</sql>
<sql id="filters">
<if test="( hasFilters == 'yes' ) and ( parameters != null )">
<where>
<foreach item="clause" collection="parameters" separator=" AND "
open="(" close=")">
UPPER(${clause.column}) ${clause.operator} #{clause.value}
</foreach>
</where>
</if>
</sql>
</mapper>
并在其他地图制作工具MyMapper.xml
中使用它:
<select id="getAllTransportUnit" resultMap="TransportUnitMap">
SELECT * FROM SSLS_GUI.VW_TU
<include refid="com.company.project.common.filters"/>
<include refid="com.company.project.common.orderBy"/>
</select>
为避免在每个包含中复制命名空间,您可以在MyMapper.xml
中创建快捷方式摘要:
<sql id="orderBy">
<include refid="com.company.project.common.orderBy"/>
</sql>
<select id="getAllTransportUnit" resultMap="TransportUnitMap">
SELECT * FROM SSLS_GUI.VW_TU
<include refid="orderBy"/>
</select>
另一种可能的选择是使用mybatis scripting。使用mybatis-velocity脚本引擎,您可以定义速度宏并重复使用它。
在Commons.xml
:
<sql id="macros"
#macro(filters)
#if ( $_parameter.hasFilters )
#repeat( $_parameter.parameters $clause "AND" " (" ")" )
${clause.column} ${clause.operator} @{clause.value}
#end
#end
#end
#macro(order_by)
..
#end
</sql>
在MyMapper.xml
:
<select id="getAllTransportUnit" resultMap="TransportUnitMap">
<include refid="macros"/>
SELECT * FROM SSLS_GUI.VW_TU
#filters()
#order_by()
</select>
通过sql代码段包含宏并不是重用宏的最简洁方法。这只是一个想法如何使用它。
更好的选择是配置mybatis-velocity并指定可用的全局宏。在这种情况下,不需要包含macros
代码段,结果查询将是这样的:
<select id="getAllTransportUnit" resultMap="TransportUnitMap">
SELECT * FROM SSLS_GUI.VW_TU
#filters()
#order_by()
</select>
答案 1 :(得分:1)
请参阅@Roman Konoval关于如何在XML中执行此操作的答案。
对于纯Java方面的另一个选项(在OP的情况下,上面的XML选项更适用;我在这里留给那些可能使用纯Java的人),可以使用Mybatis'Statement Builders,允许构建与 Java 代码内联的动态 SQL ,您可以将那里的公共代码分解为类似于分解任何公共代码的方式。
他们在 Mybatis doc中提供的示例如下:
private String selectPersonSql() {
return new SQL() {{
SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME");
SELECT("P.LAST_NAME, P.CREATED_ON, P.UPDATED_ON");
FROM("PERSON P");
FROM("ACCOUNT A");
INNER_JOIN("DEPARTMENT D on D.ID = P.DEPARTMENT_ID");
INNER_JOIN("COMPANY C on D.COMPANY_ID = C.ID");
WHERE("P.ID = A.ID");
WHERE("P.FIRST_NAME like ?");
OR();
WHERE("P.LAST_NAME like ?");
GROUP_BY("P.ID");
HAVING("P.LAST_NAME like ?");
OR();
HAVING("P.FIRST_NAME like ?");
ORDER_BY("P.ID");
ORDER_BY("P.FULL_NAME");
}}.toString();
}
因此,您可以定义一个函数,该函数将XML中的commmon动态 SQL 分解出来,并且可能会使用表示SELECT
列和FROM
表部分的参数。语句(以及可能有所不同的任何其他内容),然后可以将其传递给函数内部的动态 SQL 方法。