MyBatis动态SQL

x33g5p2x  于2022-02-18 转载在 其他  
字(7.1k)|赞(0)|评价(0)|浏览(372)

MyBatis动态SQL

一、script

注解版下,使用动态SQL需要将sql语句包含在script标签里。

在 < script>< /script>内使用特殊符号,则使用java的转义字符,如 双引号"" 使用\"\" 代替

  1. <script></script>

二、< where>标签、< if>标签

if:通过判断动态拼接sql语句,一般用于判断查询条件

当查询语句的查询条件由于输入参数的不同而无法确切定义时,可以使用< where>标签对来包裹需要动态指定的SQL查询条件,而在< where>标签对中,可以使用< if test="…">条件来分情况设置SQL查询条件
当使用标签对包裹 if 条件语句时,将会忽略查询条件中的第一个and或or

  1. <!-- 查询用户信息 -->
  2. <select id="queryUserInfo" parameterType="com.mybatis.po.UserParam" resultType="com.mybatis.po.User">
  3. SELECT * FROM tb_user
  4. <where>
  5. <if test="userId > 0">
  6. and user_id = #{userId}
  7. </if>
  8. <if test="userName!= null and userName!=''">
  9. and user_name like '%${userName}%'
  10. </if>
  11. <if test="sex!=null and sex!=''">
  12. and sex = #{sex}
  13. </if>
  14. </where>
  15. </select>
  1. @Select({"<script>" +
  2. " select * from tb_user " +
  3. "<where>" +
  4. "<if test = 'userId != null and userId !=\"\" '> " +
  5. "and user_Id = #{userId} " +
  6. "</if>" +
  7. "<if test = 'userPassword != null and userPassword !=\"\" '> " +
  8. "and user_password like CONCAT('%',#{userPassword},'%')" +
  9. "</if>" +
  10. "</where>" +
  11. "</script>"})

三、< sql>片段

MyBatis提供了可以将复用性比较强的SQL语句封装成“SQL片段”,在需要使用该SQL片段的映射配置中声明一下,即可引入该SQL语句,声明SQL片段的格式如下:

  1. <sql id="query_user_where">
  2. <!-- 要复用的SQL语句 -->
  3. </sql>

例子:

  1. <!--用户查询条件SQL片段-->
  2. <sql id="query_user_where">
  3. <if test="userId>0">
  4. AND user_id = #{userId}
  5. </if>
  6. <if test="userName!=null and userName!=''">
  7. AND user_name like '%${userName}%'
  8. </if>
  9. <if test="sex!=null and sex!=''">
  10. AND sex = #{sex}
  11. </if>
  12. </sql>
  13. <!-- 查询用户信息 -->
  14. <select id="queryUserInfo" parameterType="com.mybatis.po.UserParam" resultType="com.mybatis.po.User">
  15. SELECT * FROM tb_user
  16. <where>
  17. <include refid="query_user_where"/>
  18. <!-- 这里可能还会引入其他的SQL片段 -->
  19. </where>
  20. </select>
  • id是SQL片段的唯一标识,是不可重复的
  • SQL片段是支持动态SQL语句的,但建议,在SQL片段中不要使用< where>标签,而是在调用的SQL方法中写< where>标签,因为该SQL方法可能还会引入其他的SQL片段,如果这些多个的SQL片段中都有< where>标签,那么会引起语句冲突。
  • SQL映射配置还可以引入外部Mapper文件中的SQL片段,只需要在refid属性填写的SQL片段的id前添加其所在Mapper文件的namespace信息即可(如:test.query_user_where)

四、< foreach>标签

< foreach>标签属性说明:

属性说明
index当迭代对象是数组,列表时,表示的是当前迭代的次数。
item当迭代对象是数组,列表时,表示的是当前迭代的元素。
collection当前遍历的对象。
open遍历的SQL以什么开头。
close遍历的SQL以什么结尾。
separator遍历完一次后,在末尾添加的字符等。

需求:

  1. SELECT * FROM tb_user WHERE user_id=2 OR user_id=4 OR user_id=5;
  2. -- 或者
  3. SELECT * FROM tb_user WHERE user_id IN (2,4,5);

