Mybatis动态SQL

本文详细介绍了MyBatis中几种动态SQL标签的使用。包括if标签用于多条件查询,where标签让where子句更智能,trim标签可添加或删除前后缀,set标签用于update语句,choose标签类似if-else语句。通过示例展示了各标签的功能及使用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


一、if标签

需求:多条件查询
可能的条件包括:品牌(brand)、指导价格(guide_price)、汽车类型(car_type)
接口

/**
     * 多条件查询
     * @param brand
     * @param guidePrice
     * @param carType
     * @return
     */
    List<Car> selectByMultiCondition(@Param("brand")String brand,@Param("guidePrice") Double guidePrice,@Param("carType") String carType);

mapper.xml:
1、if标签中test属性是必须的
2、if标签中test属性的值是false或者true
3、如果test是true,则if标签中的sql语句就会拼接,反之则不会
4、test属性中可以使用的是:
* 当使用了@Param注解,那么test中要出现的是@Param注解指定的参数名。@Param(“brand”),那么这里只能使用brand
*当没有使用@Param注解,那么test中要出现的是:param1 param2 param3 arg0 arg1 arg2
*当使用了POJO,那么test中要出现的是POJO类的属性名
5、在mybatis的动态SQL当中,不能使用&& 只能使用and

<select id="selectByMultiCondition" resultType="car">
    select * from t_car where
    <!--
        1、if标签中test属性是必须的
        2、if标签中test属性的值是false或者true
        3、如果test是true,则if标签中的sql语句就会拼接,反之则不会
        4、test属性中可以使用的是:
            当使用了@Param注解,那么test中要出现的是@Param注解指定的参数名。@Param("brand"),那么这里只能使用brand
            当没有使用@Param注解,那么test中要出现的是:param1 param2 param3 arg0 arg1 arg2
            当使用了POJO,那么test中要出现的是POJO类的属性名
        5、在mybatis的动态SQL当中,不能使用&& 只能使用and
    -->
    <if test="brand != null and brand != ''">
        brand like "%"#{brand}"%"
    </if>
    <if test="guidePrice != null and guidePrice != ''">
        and guide_price > #{guidePrice}
    </if>
    <if test="carType != null and carType != ''">
        and car_type = #{carType}
    </if>
</select>

测试:

@Test
    public void testSelectByMultiCondition() throws IOException {
        SqlSession session = SqlSessionUtil.openSession();
        CarMapper mapper = session.getMapper(CarMapper.class);
        //假设三个条件都不是空
        //List<Car> cars = mapper.selectByMultiCondition("川",10.0,"能能源");

        //假设三个条件都是空
        //List<Car> cars = mapper.selectByMultiCondition("",null,"");

        //假设后两个条件不是空,第一个条件是空
        //List<Car> cars = mapper.selectByMultiCondition("",10.0,"能能源");

        //假设第一个条件不是空,后两个条件是空
        List<Car> cars = mapper.selectByMultiCondition("川",null,"");
        cars.forEach(car -> {
            System.out.println(car);
        });
        session.close();
    }

运行结果:
1、假设三个条件都不为空
在这里插入图片描述
2、假设三个条件都为空
在这里插入图片描述
SQL语句语法报错,当三个条件都为null时:select * from t_car where…
where 多余了不符合规定,解决方法:where 1=1 查询所有结果。
在这里插入图片描述
3、假设后两个条件不是空,第一个条件是空
在这里插入图片描述
4、假设第一个条件不是空,后两个条件是空
有语法问题:少一个and,加上去
在这里插入图片描述
有语法问题:少一个and,加上去
在这里插入图片描述
最终的mapper.xml文件:

<select id="selectByMultiCondition" resultType="car">
    select * from t_car where 1=1
    <!--
        1、if标签中test属性是必须的
        2、if标签中test属性的值是false或者true
        3、如果test是true,则if标签中的sql语句就会拼接,反之则不会
        4、test属性中可以使用的是:
            当使用了@Param注解,那么test中要出现的是@Param注解指定的参数名。@Param("brand"),那么这里只能使用brand
            当没有使用@Param注解,那么test中要出现的是:param1 param2 param3 arg0 arg1 arg2
            当使用了POJO,那么test中要出现的是POJO类的属性名
        5、在mybatis的动态SQL当中,不能使用&& 只能使用and
    -->
    <if test="brand != null and brand != ''">
        and brand like "%"#{brand}"%"
    </if>
    <if test="guidePrice != null and guidePrice != ''">
        and guide_price > #{guidePrice}
    </if>
    <if test="carType != null and carType != ''">
        and car_type = #{carType}
    </if>
</select>

二、where标签

where标签的作用:让where子句更加智能
*所有条件都为空时,where标签保证不会生成where子句
*自动去除某些条件前面多余的and或or。
接口

  /**
     * 多条件查询
     * @param brand
     * @param guidePrice
     * @param carType
     * @return
     */
    List<Car> selectByMultiConditionWithWhere(@Param("brand")String brand,@Param("guidePrice") Double guidePrice,@Param("carType") String carType);

mapper.xml

<select id="selectByMultiConditionWithWhere"  resultType="car">
    select * from t_car
    <!--where标签是专门负责where子句动态生成的-->
    <where>
        <if test="brand != null and brand != ''">
            brand like "%"#{brand}"%"
        </if>
        <if test="guidePrice != null and guidePrice != ''">
            and guide_price > #{guidePrice}
        </if>
        <if test="carType != null and carType != ''">
            and car_type = #{carType}
        </if>
    </where>
</select>

测试

@Test
    public void testSelectByMultiConditionWithWhere() throws IOException {
        SqlSession session = SqlSessionUtil.openSession();
        CarMapper mapper = session.getMapper(CarMapper.class);
        //假设三个条件都不是空
        //List<Car> cars = mapper.selectByMultiConditionWithWhere("川",10.0,"能能源");

        //假设三个条件都是空
        List<Car> cars = mapper.selectByMultiConditionWithWhere("",null,"");

        //假设后两个条件不是空,第一个条件是空
        //List<Car> cars = mapper.selectByMultiConditionWithWhere("",10.0,"能能源");

        //假设第一个条件不是空,后两个条件是空
        //List<Car> cars = mapper.selectByMultiConditionWithWhere("川",null,"");
        cars.forEach(car -> {
            System.out.println(car);
        });
        session.close();
    }

运行结果
四种情况都可正常执行。

三、trim标签

接口

  /**
     * 多条件查询 使用trim标签
     * @param brand
     * @param guidePrice
     * @param carType
     * @return
     */
    List<Car> selectByMultiConditionWithTrim(@Param("brand")String brand,@Param("guidePrice") Double guidePrice,@Param("carType") String carType);

mapper.xml
trim标签:
*prefix:加前缀
*suffix:加后缀
*prefixOverrides:删除前缀
*suffixOverrides:删除后缀

    <select id="selectByMultiConditionWithTrim"  resultType="car">
        select * from t_car
        <!--where标签是专门负责where子句动态生成的-->
        <trim prefix="where" suffixOverrides="and|or">
            <if test="brand != null and brand != ''">
                brand like "%"#{brand}"%" and
            </if>
            <if test="guidePrice != null and guidePrice != ''">
                guide_price > #{guidePrice} and
            </if>
            <if test="carType != null and carType != ''">
                and car_type = #{carType}
            </if>
            </trim>
    </select>

< trim prefix=“where” suffixOverrides=“and|or”></ trim>意思包含在trim标签里所有内容的前边加上前缀where,并且去掉trim标签里的后缀and或or。

测试

