Mybatis之动态SQL
mybatis 的动态sql语句是基于OGNL表达式的。可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类:
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
if
动态 SQL 通常要做的事情是有条件地包含 where 子句的一部分。
1 <select id="selectUserByOrgid" resultType="java.util.HashMap"> 2 select username,password from sys_user where org_id = #{orgid,jdbcType=VARCHAR} 3 <if test="orderFiled != null" > 4 order by ${orderFiled} 5 <if test="orderSort != null" > 6 ${orderSort} 7 </if> 8 </if> 9 </select>
choose, when, otherwise
有些时候,我们不想用到所有的条件语句,而只想从中择其一二。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
1 <select id="selectByUsernameORorg" parameterType="java.lang.String" resultMap="BaseResultExtMap"> 2 select 3 <include refid="Base_Ext_Column_List" /> 4 from sys_user 5 where 6 <choose> 7 <when test="username != null"> 8 AND username like#{username,jdbcType=VARCHAR} 9 </when> 10 <when test="name != null "> 11 AND name like #{name,jdbcType=VARCHAR} 12 </when> 13 <otherwise> 14 AND org_id =#{orgid,jdbcType=VARCHAR} 15 </otherwise> 16 </choose> 17 </select>
trim, where, set
前面几个例子已经合宜地解决了一个臭名昭著的动态 SQL 问题。为了解决前面SQL可能出现的问题,就是使用where标签改写。where标签非常智能。如果标签内部没有合适的语句,where标签就不会生成任何东西,防止出现错误语句。
1 <select id="selectByUsernameORorg2" parameterType="java.lang.String" resultMap="BaseResultExtMap"> 2 select 3 <include refid="Base_Ext_Column_List" /> 4 from sys_user 5 <where> 6 <if test="name != null"> 7 name = #{name,jdbcType=VARCHAR} 8 </if> 9 <if test="username != null"> 10 AND username like #{username,jdbcType=VARCHAR} 11 </if> 12 </where> 13 </select>
有时候where标签还不能满足需求。这时候还可以使用trim标签进行更高级的定制。trim标签中的prefix和suffix属性会被用于生成实际的SQL语句,会和标签内部的语句拼接。如果语句的前面或后面遇到prefixOverrides或suffixOverrides属性中指定的值,MyBatis会自动将它们删除。在指定多个值的时候,别忘了每个值后面都要有一个空格,保证不会和后面的SQL连接在一起。下面这个例子和where标签完全等效。
1 <trim prefix="WHERE" prefixOverrides="AND |OR "> 2 ... 3 </trim>
类似的用于动态更新语句的解决方案叫做 set。set 元素可以被用于动态包含需要更新的列,而舍去其他的。
1 <update id="updateByPrimaryKeySelective" parameterType="com.goku.mybatis.model.sysUser"> 2 <!-- 3 WARNING - @mbg.generated 4 This element is automatically generated by MyBatis Generator, do not modify. 5 --> 6 update sys_user 7 <set> 8 <if test="username != null"> 9 username = #{username,jdbcType=VARCHAR}, 10 </if> 11 <if test="password != null"> 12 password = #{password,jdbcType=VARCHAR}, 13 </if> 14 <if test="name != null"> 15 name = #{name,jdbcType=VARCHAR}, 16 </if> 17 <if test="sex != null"> 18 sex = #{sex,jdbcType=VARCHAR}, 19 </if> 20 <if test="status != null"> 21 status = #{status,jdbcType=CHAR}, 22 </if> 23 <if test="orgId != null"> 24 org_id = #{orgId,jdbcType=VARCHAR}, 25 </if> 26 <if test="email != null"> 27 email = #{email,jdbcType=VARCHAR}, 28 </if> 29 <if test="idcard != null"> 30 idcard = #{idcard,jdbcType=VARCHAR}, 31 </if> 32 <if test="isAdmin != null"> 33 is_admin = #{isAdmin,jdbcType=VARCHAR}, 34 </if> 35 <if test="sort != null"> 36 sort = #{sort,jdbcType=BIGINT}, 37 </if> 38 <if test="mobile != null"> 39 mobile = #{mobile,jdbcType=VARCHAR}, 40 </if> 41 <if test="stationid != null"> 42 stationid = #{stationid,jdbcType=LONGVARCHAR}, 43 </if> 44 </set> 45 where id = #{id,jdbcType=VARCHAR} 46 </update>
这里,set 元素会动态前置 SET 关键字,同时也会消除无关的逗号,因为用了条件语句之后很可能就会在生成的赋值语句的后面留下这些逗号。
若你对等价的自定义 trim 元素的样子感兴趣,那这就应该是它的真面目:
1 <trim prefix="SET" suffixOverrides=","> 2 ... 3 </trim>
foreach
动态 SQL 的另外一个常用的必要操作是需要对一个集合进行遍历,通常是在构建 IN 条件语句的时候
1 <select id="selectUserByOrgid2" resultType="java.util.HashMap"> 2 select username,password from sys_user where org_id IN 3 <foreach item="item" index="index" collection="list" 4 open="(" separator="," close=")"> 5 #{item} 6 </foreach> 7 </select>
bind
bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。
1 <select id="selectByUsername2" parameterType="java.lang.String" resultMap="BaseResultExtMap"> 2 <bind name="username" value="'%' + username + '%'" /> 3 select 4 <include refid="Base_Ext_Column_List" /> 5 from sys_user 6 where username LIKE #{username} 7 </select>
GITHUB
github : https://github.com/nbfujx/learn-java-demo/tree/master/Goku.MybatisDemo.XML