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.mzph.cn/news/852329.shtml

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

相关文章

使用pnpm创建vue3项目

https://pnpm.io/zh/ 全局安装&#xff1a; npm install -g pnpm 检查版本&#xff1a; pnpm -v 创建vue3项目&#xff1a; pnpm create vuelatest 项目装包&#xff1a; pnpm install 运行项目&#xff1a; pnpm dev 命令行&#xff1a; https://pnpm.io/zh/pnpm-cli pnpm …

C语言 | Leetcode C语言题解之第150题逆波兰表达式求值

题目&#xff1a; 题解&#xff1a; int evalRPN(char** tokens, int tokensSize) {int n tokensSize;int stk[(n 1) / 2];memset(stk, 0, sizeof(stk));int index -1;for (int i 0; i < n; i) {char* token tokens[i];if (strlen(token) > 1 || isdigit(token[0])…

UNIAPP-ADB无线调试

ADB下载 SDK 平台工具版本说明 | Android Studio | Android Developers (google.cn) 环境变量配置 ADB版本查看 adb version 手机使用数据线连接到电脑 手机需要授权adb调试(开发人员选项里面) CMD输入命令 adb tcpip 5555 到了这一步你手机已经启动了adb服务了&…

vue 生命周期 钩子函数 keep-alive activated deactivated

一、activated deactivated 在被keep-alive包含的组件/路由中&#xff0c;会多出两个生命周期的钩子:activated 与 deactivated。在 2.2.0 及其更高版本中&#xff0c;activated 和 deactivated 将会在树内的所有嵌套组件中触发。activated在组件第一次渲染时会被调用&#x…

kafka 快速上手

下载 Apache Kafka 演示window 安装 编写启动脚本,脚本的路径根据自己实际的来 启动说明 先启动zookeeper后启动kafka,关闭是先关kafka,然后关闭zookeeper 巧记&#xff1a; 铲屎官&#xff08;zookeeper&#xff09;总是第一个到&#xff0c;最后一个走 启动zookeeper call bi…

2024 Idea最新激活码

idea的激活与安装 操作如下&#xff1a; ① 打开网站&#xff1a;https://web.52shizhan.cn 切换到&#xff1a;激活码&#xff0c;点击获取 ② 这个时候就跳转到现成账号页面&#xff0c;点击获取体验号&#xff0c;如图 ③ 来到了获取现成账号的页面了。输入你的邮箱账号即…

Flutter笔记:关于WebView插件的用法(上)

Flutter笔记 关于WebView插件的用法&#xff08;上&#xff09; - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:htt…

官宣!2024影响因子即将公布,或将迎来这些重大变化!

【SciencePub学术】IF是Impact Factor&#xff0c;即我们俗称的“影响因子”&#xff0c;是衡量学术期刊一个重要性的指标。它通过计算期刊上发表的文章在特定时间内被引用的平均次数来评估期刊的影响力。 影响因子计算公式 影响因子&#xff08;IF&#xff09;&#xff08;期…

vue3实战练习之红包雨,抢红包案例

抢红包案例 每当618消费节到来时&#xff0c;某宝、某多&#xff0c;等购物网站都会退出各种活动&#xff0c;其中抢红包&#xff0c;优惠券等红包雨活动很是火热&#xff0c;于是就通过vue的知识来做一个红包雨&#xff0c;抢红包加分活动&#xff01;代码中红包的路径改成自己…

2024年人工智能与云计算国际会议(ICAICC 2024)

2024 International Conference on Artificial Intelligence and Cloud Computing 【1】大会信息 大会时间&#xff1a;2024-07-19 大会地点&#xff1a;中国长沙 截稿时间&#xff1a;2024-07-05(以官网为准&#xff09; 审稿通知&#xff1a;投稿后2-3日内通知 会议官网&am…

看完“土猪拱白菜“的张锡峰,我明白计算机有多难了

