九点钟☆方向

记录成长点滴

欢迎来到我的个人博客~


Mybatis笔记(七) Mybatis动态SQL语句

目录

if标签

我们根据实体类的不同取值,使用不同的 SQL 语句来进行查询。比如在 id 如果不为空时可以根据 id 查询,如果 username 不同空时还要加入用户名作为条件。这种情况在我们的多条件组合查询中经常会碰到。

  1. 持久层 Dao 接口

    /**
    * 根据用户信息,查询用户列表
    * @param user
    * @return
    */
    List<User> findByUser(User user);
    
  2. 持久层 Dao 映射配置

    <select id="findByUser" resultType="user" parameterType="user">
    	select * from user where 1=1
        <!-- test中条件关系要写and   不能写&&-->
        <if test="username!=null and username != '' ">
        	and username like #{username}
        </if>
        <if test="address != null">
        	and address like #{address}
        </if>
    </select>
    注意: <if>标签的 test 属性中写的是对象的属性名,如果是包装类的对象要使用 OGNL 表达式的写法。
        另外要注意 where 1=1 的作用:保证有where,确保SQL语句正确
    

where标签

为了简化上面 where 1=1 的条件拼装,我们可以采用where标签来简化开发 。标签会将用到的第一个条件的and或or去掉

持久层Dao映射配置

<!-- 根据用户信息查询 -->
<select id="findByUser" resultType="user" parameterType="user">
    select * from user
    <where>
        <if test="username!=null and username != '' ">
            and username like #{username}
        </if>
        <if test="address != null">
            and address like #{address}
        </if>
    </where>
</select>

foreach标签

传入多个 id 查询用户信息,用下边两个 sql 实现: SELECT * FROM USERS WHERE username LIKE ‘%张%’ AND (id =10 OR id =89 OR id=16) SELECT * FROM USERS WHERE username LIKE ‘%张%’ AND id IN (10,89,16) 这样我们在进行范围查询时,就要将一个集合中的值,作为参数动态添加进来。 这样我们将如何进行参数的传递?

第一种方式:

  1. 在 QueryVo 中加入一个 List 集合用于封装参数

    /**
    *
    * <p>Title: QueryVo</p>
    * <p>Description: 查询的条件</p>
    * <p>Company: http://www.itheima.com/ </p>
    */
    public class QueryVo implements Serializable {
    	private List<Integer> ids;
        //生成set/get
    }
    
  2. 持久层 Dao 接口

    /**
    * 根据 id 集合查询用户
    * @param vo
    * @return
    */
    List<User> findInIds(QueryVo vo);
    
  3. 持久层DAO映射配置

    <!-- 查询所有用户在 id 的集合之中 -->
    <select id="findInIds" resultType="user" parameterType="queryvo">
    	select * from user
    	<where>
            <if test="ids != null and ids.size() > 0">
                <foreach collection="ids" open="id in ( " close=")" item="uid" separator=",">
                    #{uid}
                </foreach>
            </if>
        </where>
    </select>
       
    上面生成的SQL 语句是:
    select * from user where id in (XX,XX,XX); 
       
    <foreach>标签用于遍历集合,它的属性:
    collection:代表要遍历的集合元素,注意编写时不要写#{}
    open:代表语句的开始部分
    close:代表结束部分
    item:代表遍历集合的每个元素,生成的变量名
    sperator:代表分隔符
    

第二种方式:

  1. 持久层dao接口

    /**
    * 根据 id 集合查询用户
    * @param vo
    * @return
    */
    //接收一个List参数
    List<User> findInIds(List<String> ids);
       
    //或者用@Param注解标注,配置文件中的collection属性就要写注解的名称
    //List<User> findInIds(@Param("userIds") List<String> ids);
    
  2. 持久层dao映射配置

    <select id="findInIds" parameterType="String" resultType="user">
        select * from user where id in
        <foreach collection="list" open="(" close=")" item="uid" separator=",">
            #{uid}
        </foreach>
           
        <!--
        <foreach collection="userIds" open="(" close=")" item="uid" separator=",">
            #{uid}
        </foreach>
    	-->
    </select>
       
    如果参数是一个数组或者集合,collection属性要写相应的类型list,map,array
    或者在形参上用@Param注解指定参数的名字,collection属性就要写指定的名字
    

