MyBatis 动态 SQL 的详细内容讲解

1. MyBatis 动态 SQL 的详细内容讲解

文章目录

  • 1. MyBatis 动态 SQL 的详细内容讲解
  • 2. 准备工作
  • 3. if 标签
  • 4. where 标签
  • 5. trim 标签
  • 6. set 标签
  • 7. choose when otherwise 标签
  • 8. foreach 标签
    • 8.1 批量删除
    • 8.2 批量添加
  • 9. SQL 标签与 include 标签
  • 10. 总结:
  • 11. 最后:


有的业务场景,也需要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 .....;

2. 准备工作

数据表结构的设计,数据表名为:t_car

在这里插入图片描述

t_car 表中的数据信息:

在这里插入图片描述

pom.xml 文件当中配置相关的依赖的 jar 包如下:

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.rainbowsea</groupId><artifactId>mybatis-005-crud-blog</artifactId><version>1.0-SNAPSHOT</version><properties><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target></properties><dependencies><!--        mybatis 的依赖--><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.10</version></dependency><!--        mysql --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.30</version></dependency><dependency><groupId>junit</groupId><artifactId>junit</artifactId><version>4.13.2</version><scope>test</scope></dependency><!--        引入 logback的依赖,这个日志框架实现了slf4j 规范--><dependency><groupId>ch.qos.logback</groupId><artifactId>logback-classic</artifactId><version>1.2.11</version></dependency></dependencies></project>

配置 logback 的配置文件,用于打印显示,我们的日志信息,方便我们查看我们的运行过程,效果。

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8"?><configuration debug="false"><!-- 控制台输出 --><appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"><encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符--><pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern></encoder></appender><!--mybatis log configure--><logger name="com.apache.ibatis" level="TRACE"/><logger name="java.sql.Connection" level="DEBUG"/><logger name="java.sql.Statement" level="DEBUG"/><logger name="java.sql.PreparedStatement" level="DEBUG"/><!-- 日志输出级别,logback日志级别包括五个:TRACE < DEBUG < INFO < WARN < ERROR --><root level="DEBUG"><appender-ref ref="STDOUT"/><appender-ref ref="FILE"/></root></configuration>

配置 MyBatis 的核心配置文件,

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configurationPUBLIC "-//mybatis.org//DTD Config 3.0//EN""http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration><!--  使用 <package>	还可以将这个包下的所有的类的全部自动起别名,别名就是简名,不区分大小写 --><package name="com.rainbowsea.mybatis.pojo"/></typeAliases><environments default="mybatis"><environment id="mybatis"><!--            MANAGED 没有用第三框架管理的话,都是会被提交的,没有事务上的管理了 --><transactionManager type="JDBC"/><dataSource type="POOLED"><property name="driver" value="com.mysql.cj.jdbc.Driver"/><property name="url" value="jdbc:mysql://localhost:3306/mybatis"/><property name="username" value="root"/><property name="password" value="MySQL123"/></dataSource></environment></environments><mappers><!-- 这里也是可以使用 package 包名扫描,但是同样的:对应接口路径要一致,接口名一致--><package name="com.rainbowsea.mybatis.mapper"></package></mappers>
</configuration>

对照 t_car 创建的ORM 映射的 Car 类

注意:在MyBatis 当中对应的ORM ,一般在框架里对应的 Bean实体类,一定要实现该 set 和 get 方法以及无参数构造方法,无法框架无法使用反射机制,进行操作

建议用包装类,这样可以防止 Null的问题,因为(简单类型 int num = null ,是不可以赋值为 null)的编译无法通过

在这里插入图片描述

