MyBatis动态SQL,基本语法加实战,一篇搞懂

问题:
有的时候我们需要实现批量删除:delete from t_car where id in(1,2,3,4,5,6,…这⾥的值是动态的,根据⽤户选择的
id不同,值是不同的);
多条件查询:有时我们需要根据多个不同地条件来进行查询,比如:select * from t_car where brand like ‘丰⽥%’ and guide_price > 30 and …;
以上情况地sql语句都是动态的,因此需要我们来进行SQL语句的动态拼接。在MyBatis中是通过不同标签来实现SQL语句的动态的。下面来一一讨论使用标签。

准备工作

在这里插入图片描述
在这里插入图片描述

几种常用标签

if标签

需求:多条件查询。
可能的条件包括:记录id(id)、指导价格(guide_price)、汽⻋类型(car_type)

实战
CarMapper接口中方法

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

SQL语句映射文件代码

<select id="multiConditionSelect" resultType="Car">
        select * from t_car where
        <if test="id != null and id != ''">
            id = #{id}
        </if>
        <if test="brand != null and brand != ''">
            and brand like "%"#{brand}"%"
        </if>
        <if test="guidePrice != null and guidePrice != ''">
            and guide_price > #{guidePrice}
        </if>
    </select>

基本语法:test后面语句的结果如果为true,则该if标签的语句生效,否则不生效。
细节:if标签test后面中的变量是@param起的别名,如果没用@param就是系统默认的arf0…param1…,如果参数是bean类则test后面的变量是bean类的属性名。

测试代码

@Test
    public void testMultiConditionSelect(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.multiConditionSelect(59L,"大众",5.0);
        cars.forEach(car -> System.out.println(car));
        sqlSession.close();
    }

可以看出三个参数都不为空,且不为null,执行一下看一下结果
在这里插入图片描述
可以看出sql语句和预想的一样。

我们将测试代码中

        List<Car> cars = mapper.multiConditionSelect(59L,"大众",5.0);

的第一个参数置空,并再次执行,结果如下
在这里插入图片描述
因为我们将第一个参数置空后SQL语句变为了 select * from t_car where and brand like “%”?“%” and guide_price > ? 可以看出多了一个and,如何解决呢?很简单,我们只需要在where后面加上 1=1 就可以了。更改后再次执行,结果如下
在这里插入图片描述
成功解决

但是这样的话我们需要在第一个条件前面也加上and,否则第一个条件不为空的时候也会出错

where标签

where标签的作⽤:让where⼦句更加动态智能。
所有条件都为空时,where标签保证不会⽣成where⼦句。
⾃动去除某些条件前⾯多余的and或or。

在上面if语句的使用中我们发现每个条件前面加不加and是个麻烦的事情,where标签很好地解决了上面地问题

CarMapper接口中方法

/***
     * 使用Where标签,使Where子句更加智能
     * @param id
     * @param brand
     * @param guidePrice
     * @return
     */
    List<Car> multiConditionSelectWithWhere(@Param("id") Long id,@Param("brand") String brand,@Param("guidePrice") Double guidePrice);

SQL映射文件中代码

<select id="multiConditionSelectWithWhere" resultType="Car">
        select * from t_car
        <where>
            <if test="id != null and id != ''">
                and id = #{id}
            </if>
            <if test="brand != null and brand != ''">
                and brand like "%"#{brand}"%"
            </if>
            <if test="guidePrice != null and guidePrice != ''">
                and guide_price > #{guidePrice}
            </if>
        </where>
    </select>

细节解析:使用where标签,会自动地在t_car后面添加去除where,当后面条件为空,where不会生成,反之生成,同时还会智能去除某些情况下if子句中前面地and但后面地不会去除。

测试代码:

@Test
    public void testMultiConditionSelectWithWhere(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.multiConditionSelectWithWhere(null,"",null);
        cars.forEach(car -> System.out.println(car));
        sqlSession.close();
    }

执行结果
在这里插入图片描述
可以看出在三个参数都为空地情况下where子句智能地没有添加,其他情况不在一一测试。

trim 标签

基本语法
trim标签的属性:
prefix:在trim标签中的语句前添加内容
suffix:在trim标签中的语句后添加内容
prefixOverrides:前缀覆盖掉(去掉)
suffixOverrides:后缀覆盖掉(去掉)

实战
CarMapper接口中方法代码

/***
     * 根据多条件啊查询使用trim标签
     * @param id
     * @param brand
     * @param guidePrice
     * @return
     */
    List<Car> multiConditionSelectWithTrim(@Param("id") Long id,@Param("brand") String brand,@Param("guidePrice") Double guidePrice);