@Test
    @Test
    public void testSelectByMultiConditionWithTrim() throws IOException {
        SqlSession session = SqlSessionUtil.openSession();
        CarMapper mapper = session.getMapper(CarMapper.class);
        //假设三个条件都不是空
        //List<Car> cars = mapper.selectByMultiConditionWithTrim("川",10.0,"能能源");

        //假设三个条件都是空
        List<Car> cars = mapper.selectByMultiConditionWithTrim("",null,"");

        //假设后两个条件不是空,第一个条件是空
        //List<Car> cars = mapper.selectByMultiConditionWithTrim("",10.0,"能能源");

        //假设第一个条件不是空,后两个条件是空
        //List<Car> cars = mapper.selectByMultiConditionWithTrim("川",null,"");
        cars.forEach(car -> {
            System.out.println(car);
        });
        session.close();
    }

运行结果
四种情况都可正常执行。

四、set标签

主要使用在update语句当中,用来生成set关键字,同时去掉最后多余的”,“
比如我们只更新提交的不为空的字段,如果提交的数据是空或者” “,那么这个字段我们将不更新。

接口

    /**
     * 使用set标签
     * @param car
     * @return
     */
    int updateBySet(Car car);

mapper.xml:
与正常的update标签进行对比:

<update id="updateById">
    update t_car set
        car_num = #{carNum},
        brand = #{brand},
        guide_price = #{guidePrice},
        produce_time = #{produceTime},
        car_type = #{carType}
</update>

这个会出现的情况就是当在测试时传进去的参数new Car(1L,null,null,null,null,null,“燃油车”);我们的目的是只想修改car_type,其他都不变。但是执行完上述代码之后,除了id和car_type字段其他都变为空。
使用set标签之后:

<update id="updateBySet">
    update t_car
    <set>
        <if test="carNum !=null and carNum != ''">
            car_num = #{carNum},
        </if>
        <if test="brand !=null and brand != ''">
            brand = #{brand},
        </if>
        <if test="guidePrice !=null and guidePrice != ''">
            guide_price = #{guidePrice},
        </if>
        <if test="carType !=null and carType != ''">
            car_type = #{carType},
        </if>
    </set>
    where 
        id =#{id}
</update>

测试

    @Test
    public void testUpdateBySet() throws IOException {
        SqlSession session = SqlSessionUtil.openSession();
        CarMapper mapper = session.getMapper(CarMapper.class);
        Car car = new Car(13L,"1004",null,60.0,null,null);
        int count = mapper.updateBySet(car);
        System.out.println(count);
        session.commit();
        session.close();
    }

运行结果
执行前: (id=13的数据)
在这里插入图片描述
执行后:
在这里插入图片描述

五、choose标签

等同于:
if(){
}else if(){
}else if(){
}else{
}
只有一个分支会被选择。
需求:先根据品牌查询,如果没有提供品牌,再根据指导价查询,如果没有提供指导价,就根据生产日期查询。
接口

	/**
     * 使用choose when otherwise标签
     * @param brand
     * @param guidePrice
     * @param carType
     * @return
     */
    List<Car> selectByChoose(@Param("brand") String brand,@Param("guidePrice") Double guidePrice,@Param("carType") String carType);


mapper.xml

<select id="selectByChoose" resultType="car">
    select * from t_car
    <where>
        <choose>
            <when test="brand !=null and brand!=''">
                brand like "%"#{brand}"%"
            </when>
            <when test="guidePrice !=null and guidePrice!=''">
                guide_price > #{guidePrice}
            </when>
            <otherwise test="carType !=null and carType!=''">
                car_type = #{carType}
            </otherwise>
        </choose>
    </where>
</select>

测试

    @Test
    public void testSelectByChoose() throws IOException {
        SqlSession session = SqlSessionUtil.openSession();
        CarMapper mapper = session.getMapper(CarMapper.class);
        List<Car> cars =  mapper.selectByChoose("宝马",null,null);
        cars.forEach(car -> {
            System.out.println(car);
        });
        session.close();
    }

运行结果
若三个参数都不为空,则以第一个参数为主。
在这里插入图片描述

若三个参数都为空,则条件最后会落在carType上,此时carType=null;也就是查不到任何数据
在这里插入图片描述

注意:choose when otherwise 三个标签必须一起使用


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值