package com.rainbowsea.mybatis.pojo;public class Car {// 数据库表当中的字段应该和pojo类的属性一一对应// 建议使用包装类,这样可以防止null的问题private Long id;private String carNum;private String brand;private Double guidePrice;private String produceTime;private String carType;public Car() {}public Car(Long id, String carNum, String brand, Double guidePrice, String produceTime, String carType) {this.id = id;this.carNum = carNum;this.brand = brand;this.guidePrice = guidePrice;this.produceTime = produceTime;this.carType = carType;}@Overridepublic String toString() {return "Car{" +"id=" + id +", carNum='" + carNum + '\'' +", brand='" + brand + '\'' +", guidePrice=" + guidePrice +", produceTime='" + produceTime + '\'' +", catType='" + carType + '\'' +'}';}public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getCarNum() {return carNum;}public void setCarNum(String carNum) {this.carNum = carNum;}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public Double getGuidePrice() {return guidePrice;}public void setGuidePrice(Double guidePrice) {this.guidePrice = guidePrice;}public String getProduceTime() {return produceTime;}public void setProduceTime(String produceTime) {this.produceTime = produceTime;}public String getcarType() {return carType;}public void setcarType(String catType) {this.carType = catType;}
}

3. if 标签

需求:多条件查询。

可能的条件包括:品牌(brand)、指导价格(guide_price)、汽车类型(car_type)

多条件查询
不提供查询:0 条件 select * from t_product;
当选择一个条件: select * from t_product where brand=#{brand}
当用户选了多个条件:select * from t_product where 条件1=...and 条件2=..and条件3 =...
 <if test="表达式运行之后的结果是false,不会拼接"></if>

if 标签的使用的注意事项:

  1. if 标签中的 test 属性是必须的
  2. if 标签中 test 属性的值是false 或者 true
  3. 如果test是true ,则if标签中的sql语句就会拼接,反之则部分拼接、
  4. test属性中可以使用的是:
    1. 当使用了@Param注解,那么 test 中给你要出现的是 @Param 注解指定的参数名,@Param(“brand”)
    2. 当没有使用@Param注解,那么test中要出现的是:param1,param2,param3 ; arg0,arg1…
    3. 当使用了POJO,那么test中出现的是POJO类的属性名,
    4. 5.在mybatis的动态SQL当中,不能使用&&,只能使用 and ,or
  5. 注意单引号双引号交替使用

在这里插入图片描述

package com.rainbowsea.mybatis.mapper;import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface CarMapper {/*** 多条件查询** @param brand       品牌* @param guiderPrice 指导价* @param carType     汽车类型* @return*/List<Car> selectByMultiCondition(@Param("brand") String brand, @Param("guidePrice") Double guiderPrice,@Param("carType") String carType);
}

在这里插入图片描述

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><!--	id 要是 namespace 对应接口上的方法名: --><select id="selectByMultiCondition" resultType="Car">SELECT id, car_num, brand, guide_price, produce_time, car_typeFROM `t_car`where 1=1<!--1.if标签中的test属性是必须的2.if标签中test属性的值是false 或者 true3.如果test是true ,则if标签中的sql语句就会拼接,反之则部分拼接4.test属性中可以使用的是:当使用了@Param注解,那么test中i给你要出现的是@Param注解指定的参数名,@Param("brand")当没有使用@Param注解,那么test中要出现的是:param1,param2,param3 ; arg0,arg1...当使用了POJO,那么test中出现的是POJO类的属性名5.在mybatis的动态SQL当中,不能使用&&,只能使用 and ,or6.注意单引号双引号交替使用--><!--        <if test="表达式运行之后的结果是false,不会拼接"></if>--><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></mapper>

运行测试:

在这里插入图片描述

在这里插入图片描述

package com.rainbowsea.mybatis.test;import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;import java.io.IOException;
import java.util.List;public class CarMapperTest {@Testpublic void testSelectByMultiCondition() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);// 假设三个条件都不为null//List<Car> cars = mapper.selectByMultiCondition("小米",21.00,"新能源");// 假设三个条件都是空//List<Car> cars = mapper.selectByMultiCondition("",null,"");// 假设后两个条件不为空,第一个条件为空//List<Car> cars = mapper.selectByMultiCondition("",21.00,"新能源");// 假设第一个条件不是空,后两个条件为空List<Car> cars = mapper.selectByMultiCondition("小米",null,"");cars.forEach(car -> {System.out.println(car);});sqlSession.close();}
}