SQL语句映射文件中代码

<select id="multiConditionSelectWithTrim" resultType="Car">
        select * from t_car
        <trim prefix="where" suffixOverrides="and">
            <if test="id != null and id != ''">
                id = #{id} and
            </if>
            <if test="brand != null and brand != ''">
                brand like "%"#{brand}"%" and
            </if>
            <if test="guidePrice != null and guidePrice != ''">
                guide_price > #{guidePrice}
            </if>
        </trim>
    </select>

prefix="where"加一个前缀,在t_car后面我们就不用自己写where了

suffixOverrides=“and” 去除某些条件后面地and,如果第一个第三个参数都为空,第二个条件后面地and会不会智能去除?

测试代码

@Test
    public void testMultiConditionSelectWithTrim(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.multiConditionSelectWithTrim(null,"大众",null);
        cars.forEach(car -> System.out.println(car));
        sqlSession.close();
    }

测试结果
在这里插入图片描述
显然智能去除了第二个条件后面的and,如果三个条件都为空,前缀where还会添加吗?答案是否定地,不会添加,trim标签还是很智能地

set标签

语法
1.主要使⽤在update语句当中,⽤来⽣成set关键字,同时去掉最后多余的“,”

需求:⽐如我们只更新提交的不为空的字段,如果提交的数据是空或者"",那么这个字段我们将不更新。(set标签if标签混用)
实战

CarMapper接口中方法代码

/***
     * 使用set标签完成根据id修改记录
     * <set><set/>生成set同时去掉多余  ,
     * @return
     */
    int updateBySet(Car car);

SQL语句映射文件中代码

<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="produceTime != null and produceTime != ''">produce_time = #{produceTime},</if>
            <if test="carType != null and carType != ''">car_type = #{carType},</if>
        </set>
        where id = #{id}
    </update>

测试代码

@Test
    public void TestUpdateBySet(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car = new Car(59L,"7777",null,null,null,null);
        int count = mapper.updateBySet(car);
        System.out.println("成功" + count + "条");
        sqlSession.commit();
        sqlSession.close();
    }

执行结果
在这里插入图片描述
在这里插入图片描述

可以看出生成了set并且语句后面多余地’ , '被智能去除

choose when oterwise标签

基本语法
三者一块使用

语法格式

<choose>
 <when></when>
 <when></when>
 <when></when>
 <otherwise></otherwise>
</choose>

相当于

if(){
 
}else if(){
 
}else if(){
 
}else if(){
 
}else{
}

只有⼀个分⽀会被选择!!!!
需求:先根据品牌查询,如果没有提供品牌,再根据指导价格查询,如果没有提供指导价格,就根据⽣
产⽇期查询。
实战

CarMapper接口中方法

/***
     * 使用choose 标签进行查询
     * @return
     */
    List<Car> selectWithChoose(@Param("brand") String brand,@Param("guidePrice") Double guidePrice,@Param("carType") String carType);

SQL映射文件中代码

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

测试代码

@Test
    public void testSelectWithChoose(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        List<Car> cars = mapper.selectWithChoose("",null,"新能源");
        cars.forEach(car -> System.out.println(car));
        sqlSession.close();
    }

执行结果
在这里插入图片描述

foreach标签

基本用法
和java中地foreach类似,一共有五个参数,解释如下
collection:集合或数组
item:集合或数组中的元素
separator:分隔符
open:foreach标签中所有内容的开始
close:foreach标签中所有内容的结束

需求

批量添加

insert into t_car values
 (null,'1001','凯美瑞',35.0,'2010-10-11','燃油⻋'),
 (null,'1002','⽐亚迪唐',31.0,'2020-11-11','新能源'),
 (null,'1003','⽐亚迪宋',32.0,'2020-10-11','新能源')

实战

CarMapper接口中方法代码

/***
     * 利用foreach标签进行批量插入
     * @return
     */
    int insertBatchByForeach(@Param("cars") List<Car> cars);

SQL映射文件中代码