SQL片段

Sql 中可将重复的 sql 提取出来,使用时用 include 引用即可,最终达到 sql 重用的目的

  1. 定义代码片段

    <!-- 抽取重复的语句代码片段 -->
    <sql id="defaultSql">
    	select * from user
    </sql>
    
  2. 引用代码片段

    <!-- 配置查询所有操作 -->
    <select id="findAll" resultType="user">
    	<include refid="defaultSql"></include>
    </select>
       
    <!-- 根据 id 查询 -->
    <select id="findById" resultType="UsEr" parameterType="int">
        <include refid="defaultSql"></include>
    	where id = #{uid}
    </select>
    

Set标签

动态配置set关键字,并剔除追加到条件末尾任何不相关的逗号,使用if+set标签修改后,在进行表单更新操作中,当字段有值时才更新,如果为null,则不更新保持数据库原值

  1. 持久层dao接口

    void updateUser(User user);
    
  2. 持久层dao映射配置

    <update id="updateUser" parameterType="user">
        update user
        <set>
            <if test="username != null and username!=''">
                username=#{username},
            </if>
            <if test="address!=null and address!=''">
                address=#{address},
            </if>
        </set>
        where id=1
    </update>
    

trim标签

trim 是一个格式化标签,可以完成< set > 或者是 < where > 标记的功能主要有4个参数: ① prefix:在trim标签内sql语句加上前缀

② prefixOverrides:指定去除多余的前缀内容。如:prefixOverrides=”and or” 指 去掉多余的and或者是or

③ suffix:在trim标签内sql语句加上后缀

④ suffixOverrides:指定去除多余的后缀内容。如:suffixOverrides=“,” 指去掉最后一个逗号

  1. 替换where

    <select id="findUserByCondition" parameterType="user" resultType="user">
        select * from user
        <trim prefix="where" prefixOverrides="and | or">
            <if test="username != null and username!=''">
                and username=#{username}
            </if>
        </trim>
    </select>
    如果username不为空,则生成的sql语句为:
    select * from user where username="XXX"  username前面的and会自动去掉
    
  2. 替换update

    <update id="updateUser" parameterType="user">
        update user
        <trim prefix="set" suffixOverrides=",">
            <if test="username != null and username!=''">
                username=#{username},
            </if>
            <if test="address!=null and address!=''">
                address=#{address},
            </if>
        </trim>
        where id=#{id}
    </update>
    如果username不为空,address为空,则生成的sql语句为:
    update user set username="XXX" where id="XXX"    username后面的逗号会自动去掉
    

choose、when、otherwise 标签

这三个标签需要组合在一起使用,类似于 Java 中的 switch、case、default。只有一个条件生效,也就是只执行满足的条件 when,没有满足的条件就执行 otherwise,表示默认条件。

  1. 持久层dao接口

    List<User> findUser1(@Param("username") String username,
                         @Param("address") String address,
                         @Param("id") String id);
    
  2. 持久层dao映射配置

    <select id="findUser1" resultType="user">
        select * from user
        <where>
            <choose>
                <when test="username!=null and username!=''">
                    and username=#{username}
                </when>
                <when test="address!=null and address!=''">
                    and address=#{address}
                </when>
                <otherwise>
                    and id=#{id}
                </otherwise>
            </choose>
        </where>
    </select>
       
    此时即使username和address的值都不为空,那么sql也只会添加username的值
    

bind标签

bind标签可以使用OGNL表达式创建一个变量并将其绑定到上下文中。比如由于数据库不同,语法上会存在差异,更换数据库时部分sql语句需要修改,此时使用bind即可解决,也能防止SQL注入

<if test="username!=null and username!=''">
    <!-- concat:mysql的连接字符串函数,不同的数据库不同-->
	and username like concat('%',#{username},"%")
</if>

可以使用 bind标签改造
<if test="username!=null and username!=''">
    <bind name="userNameLike" value="'%' + userName + '%'"/>
    and username like #{userNameLike}
</if>

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