补充:

如果第一个条件为空,剩下两个条件不为空,会是怎样呢?

List<Car> cars = mapper.selectByMultiCondition("", 20.0, "燃油车");

在这里插入图片描述

报错了,SQL语法有问题,where后面出现了and。这该怎么解决呢?

可以where后面添加一个恒成立的条件。

在这里插入图片描述

在这里插入图片描述

4. where 标签

where标签的作用:让 where 子句更加动态智能。

  • 所有条件都为空时,where 标签不会生成where子句。同时满足条件 会自动生成 where 关键字,不需要我们手动添加。
  • 自动去除某些条件前面多余的 and 或 or。

继续使用 if 标签中的需求。

需求:多条件查询。

可能的条件包括:品牌(brand)、指导价格(guide_price)、汽车类型(car_type)

在这里插入图片描述

import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface CarMapper {/*** 使用where标签,让where 子句更加灵活,更加智能** @param brand* @param guidePrice* @param carType* @return*/List<Car> selectByMultiConditionWithWhere(@Param("brand") String brand, @Param("guidePrice") Double guidePrice,@Param("carType") String carType);}

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><select id="selectByMultiConditionWithWhere" resultType="Car">SELECT id, car_num, brand, guide_price, produce_time, car_typeFROM `t_car`<!--where 标签是专门负责 where 子句动态生成的,不用我们自己再写 where 关键字了,自动生成--><!--自动去除某些条件前面多余的and或or。--><where><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></where></select></mapper>

运行测试:

在这里插入图片描述


import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;import java.io.IOException;
import java.util.List;public class CarMapperTest {@Testpublic void testSelectByMultiConditionWithWhere() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);// 假设三个条件都不为nullList<Car> cars = mapper.selectByMultiConditionWithWhere("小米",21.00,"新能源");// 如果第一个条件是空,其他的不为空List<Car> cars2 = mapper.selectByMultiConditionWithWhere("",21.00,"新能源");// 假设第一个条件不是空,后两个条件为空List<Car> cars3 = mapper.selectByMultiConditionWithWhere("小米",null,"");cars3.forEach(car -> {System.out.println(car);});sqlSession.close();}
}

5. trim 标签

trim标签的属性:

  • prefix:在trim标签所有内容的最 前面添加内容
  • suffix:在trim标签中所有内容的最 后面添加 内容
  • prefixOverrides:trim 标签中所有内容当中前缀覆盖掉(去掉)
  • suffixOverrides:trim 标签中所有内容当中后缀覆盖掉(去掉)

在这里插入图片描述

import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface CarMapper {/*** 使用 trim 标签,添加删除** @param brand* @param guidePrice* @param carType* @return*/List<Car> selectByMultiConditionWithTrim(@Param("brand") String brand, @Param("guidePrice") Double guidePrice,@Param("carType") String carType);
}

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><select id="selectByMultiConditionWithTrim" resultType="Car" >SELECT id, car_num, brand, guide_price, produce_time, car_typeFROM `t_car`<!--prefix 加前缀suffix: 加后缀prefixOverriders: 删除前缀suffixOverrides : 删除后缀prefix="where" 表示是在 trim 标签所有内容的最前面添加 where ,suffix 同理suffixOverrides="and|or" 把 trim 标签中所有内容的后缀 and 或 or 去掉--><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 !=''">car_type = #{carType}</if></trim></select></mapper>

运行测试:

在这里插入图片描述


import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;import java.io.IOException;
import java.util.List;public class CarMapperTest {@Testpublic void testSelectByMultiConditionWithTrim() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);List<Car> cars = mapper.selectByMultiConditionWithTrim("", null, "");List<Car> cars2 = mapper.selectByMultiConditionWithTrim("小米", null, "");cars.forEach(car -> {System.out.println(car);});sqlSession.close();}
}