案例:

  1. <!-- 使用foreach标签,拼接or语句 -->
  2. <sql id="query_user_or">
  3. <if test="ids!=null and ids.length>0">
  4. <foreach collection="ids" item="user_id" open="AND (" close=")" separator="OR">
  5. user_id=#{user_id}
  6. </foreach>
  7. </if>
  8. </sql>
  9. <!-- 使用foreach标签,拼接in语句 -->
  10. <sql id="query_user_in">
  11. <if test="ids!=null and ids.length>0">
  12. AND user_id IN
  13. <foreach collection="ids" item="user_id" open="(" close=")" separator=",">
  14. #{user_id}
  15. </foreach>
  16. </if>
  17. </sql>
  1. @Insert("<script>" +
  2. "insert into tb_user(user_id,user_account,user_password,blog_url,blog_remark) values" +
  3. "<foreach collection = 'list' item = 'item' index='index' separator=','>" +
  4. "(#{item.userId},#{item.userAccount},#{item.userPassword},#{item.blogUrl},#{item.blogRemark})" +
  5. "</foreach>" +
  6. "</script>")
  7. int insertByList(@Param("list") List<UserInfo> userInfoList);
  8. @Select("<script>" +
  9. "select * from tb_user" +
  10. " WHERE user_id IN " +
  11. "<foreach collection = 'list' item = 'id' index='index' open = '(' separator= ',' close = ')'>" +
  12. "#{id}" +
  13. "</foreach>" +
  14. "</script>")
  15. List<UserInfo> selectByList(@Param("list") List<Integer> ids);
  16. @Update({"<script>" +
  17. "<foreach item='item' collection='list' index='index' open='' close='' separator=';'>" +
  18. " UPDATE tb_user " +
  19. "<set>" +
  20. "<if test='item.userAccount != null'>user_account = #{item.userAccount},</if>" +
  21. "<if test='item.userPassword != null'>user_password=#{item.userPassword}</if>" +
  22. "</set>" +
  23. " WHERE user_id = #{item.userId} " +
  24. "</foreach>" +
  25. "</script>"})
  26. int updateBatch(@Param("list")List<UserInfo> userInfoList);

五、< choose>标签、< when>标签、< otherwise>标签

有时我们不想应用到所有的条件语句,而只想从中择其一项。针对这种情况,MyBatis提供了choose元素,它有点像Java中的switch语句。

  1. <select id="queryUserChoose" parameterType="com.mybatis.po.UserParam" resultType="com.mybatis.po.User">
  2. SELECT * FROM tb_user
  3. <where>
  4. <choose>
  5. <when test="userId>0">
  6. AND user_id = #{userId}
  7. </when>
  8. <when test="userName!=null and userName!=''">
  9. AND user_name like '%${userName}%'
  10. </when>
  11. <otherwise>
  12. AND sex = '女'
  13. </otherwise>
  14. </choose>
  15. </where>
  16. </select>
  1. @Select("<script>"
  2. + "select * from tb_user "
  3. + "<where>"
  4. + "<choose>"
  5. + "<when test='userId != null and userId != \"\"'>"
  6. + " and user_id = #{userId}"
  7. + "</when>"
  8. + "<otherwise test='userAccount != null and userAccount != \"\"'> "
  9. + " and user_account like CONCAT('%', #{userAccount}, '%')"
  10. + "</otherwise>"
  11. + "</choose>"
  12. + "</where>"
  13. + "</script>")
  14. List<UserInfo> selectAll(UserInfo userInfo);

六、< trim>标签、< set>标签

MyBatis还提供了< trim>标签,我们可以通过自定义< trim>标签来定制< where>标签的功能。比如,和< where>标签等价的自定义 < trim>标

prefixOverrides 属性会忽略通过管道分隔的文本序列(注意此例中的空格也是必要的)。它的作用是移除所有指定在 prefixOverrides 属性中的内容,并且插入 prefix 属性中指定的内容。

使用自定义< trim>标签来定制< where>标签的功能,获取用户信息:

  1. <!-- 查询用户信息 -->
  2. <select id="queryUserTrim" parameterType="com.mybatis.po.UserParam" resultType="com..mybatis.po.User">
  3. SELECT * FROM tb_user
  4. <trim prefix="WHERE" prefixOverrides="AND |OR ">
  5. <if test="userId>0">
  6. and user_id = #{userId}
  7. </if>
  8. <if test="userName!=null and userName!=''">
  9. and user_name like '%${userName}%'
  10. </if>
  11. <if test="sex!=null and sex!=''">
  12. and sex = #{sex}
  13. </if>
  14. </trim>
  15. </select>

在修改用户信息的SQL配置方法中,使用< set>标签过滤多余的逗号:

  1. <!-- 修改用户信息 -->
  2. <update id="updateUser" parameterType="com.pjb.mybatis.po.UserParam">
  3. UPDATE tb_user
  4. <set>
  5. <if test="userName != null">user_name=#{userName},</if>
  6. <if test="sex != null">sex=#{sex},</if>
  7. <if test="age >0 ">age=#{age},</if>
  8. <if test="blogUrl != null">blog_url=#{blogUrl}</if>
  9. </set>
  10. where user_id = #{userId}
  11. </update>

这里,< set>标签会动态前置SET关键字,同时也会删掉无关的逗号,因为用了条件语句之后很可能就会在生成的SQL语句的后面留下这些逗号。因为用的是“if”元素,若最后一个“if”没有匹配上而前面的匹配上,SQL 语句的最后就会有一个逗号遗留。

相关文章