计算机有多难&#xff1f; 今天无意中&#xff0c;看到一篇关于「"土猪拱白菜"学霸后悔报考浙大计算机」的文章。 或许会有不少和我刚开始一样懵圈的同学&#xff1a;张锡峰是谁&#xff1f;"土猪拱白菜"又是什么梗&#xff1f; 带着疑惑&#xff0c;我打开…

Tita 360评估:有效 360度反馈流程的 10 大步骤

宣传过程 如果你的公司首次引入多方位反馈或 360 度反馈&#xff0c;那么向所有利益相关者描述这一流程至关重要。由于流程太新&#xff0c;很多人还不了解。确保参与该流程的每个人都了解其目的&#xff0c;以及将如何实施该流程和使用其结果。花时间在一对一会议、小组会议和…

python的a[:2]、a[:] 和a [::] 的区别

一、a[:2] 数据准备 import numpy as np X np.array([[0,1],[2,3],[4,5],[6,7],[8,9],[10,11],[12,13],[14,15],[16,17],[18,19]]) print(X)形成矩阵 print (“X[: 2]:”, X[: 2]) ### :表示索引 0至1行&#xff1b; 二、a[:]和a [::] 在 Python 中&#xff0c;[:] 和 [::…

SQL Server 安装后,服务器再改名,造成名称不一致,查询并修改数据库服务器真实名称

SELECT SERVERNAME -- 1.查询旧服务器名称 SELECT serverproperty(servername) AS new --2.查询新服务器名称 -- 3.更新服务器名称 IF SERVERPROPERTY(servername) <> 新服务器名称替换 BEGIN DECLARE server_name NVARCHAR(128) SET server_name 新服务器…

Linux部署项目

手动部署 1.在IDEA写一个有关springboot项目 在windows客户端可以通过localhost:8080/hello 访问 2.用packge 命令将该springboot项目打包 并在target目录下找到打包的jar包 3.上传到linux上 个人习惯在usr/local/app 下上传该项目 创建切换到app目录下 mkdir /usr/local/ap…

无文件落地分离拆分-将shellcode从文本中提取-file

马子分为shellcode和执行代码. --将shellcode单独拿出,放在txt中---等待被读取执行 1-cs生成python的payload. 2-将shellcode进行base64编码 import base64code b en_code base64.b64encode(code) print(en_code) 3-将编码后的shellcode放入文件内 4-读取shellcod…

记录pytest中场景执行的token异常处理问题

前言中写了一个conftest钩子函数用于处理重复调用token的方法&#xff0c;http://t.csdnimg.cn/N4rCK&#xff0c;每个用例单独执行都很正常&#xff0c;但是批量执行时一直报错&#xff0c;token缓存处理也不生效。 所有的用例都报获取不到token&#xff0c;方法改了又改&…

C++和C语言到底有什么区别?

引言&#xff1a;C和C语言是两种非常常见的编程语言&#xff0c;由于其广泛的应用和灵活性&#xff0c;它们在计算机科学领域内受到了广泛的关注。虽然C是从C语言发展而来的&#xff0c;但是这两种语言在许多方面都有所不同。本文将对C和C语言进行比较和分析&#xff0c;以便更…

Modbus通信协议(1)--基础知识

一、基础知识 1.信息的划分 2.基本概念 3.机器数和真值 4.原码、反码与补码 5.存储单位 6.基本类型数据 7.数的浮点表示 8.各种进位制的对比 9.十进制 10.二进制 11.十六进制 12.不同进制的换算 13.位的标记 二、常用的信息编码 1.西文字符的计算机表示 2.汉字处理过程 3.汉字…

如何用ai写文案?分享方法和软件!

在当今数字化时代&#xff0c;内容创作已经成为各行各业不可或缺的一部分。然而&#xff0c;对于许多创作者来说&#xff0c;如何写出既具有吸引力又符合平台特点的文案&#xff0c;却是一项不小的挑战。幸运的是&#xff0c;人工智能&#xff08;AI&#xff09;技术的快速发展…