6. set 标签

主要使用在 update 语句当中,用来生成 set 关键字,同时去掉最后多余的“,”。set 标签会自动添加 set 关键字,不用我们自己再写了-

比如我们只更新提交的不为空的字段,如果提交的数据是空或者 “”,那么这个字段我们将不更新

在这里插入图片描述


import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface CarMapper {/*** 使用set 标签** @param car* @return*/int updateSet(Car car);}

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><update id="updateSet">update t_car<!--set 标签会自动添加 set 关键字,不用我们自己再写了--><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>whereid = #{id}</update>
</mapper>

运行测试:

将 id 为 128的 brand 改为:丰田霸道 ,car_type 改为 燃油车,其他的为 null (这里使用了 set ,为null / 空字段值,不会被修改)

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;import java.io.IOException;
import java.util.List;public class CarMapperTest {/** 主要使用在update语句当中,用来生成set关键字,同时去掉最后多余的“,”比如我们只更新提交的不为空的字段,如果提交的数据是空或者"",那么这个字段我们将不更新。*/@Testpublic void testUpdateSet() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);Car car = new Car(128L, null, "丰田霸道", null, null, "燃油车");mapper.updateSet(car);sqlSession.commit();sqlSession.close();}
}

7. choose when otherwise 标签

这三个标签是在一起使用的:

<choose><when></when><when></when><when></when><otherwise></otherwise>  // 上面的 when 都没满足时,执行这个
</choose>

等同于

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

只有一个分支会被选择(其中一个满足了,后面的就不会进去了),被执行 SQL拼接 !!!!

需求:先根据品牌查询,如果没有提供品牌,再根据指导价格查询,如果没有提供指导价格,就根据生产日期查询。

在这里插入图片描述

import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface CarMapper {/*** 使用choose when otherwise 标签** @param brand* @param guiderPrice* @param carType* @return*/List<Car> selectByChoose(@Param("brand") String brand, @Param("guidePrice") Double guiderPrice,@Param("carType") String carType);}

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><select id="selectByChoose" resultType="Car">SELECT id, car_num, brand, guide_price, produce_time, car_typeFROM `t_car`<!--只会执行其中的 一个满足条件的分支当中。--><where><choose><!-- 当其中的某个 when 满足条件,进入该 when 的SQL语句(拼接),并执行,后面其他的when 就不会进入了--><when test="brand != null and brand != ''">brand like "%"#{brand}"%"</when><when test="guidePrice != null and guidePrice !=''">guide_price > #{guidePrice}</when><otherwise><!-- 当上面所有的 when 都没有满足条件的,则会进入这里的 otherwise的SQL语句(拼接),并执行-->car_type = #{carType}</otherwise></choose></where></select></mapper>

运行测试:

在这里插入图片描述

在这里插入图片描述


import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;import java.io.IOException;
import java.util.List;public class CarMapperTest {/*** 只有一个分支会被选择!!!!*/@Testpublic void testSelectByChoose() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);// 三个条件不为空List<Car> cars = mapper.selectByChoose("丰田霸道",3.00,"燃油车");// 第一条件为空List<Car> cars2 = mapper.selectByChoose("",3.00,"燃油车");// 两个条件为NullList<Car> cars3 = mapper.selectByChoose("",null,"燃油车");// 全部为空,执行选择 otherwise 标签当中的信息List<Car> cars4 = mapper.selectByChoose("",null,"");cars4.forEach(car ->{System.out.println(car);});sqlSession.close();}
}

8. foreach 标签

利用循环数组或集合,动态生成sql,比如这样的SQL:

批量删除

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

批量添加:

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','新能源')

8.1 批量删除

方式一:

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

在这里插入图片描述

import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface CarMapper {/*** 批量删除,foreach 标签** @param ids* @return*/int deleteByIds(@Param("ids") Long[] ids);
}

