mybatis 动态sql
spring 集成mybatis 不得不说省了很大一部分拼写sql的烦恼。此处记录一下我用到的mybatis强大的动态语句
- if
- choose
- foreach
- trim
if
<select id="selectAnswerByCondition" parameterType="..Answer" resultMap="answerMapper">
<include refid="selectColumn"/>
<where>
valid ='1'
<if test="answerId != null ">AND ans_id = #{answerId}</if>
<if test="studentId != null ">AND stu_id = #{studentId}</if>
<if test="jobId != null">AND job_id = #{jobId}</if>
</where>
</select>
注意此处where里必须保证有一个条件命中,比如我在这里加了一个valid=1
choose
<select id="selectBetweenTimes" parameterType="..Query"
resultMap="BaseResultMap">
SELECT
<include refid="searchSql"/>
FROM third_platform_mapping
WHERE create_time <![CDATA[ < ]]> #{endTime} AND
create_time <![CDATA[ > ]]> #{startTime} AND
is_auth = 1
ORDER BY create_time ASC
<choose>
<when test="pageSize > 1000 ">
limit #{startIndex},1000
</when>
<when test="pageSize == 0">
limit #{startIndex}, 1
</when>
<otherwise>
limit #{startIndex}, #{pageSize}
</otherwise>
</choose>
</select>
choose的好处就是必然会匹配一个条件
foreach
<select id="selectBatch" parameterType="java.util.List" resultMap="ClassStartMapper">
<include refid="selectColumn"/>
<where>
class_id in
<foreach collection="classIds" item="item" index="index"
open="(" separator="," close=")">#{item}
</foreach>
</where>
</select>
这里使用foreach 对集合进行遍历,使用in构建条件
<insert id="insertSubscribeBatch" parameterType="java.util.List">
INSERT INTO s_m
(id,third_id,customer_id,authorizer_id,subscribe,create_time, op_time)
VALUES
<foreach collection="subscribeMappings" item="subscribe" separator=",">
(
#{subscribe.id},
#{subscribe.thirdOpenId},
#{subscribe.customerRegisterId},
#{subscribe.authorizerAppId},
#{subscribe.subscribe},
#{subscribe.createTime},
#{subscribe.opTime}
)
</foreach>
<![CDATA[ ON DUPLICATE KEY UPDATE ]]> subscribe= #{subscribe.subscribe},op_time=#{subscribe.opTime}
</insert>
这条sql的意思是批量插入数据,如果存在主键或者复合主键冲突的情况就做更新操作。
还有一个防止主键冲突的语句是 insert ignore ,这两天语句可以避免因为主键冲突报异常。
trim
<update id="select" parameterType="ReplaceBeanName" >
SELECT * from s_m
<trim prefix="where" suffixOverrides="AND | OR">
<if test="name !=null"> name = #{name} AND </if>
<if test="thirdId != null"> third_id = #{thirId}</if>
</trim>
</update>
trim 可以自定义元素来满足我们想要的功能,并且如果条件未命中,会移除以suffixOverrides值的结尾。或者以prefixOverrides值的开头。
比如上条sql,如果用where 元素第二条条件没有命中,sql 就会多一and 很尴尬的语法错误,但是你有不能保证别人传过来的100%都有值。但是trim 会在有条件的情况下才会插入where,而且如果最后是and 或者or ,where 会将他们去除。
等价于if 示例。
当然,MyBatis 从 3.2 开始支持可插拔的脚本语言,因此你可以在插入一种语言的驱动(language driver)之后来写基于这种语言的动态 SQL 查询。有兴趣再研究下。