<insert id="insertBatchByForeach">
        insert into t_car values
        <foreach collection="cars" item="car" separator=",">
            (null,#{car.carNum},#{car.brand},#{car.guidePrice},#{car.produceTime},#{car.carType})
        </foreach>
    </insert>

测试代码

@Test
    public void testInsertBatchByForeach(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Car car1 = new Car(null,"1100","拖拉机1",10.0,"2001-10-11","燃油车");
        Car car2 = new Car(null,"1100","拖拉机2",10.0,"2001-10-11","燃油车");
        Car car3 = new Car(null,"1100","拖拉机3",10.0,"2001-10-11","燃油车");
        List<Car> cars = new ArrayList<>();
        cars.add(car1);
        cars.add(car2);
        cars.add(car3);
        mapper.insertBatchByForeach(cars);
        sqlSession.commit();
        sqlSession.close();
    }

执行结果
在这里插入图片描述
在这里插入图片描述
大家注意拼接成地sql语句还是很好理解的
需求
批量删除 分别使用or和in

delete from t_car where id in(1,2,3);
delete from t_car where id = 1 or id = 2 or id = 3;

实战1(使用in)
CarMapper接口中的方法代码

/***
     * 利用foreach进行批量删除
     * in(id1,id2.....)
     * @param ids
     * @return
     */
    int deleteBatchByForeach(@Param("ids") Long[] ids);

SQL映射文件代码

<delete id="deleteBatchByForeach">
        delete from t_car
        <where>
            id in
            <foreach collection="ids" item="id" separator="," open="(" close=")">
                #{id}
            </foreach>
        </where>
    </delete>

测试代码

@Test
    public void testDeleteBatchByForeach(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Long[] ids = {68L,69L,70L};
        int count = mapper.deleteBatchByForeach(ids);
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
    }

执行结果
在这里插入图片描述
在这里插入图片描述
实战2 使用or实现批量删除
CarMapper接口中方法代码

/***
     * 利用foreach进行批量删除
     * or
     * @param ids
     * @return
     */
    int deleteBatchByForeach2(@Param("ids") Long[] ids);

SQL映射文件中代码

<delete id="deleteBatchByForeach2">
        delete from t_car where
        <foreach collection="ids" item="id" separator="or">
            id = #{id}
        </foreach>
    </delete>

测试代码

@Test
    public void testDeleteBatchByForeach2(){
        SqlSession sqlSession = SqlSessionUtil.openSession();
        CarMapper mapper = sqlSession.getMapper(CarMapper.class);
        Long[] ids = {71L,72L,73L};
        int count = mapper.deleteBatchByForeach2(ids);
        System.out.println(count);
        sqlSession.commit();
        sqlSession.close();
    }

测试结果
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
将基本语法与测试结果中拼接的sql语句一块理解,还是很好理解的😊

sql标签与include标签

基本用法:
sql标签⽤来声明sql⽚段
include标签⽤来将声明的sql⽚段包含到某个sql语句当中
作⽤:代码复⽤。易维护。

SQL映射文件中代码

<sql id="carCols">id,car_num carNum,brand,guide_price guidePrice,produce_t
ime produceTime,car_type carType</sql>
<select id="selectAllRetMap" resultType="map">
 select <include refid="carCols"/> from t_car
</select>
<select id="selectAllRetListMap" resultType="map">
 select <include refid="carCols"/> carType from t_car
</select>
<select id="selectByIdRetMap" resultType="map">
 select <include refid="carCols"/> from t_car where id = #{id}
</select>

总结结束,希望对你能有所帮助

基本语法是指SQL语句的基本结构和规则。动态SQL语句是指在执行时根据不同的条件或参数生成不同的SQL语句。下面是基本语法的示例: 1. 查询当前数据库: SELECT DATABASE(); 2. 创建数据库: CREATE DATABASE \[IF NOT EXISTS\] 数据库名 \[DEFAULT CHARSET 字符集\] \[COLLATE 排序规则\]; 3. 创建表: CREATE TABLE 表名 ( 字段1 字段1类型 \[COMMENT 字段1注释\], 字段2 字段2类型 \[COMMENT 字段2注释\], 字段3 字段3类型 \[COMMENT 字段3注释\], ......, 字段n 字段n类型 \[COMMENT 字段n注释\] ) \[COMMENT 表注释\]; 请注意,以上示例中的方括号表示可选项,其中的内容可以根据实际情况进行选择或省略。另外,方括号内的内容是用来解释说明的,不需要在实际使用时包含在SQL语句中。 动态SQL语句的基本语法与静态SQL语句相似,只是在执行时可以根据需要动态生成SQL语句。例如,可以使用条件语句(如IF语句)或循环语句(如FOR循环)来根据不同的条件或参数生成不同的SQL语句。动态SQL语句的具体实现方式可能因不同的数据库管理系统而有所不同。 希望以上回答能够解决您的问题。 #### 引用[.reference_title] - *1* *2* *3* [SQL基本语法](https://blog.csdn.net/m0_64362989/article/details/126211075)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一只呆小白

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值