foreach 标签的属性:

 collection :指定数组或者集合,在对应接口方法当中参数中定义的参数名item:代表数组或集合中的元素的一个临时变量,命名随意,但是最好见名知意separator:循环之间的分隔符open: foreach 循环拼接的所有sql语句的最前面以什么开始close: foreach 循环拼接的所有sql语句的最前面以什么结束collection="ids" 第一次写这个的时候报错了,错误信息是:{array,arg0}什么意思?map.put("array",数组)map.put("arg0",数组)
 <!--  delete from t_car where id in(1,2,3)--><!-- delete from t_car where id in ( -->
<foreach collection="ids" item="变量" separator=",">
</foreach><foreach collection="ids" item="aaa" separator=",">#{aaa}</foreach>

在这里插入图片描述

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><!--foreach 标签的属性:collection :指定数组或者集合,在对应接口方法当中参数中定义的参数名item:代表数组或集合中的元素separator:循环之间的分隔符open: foreach 循环拼接的所有sql语句的最前面以什么开始close: foreach 循环拼接的所有sql语句的最前面以什么结束collection="ids" 第一次写这个的时候报错了,错误西悉尼是:{array,arg0}什么意思?map.put("array",数组)map.put("arg0",数组)--><delete id="deleteByIds"><!--  delete from t_car where id in(1,2,3)--><!-- delete from t_car where id in ( --><!--<foreach collection="ids" item="变量" separator=","></foreach>--><!-- <foreach collection="ids" item="aaa" separator=",">#{aaa}</foreach>--><!-- ) -->delete from t_car where id in<foreach collection="ids" item="id" separator="," open="(" close=")">#{id}</foreach></delete></mapper>

运行测试:

在这里插入图片描述

方式二:

delete from t_car where id = 1 or id = 2 or id = 3;

在这里插入图片描述

import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface CarMapper {/*** 批量删除第二种方式 or** @param ids* @return*/int deleteByIds2(@Param("ids") Long[] ids);}

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><delete id="deleteByIds2">delete from t_car where<foreach collection="ids" separator="or" item="id">id=#{id}</foreach></delete>
</mapper>

运行测试:

删除id为 136 ,137 两条记录

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述


import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;public class CarMapperTest {@Testpublic void testDeleteByIds2() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);Long[] ids = {136L, 137L};mapper.deleteByIds2(ids);sqlSession.commit();sqlSession.close();}
}

8.2 批量添加

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','新能源')

在这里插入图片描述

import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface CarMapper {/*** 批量插入,一次插入多个Car信息** @param cars* @return*/int insertBath(@Param("cars") List<Car> cars);}

需要注意的是:这里是封装到POJO实体类当中的,所定义的 item的变量后,所有POJO实体类的属性名,用 "." 的方式,比如:car.carNum,变量名.POJO实体类的属性名

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><insert id="insertBath">insert into t_car(id,car_num,brand,guide_price,produce_time,car_type) values<foreach collection="cars" item="car" separator=","><!--需要注意的是:这里是封装到POJO实体类当中的,所定义的 item的变量后,所有POJO实体类的属性名,用 "."的方式-->(null,#{car.carNum},#{car.brand},#{car.guidePrice},#{car.produceTime},#{car.carType})</foreach></insert>
</mapper>

运行测试:

在这里插入图片描述

在这里插入图片描述


import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;public class CarMapperTest {@Testpublic void testInsertBath() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);Car car1 = new Car(null, "1201", "玛莎拉蒂1", 30.0, "2020-12", "燃油车");Car car2 = new Car(null, "1202", "玛莎拉蒂2", 30.0, "2020-12", "燃油车");Car car3 = new Car(null, "1203", "玛莎拉蒂3", 30.0, "2020-12", "燃油车");List<Car> cars = new ArrayList<>();cars.add(car1);cars.add(car2);cars.add(car3);mapper.insertBath(cars);sqlSession.commit();sqlSession.close();}}

9. SQL 标签与 include 标签

sql标签用来声明sql片段

include 标签用来将声明的 sql 片段包含到某个 sql 语句当中

作用:代码复用。易维护。

首先就是通过 <SQL> 标签定义/声明一个SQL片段,再通过 <include> 标签根据所声明的 SQL语句片段的 id ,引用相关SQL片段的内容。

在这里插入图片描述

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapperPUBLIC "-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><!--namespace 一定要是:对应的接口的全限定类名-->
<mapper namespace="com.rainbowsea.mybatis.mapper.CarMapper"><!--    声明一个sql片段--><sql id="carColumnNameSql">id,car_num      as carNum,brand,guide_price  as guidePrice,produce_time as produceTime,car_type     as carType</sql><select id="selectById2" resultType="Car">SELECT<!--将声明的sql片段包含进来--><include refid="carColumnNameSql"></include>FROM `t_car`where id=#{id}</select></mapper>

运行测试:

在这里插入图片描述

import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;import java.util.List;public interface CarMapper {/*** 测试 sql标签,代码片段的运用** @param id* @return*/Car selectById2(@Param("id") Long id);}

在这里插入图片描述

在这里插入图片描述

import com.rainbowsea.mybatis.mapper.CarMapper;
import com.rainbowsea.mybatis.pojo.Car;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.junit.Test;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;public class CarMapperTest {@Testpublic void testSelectById2() throws IOException {SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(Resources.getResourceAsStream("mybatis-config.xml"), "mybatis");SqlSession sqlSession = sqlSessionFactory.openSession();CarMapper mapper = sqlSession.getMapper(CarMapper.class);Car car = mapper.selectById2(118L);System.out.println(car);sqlSession.close();}
}

10. 总结:

  1. if 标签: if 标签中的 test 属性是必须的,if 标签中 test 属性的值是false 或者 true,如果test是true ,则if标签中的sql语句就会拼接,反之则部分拼接、
  2. Where标签:所有条件都为空时,where 标签不会生成where子句。同时满足条件 会自动生成 where 关键字,不需要我们手动添加。自动去除某些条件前面多余的 and 或 or。
  3. trim 标签:
- prefix:在trim标签所有内容的最 前面添加内容
- suffix:在trim标签中所有内容的最  后面添加 内容
- prefixOverrides:trim 标签中所有内容当中前缀覆盖掉(去掉)
- suffixOverrides:trim 标签中所有内容当中后缀覆盖掉(去掉
  1. set 标签:主要使用在 update 语句当中,用来生成 set 关键字,同时去掉最后多余的“,”。set 标签会自动添加 set 关键字,不用我们自己再写了-

    比如我们只更新提交的不为空的字段,如果提交的数据是空或者 “”,那么这个字段我们将不更新

  2. choose when otherwise 标签:这三个标签是在一起使用的:

    <choose><when></when><when></when><when></when><otherwise></otherwise>  // 上面的 when 都没满足时,执行这个
    </choose>
    

    等同于

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

    只有一个分支会被选择(其中一个满足了,后面的就不会进去了),被执行 SQL拼接 !!!!

  3. SQL标签与 include 标签:提高代码的复用性。首先就是通过 <SQL> 标签定义/声明一个SQL片段,再通过 <include> 标签根据所声明的 SQL语句片段的 id ,引用相关SQL片段的内容。

11. 最后:

“在这个最后的篇章中,我要表达我对每一位读者的感激之情。你们的关注和回复是我创作的动力源泉,我从你们身上吸取了无尽的灵感与勇气。我会将你们的鼓励留在心底,继续在其他的领域奋斗。感谢你们,我们总会在某个时刻再次相遇。”

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/349037.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

centos下创建raid6磁盘阵列

在CentOS系统中创建RAID 6阵列&#xff0c;可以使用mdadm工具。 以下是创建RAID 6阵列的基本步骤和示例代码&#xff1a; 安装mdadm工具&#xff08;如果尚未安装&#xff09;&#xff1a; sudo yum install mdadm 假设你有至少四个以上的磁盘设备&#xff08;例如 /dev/sdi…

2024年最新Microsoft Edge关闭自动更新的方法分享

这里写自定义目录标题 打开【服务】 打开【服务】 windows中搜索服务&#xff0c;如下图&#xff1a; 打开服务界面&#xff0c;找到“Microsoft Edge Update Service (edgeupdate)” 及 “Microsoft Edge Update Service (edgeupdatem)” 两个服务&#xff0c;设置为禁用

【DrissionPage】Linux上如何将https改为http

最近有个老板找我做一个自动化的程序&#xff0c;要求部署到Linux上 这是一个http协议的网站&#xff0c;chrome在默认设置下&#xff0c;会将http的网站识别成不安全的内容&#xff0c;然后自动将http转化成https访问 但是&#xff0c;这个http的网站它的加载项里既有http的…

开源大模型之辩:真假开源

目录 前言开源的定义什么是开源大模型&#xff1f;大模型时代首次出现闭源和开源“齐头并进”开源和闭源不是绝对对立的 大模型到底开源什么&#xff1f;传统开源软件与开源大模型的差别开源软件让开源大模型“受益匪浅” 不同大模型企业&#xff0c;开源、闭源策略不同开源…

安装操作系统1-Win10版本介绍及硬件要求

注意&#xff1a;安装系统&#xff0c;首先弄清有哪些版本及所需硬件环境。 1.Win10有哪些版本 微软将 Win10为以下7个版本&#xff1a; Windows 10 家庭版&#xff08;Home&#xff09; 面向所有普通用户&#xff0c;提供Win 10的基本功能。此版本适合个人家庭用户使用&am…

一维信号的时频分析(Python)

代码较为简单&#xff0c;很容易读懂。 Importing the required libraries import os import numpy as np import pywt import pandas as pd import pickle as pkl from matplotlib import pyplot as plt Parameters or Required Variables DATA_POINTS_PER_FILE 2560 TIM…

Android Jetpack Compose入门教程(二)

一、列表和动画 列表和动画在应用内随处可见。在本课中&#xff0c;您将学习如何利用 Compose 轻松创建列表并添加有趣的动画效果。 1、创建消息列表 只包含一条消息的聊天略显孤单&#xff0c;因此我们将更改对话&#xff0c;使其包含多条消息。您需要创建一个可显示多条消…

(代数:解一元二次方程)可以使用下面的公式求一元二次方程 ax2+bx+c0 的两个根:

(代数:解一元二次方程)可以使用下面的公式求一元二次方程 ax2bxc0 的两个根: b2-4ac 称作一元二次方程的判别式。如果它是正值,那么一元二次方程就有两个实数根。 如果它为 0&#xff0c;方程式就只有一个根。如果它是负值&#xff0c;方程式无实根。 编写程序&#xff0c;提示…

STM32存储左右互搏 模拟U盘桥接SPI总线FATS读写FLASH W25QXX

STM32存储左右互搏 模拟U盘桥接SPI总线FATS读写FLASH W25QXX STM32的USB接口可以模拟成为U盘&#xff0c;通过FATS文件系统对连接的存储单元进行U盘方式的读写。 这里介绍STM32CUBEIDE开发平台HAL库模拟U盘桥接SPI总线FATS读写W25Q各型号FLASH的例程。 FLASH是常用的一种非易失…

vs2019 c++20规范 STL 库中头文件 <atomic> 源码注释及探讨几个知识点

&#xff08;1 探讨一&#xff09; 模板类 atomic 的继承关系与数据结构如下&#xff1a; (2 探讨二 ) 可见 atomic 的 fetch_xx 函数&#xff0c;返回的都是 atomic 中存储的旧值。测试如下&#xff1a; 谢谢

无公网IP与服务器完成企业微信网页应用开发远程调试详细流程

文章目录 前言1. Windows安装Cpolar2. 创建Cpolar域名3. 创建企业微信应用4. 定义回调本地接口5. 回调和可信域名接口校验6. 设置固定Cpolar域名7. 使用固定域名校验 前言 本文主要介绍如何在企业微信开发者中心通过使用内网穿透工具提供的公网域名成功验证回调本地接口服务! …

互联网应用主流框架整合之SpringMVC初始化及各组件工作原理

Spring MVC的初始化和流程 MVC理念的发展 SpringMVC是Spring提供给Web应用领域的框架设计&#xff0c;MVC分别是Model-View-Controller的缩写&#xff0c;它是一个设计理念&#xff0c;不仅仅存在于Java中&#xff0c;各类语言及开发均可用&#xff0c;其运转流程和各组件的应…

PFC旁路二极管、继电器驱动电路以及PFC主功率

R001和R002以及R003三个电阻作用是限放X电容上的电 整流桥串联两个BJ1和BJ2 电容C3:给整流桥储能&#xff0c;给后续llc供电 PFC工作是正弦波上叠加高频电流 PFC功率部分 2个PFC电感&#xff08;选择两个磁芯骨架小&#xff0c;有利于散热&#xff09;、2个续流二极管&…

【Hudi】核心概念-基本概念

目录 基本概念时间轴(TimeLine)Instant action:在表上执行的操作类型Instant timeState两个时间概念 文件布局(File Layout)索引(Index)原理索引选项全局索引与非全局索引索引的选择策略 表类型(Table Types)查询类型Snapshot QueriesIncremental QueriesRead Optimized Querie…

出现“由于找不到msvcr120.dll,无法继继续执行代码”提示的问题处理方法

本文章针对出现“由于找不到msvcr120.dll,无法继续执行代码”的问题进行深入剖析&#xff0c;并提供了两种有效的解决方案&#xff0c;方便大家能快速恢复正常工作状态。 一.关于msvcr120.dll文件部分介绍 “由于找不到msvcr120.dll,无法继续执行代码”常发生在我们打开一个软…

web端使用高德地图

web端使用高德地图 一、申请高德key和秘钥二、在项目中引入所需功能js、css文件三、实现地图选点、回显选点四、自定义地图 一、申请高德key和秘钥 申请高德key 申请成功后可以得到key 二、在项目中引入所需功能js、css文件 <script src"https://webapi.amap.com/m…

流程设计的基本步骤

背景 公司为什么要流程&#xff0c;已经有专门章节进行阐述&#xff1b; 什么是流程&#xff0c;已经有专门章节进行专门阐述&#xff1b; 那么接下来这个章节讨论&#xff0c;流程设计的基本步骤&#xff0c;那么谁来设计流程呢&#xff0c;让一个部门的员工来设计一份流程…

【RabbitMQ】RabbitMQ配置与交换机学习

文章目录 简介安装和部署1. 安装RabbitMQ2.创建virtual-host3. 添加依赖4.修改配置文件 WorkQueues模型1.编写消息发送测试类2.编写消息接收&#xff08;监听&#xff09;类3. 实现能者多劳 交换机Fanout交换机1.消息发送2.消息监听 Direct交换机1.消息发送2.消息接收 Topic交换…

vue3 vant4 仿京东分类功能实现

Ⅰ- 壹 - 功能展示和使用需求 需求描述 基于vant 实现,仿京东分类功能实现样式交互等基本实现,细节可能需要优化 地址 https://gitee.com/wswhq/vue3-vant-temp/tree/master/src/view/ClassIfication 功能展示 Ⅱ - 贰 - 封装思路 不表述了自己看代码吧 Ⅲ - 叁 - 使用 …

梯度下降法、牛顿法、条件熵

梯度下降法、牛顿法&#xff08;可见南瓜书&#xff09; 梯度下降法 深度学习&#xff1a;梯度下降法数学表示式的详细推导 牛顿法 条件熵 在李航老师的书中&#xff0c;第六章最大熵模型这里有个条件熵的定义&#xff1a; 推导如下&#xff1a; 其他一些事实&#xff1a;…