12、动态SQL
什么是动态SQL?
动态 SQL 是 MyBatis 的强大特性之一。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
环境搭建:
依赖:
<dependencies> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.11</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.30</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.24</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.13.2</version> <scope>test</scope> </dependency> </dependencies>
1、创建sql
CREATE TABLE `t_car` ( `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键自增', `car_num` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '汽车编号', `brand` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '汽车品牌', `guide_price` decimal(10, 2) NULL DEFAULT NULL COMMENT '厂家指导价', `produce_time` char(10) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '生产日期', `car_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL COMMENT '汽车类型,包括:燃油车,电车,氢能源', PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Records of t_car -- ---------------------------- INSERT INTO `t_car` VALUES (1, '100', '宝马520Li', 41.00, '2022-09-01', '燃油车'); INSERT INTO `t_car` VALUES (2, '101', '奔驰E300L', 54.00, '2022-08-01', '电车'); INSERT INTO `t_car` VALUES (5, '103', '丰田', 25.80, '2022-01-01', '燃油车'); INSERT INTO `t_car` VALUES (7, '104', '比亚迪汉', 10.00, '2022-11-17', '电车'); INSERT INTO `t_car` VALUES (8, '105', '奥迪', 35.50, '2022-11-11', '燃油车'); SET FOREIGN_KEY_CHECKS = 1;
2、Mybatis配置文件:resource/mybatis-config.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "https://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <properties resource="db.properties"/> <!--日志--> <settings> <setting name="logImpl" value="STDOUT_LOGGING"/> </settings> <!--设置实体类别名--> <typeAliases> <package name="com.zhixi.pojo"/> </typeAliases> <!--数据连接池--> <environments default="development"> <environment id="development"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <mappers> <mapper resource="mapper/CarMapper.xml"/> </mappers> </configuration>
3、数据库连接信息:resource/db.properties
jdbc.driver=com.mysql.cj.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/bjpowernode-mybatis?useSSL=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC jdbc.username=root jdbc.password=zhixi158
4、Mybatis工具类:com.zhixi.utils.MabatisUtil
package com.zhixi.utils; 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 java.io.IOException; /** * @ClassName MybatisUtil * @Author zhangzhixi * @Description * @Date 2022-11-18 10:37 * @Version 1.0 */ public class MybatisUtil { /** * 线程工厂 */ private static SqlSessionFactory sqlSessionFactory; /** * 保证事务 */ private static final ThreadLocal<SqlSession> THREAD_LOCAL = new ThreadLocal<>(); static { try { sqlSessionFactory = new SqlSessionFactoryBuilder().build(Resources.getResourceAsStream("mybatis-config.xml")); } catch (IOException e) { e.printStackTrace(); } } /** * 获取连接通道 * * @return sqlSession操作数据库 */ public static SqlSession openSession() { SqlSession sqlSession = THREAD_LOCAL.get(); if (sqlSession == null) { sqlSession = sqlSessionFactory.openSession(); THREAD_LOCAL.set(sqlSession); } return sqlSession; } /** * 关闭连接对象 * @param sqlSession SQL会话 */ public static void close(SqlSession sqlSession){ if (THREAD_LOCAL.get() != null) { sqlSession.close(); THREAD_LOCAL.remove(); } } }
5、实体类:com.zhixi.pojo.Car
package com.zhixi.pojo; import lombok.Builder; import java.io.Serializable; import java.math.BigDecimal; /** * * @TableName t_car */ @Builder public class Car implements Serializable { /** * 主键自增 */ private Long id; /** * 汽车编号 */ private String carNum; /** * 汽车品牌 */ private String brand; /** * 厂家指导价 */ private BigDecimal guidePrice; /** * 生产日期 */ private String produceTime; /** * 汽车类型,包括:燃油车,电车,氢能源 */ private String carType; private static final long serialVersionUID = 1L; /** * 主键自增 */ 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 BigDecimal getGuidePrice() { return guidePrice; } /** * 厂家指导价 */ public void setGuidePrice(BigDecimal 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 carType) { this.carType = carType; } @Override public boolean equals(Object that) { if (this == that) { return true; } if (that == null) { return false; } if (getClass() != that.getClass()) { return false; } Car other = (Car) that; return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) && (this.getCarNum() == null ? other.getCarNum() == null : this.getCarNum().equals(other.getCarNum())) && (this.getBrand() == null ? other.getBrand() == null : this.getBrand().equals(other.getBrand())) && (this.getGuidePrice() == null ? other.getGuidePrice() == null : this.getGuidePrice().equals(other.getGuidePrice())) && (this.getProduceTime() == null ? other.getProduceTime() == null : this.getProduceTime().equals(other.getProduceTime())) && (this.getCarType() == null ? other.getCarType() == null : this.getCarType().equals(other.getCarType())); } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((getId() == null) ? 0 : getId().hashCode()); result = prime * result + ((getCarNum() == null) ? 0 : getCarNum().hashCode()); result = prime * result + ((getBrand() == null) ? 0 : getBrand().hashCode()); result = prime * result + ((getGuidePrice() == null) ? 0 : getGuidePrice().hashCode()); result = prime * result + ((getProduceTime() == null) ? 0 : getProduceTime().hashCode()); result = prime * result + ((getCarType() == null) ? 0 : getCarType().hashCode()); return result; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append(getClass().getSimpleName()); sb.append(" ["); sb.append("Hash = ").append(hashCode()); sb.append(", id=").append(id); sb.append(", carNum=").append(carNum); sb.append(", brand=").append(brand); sb.append(", guidePrice=").append(guidePrice); sb.append(", produceTime=").append(produceTime); sb.append(", carType=").append(carType); sb.append(", serialVersionUID=").append(serialVersionUID); sb.append("]"); return sb.toString(); } }
6、mapper接口:com.zhixi.mapper.CarMapper
package com.zhixi.mapper; import com.zhixi.pojo.Car; import org.apache.ibatis.annotations.MapKey; import org.apache.ibatis.annotations.Param; import java.math.BigDecimal; import java.util.List; import java.util.Map; /** * @author zhixi * @description 针对表【t_car】的数据库操作Mapper * @createDate 2022-11-19 22:36:54 * @Entity com.zhixi.pojo.Car */ public interface CarMapper { /** * 查询所有的记录 * * @return 汽车集合 */ List<Car> selectAllCar(); /** * 按照条件进行查询,最多只能够有一个条件成立 * * @param carNum 品牌编号 * @param brand 品牌名称 * @param carType 车辆类型 * @return 查询到的数据结果 */ List<Car> selectCarByChoose(@Param("carNum") String carNum, @Param("brand") String brand, @Param("carType") String carType); /** * 批量删除-in * * @param ids id数组 * @return 删除的记录条数 */ int deleteByIdsToIn(@Param("ids") Long[] ids); /** * 批量删除-or * * @param ids id数组 * @return 删除的记录条数 */ int deleteByIdsToOr(@Param("ids") Long[] ids); /** * 根据多条件查询Car * @param brand 品牌名称 * @param guidePrice 品牌价格 * @param carType 品牌类型 * @return 查询集合列表 */ List<Car> selectByMultiCondition(@Param("brand") String brand, @Param("guidePrice") BigDecimal guidePrice, @Param("carType") String carType); /** * 插入汽车 * @param car 汽车记录 * @return =1表示插入成功,否则失败 */ int insertSelective(Car car); /** * 根据id更新car * @param car 汽车实体 * @return =1表示更新成功,否则失败 */ int updateByPrimaryKey(Car car); /** * 批量添加,使用foreach标签 * @param cars 汽车集合 * @return 插入条数 */ int insertBatchByForeach(@Param("cars") List<Car> cars); }
7、Mapper-SQL文件:resource/CarMapper.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.zhixi.mapper.CarMapper"> <resultMap id="BaseResultMap" type="com.zhixi.pojo.Car"> <id property="id" column="id" jdbcType="BIGINT"/> <result property="carNum" column="car_num" jdbcType="VARCHAR"/> <result property="brand" column="brand" jdbcType="VARCHAR"/> <result property="guidePrice" column="guide_price" jdbcType="DECIMAL"/> <result property="produceTime" column="produce_time" jdbcType="CHAR"/> <result property="carType" column="car_type" jdbcType="VARCHAR"/> </resultMap> <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap"> select <include refid="Base_Column_List"/> from t_car where id = #{id,jdbcType=BIGINT} </select> <select id="selectAllByMap" resultType="java.util.Map"> select <include refid="Base_Column_List"/> from t_car </select> <sql id="Base_Column_List"> id,car_num,brand, guide_price,produce_time,car_type </sql> <select id="selectAllCar" resultType="com.zhixi.pojo.Car"> select <include refid="Base_Column_List"/> from t_car; </select> <select id="selectCarByChoose" resultType="com.zhixi.pojo.Car"> select <include refid="Base_Column_List"/> from t_car <where> <choose> <when test="carNum!=null and carNum!=''"> car_num = #{carNum,jdbcType=VARCHAR} </when> <when test="brand!=null and brand!=''"> brand = #{brand,jdbcType=VARCHAR} </when> <otherwise> car_type = #{carType,jdbcType=VARCHAR} </otherwise> </choose> </where> </select> <select id="selectByMultiCondition" resultType="com.zhixi.pojo.Car"> select <include refid="Base_Column_List"/> from t_car <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> <delete id="deleteByPrimaryKey" parameterType="java.lang.Long"> delete from t_car where id = #{id,jdbcType=BIGINT} </delete> <delete id="deleteByIdsToIn"> delete from t_car where id in <foreach collection="ids" item="id" open="(" close=")" separator=","> #{id} </foreach> </delete> <delete id="deleteByIdsToOr"> delete from t_car where <foreach collection="ids" item="id" separator="or"> id = #{id} </foreach> </delete> <insert id="insert" keyColumn="id" keyProperty="id" parameterType="com.zhixi.pojo.Car" useGeneratedKeys="true"> insert into t_car ( id, car_num, brand , guide_price, produce_time, car_type) values ( #{id,jdbcType=BIGINT}, #{carNum,jdbcType=VARCHAR}, #{brand,jdbcType=VARCHAR} , #{guidePrice,jdbcType=DECIMAL}, #{produceTime,jdbcType=CHAR}, #{carType,jdbcType=VARCHAR}) </insert> <insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.zhixi.pojo.Car" useGeneratedKeys="true"> insert into t_car <trim prefix="(" suffix=")" suffixOverrides=","> <if test="id != null">id,</if> <if test="carNum != null">car_num,</if> <if test="brand != null">brand,</if> <if test="guidePrice != null">guide_price,</if> <if test="produceTime != null">produce_time,</if> <if test="carType != null">car_type,</if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="id != null">#{id,jdbcType=BIGINT},</if> <if test="carNum != null">#{carNum,jdbcType=VARCHAR},</if> <if test="brand != null">#{brand,jdbcType=VARCHAR},</if> <if test="guidePrice != null">#{guidePrice,jdbcType=DECIMAL},</if> <if test="produceTime != null">#{produceTime,jdbcType=CHAR},</if> <if test="carType != null">#{carType,jdbcType=VARCHAR},</if> </trim> </insert> <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> <update id="updateByPrimaryKey" parameterType="com.zhixi.pojo.Car"> update t_car <set> <if test="carNum != null"> car_num = #{carNum,jdbcType=VARCHAR}, </if> <if test="brand != null"> brand = #{brand,jdbcType=VARCHAR}, </if> <if test="guidePrice != null"> guide_price = #{guidePrice,jdbcType=DECIMAL}, </if> <if test="produceTime != null"> produce_time = #{produceTime,jdbcType=CHAR}, </if> <if test="carType != null"> car_type = #{carType,jdbcType=VARCHAR}, </if> </set> where id = #{id,jdbcType=BIGINT}; </update> </mapper>
标签的使用:
resultMap标签
查询结果的列名和java对象的属性名对应不上怎么办?
- 第一种方式:as 给列起别名
- 第二种方式:使用resultMap进行结果映射
- 第三种方式:是否开启驼峰命名自动映射(配置settings)
为什么会出现resultMap标签?
/** * 查询所有的记录 * * @return 汽车集合 */ List<Car> selectAllCar();
因为我们在查询数据的时候,可能遇到实体类的属性名跟数据库的列名不一致的情况,比如car_num与实体类属性carNum对不上的情况,这时候查询到的数据为null。
第一种解决办法:as起别名
<select id="selectAllCar" resultType="com.zhixi.pojo.Car">
select id,
car_num as carNum,
brand,
guide_price as guidePrice,
produce_time as produceTime,
car_type as carType
from t_car;
</select>
第二种(推荐):resultMap
就是将数据库属性与实体类属性做一一对应
<resultMap id="BaseResultMap" type="com.zhixi.pojo.Car"> <id property="id" column="id" jdbcType="BIGINT"/> <result property="carNum" column="car_num" jdbcType="VARCHAR"/> <result property="brand" column="brand" jdbcType="VARCHAR"/> <result property="guidePrice" column="guide_price" jdbcType="DECIMAL"/> <result property="produceTime" column="produce_time" jdbcType="CHAR"/> <result property="carType" column="car_type" jdbcType="VARCHAR"/> </resultMap>
然后将select标签中的resultType换成resultMap="BaseResultMap"即可
第三种:是否开启驼峰自动映射
使用这种方式的前提是:属性名遵循Java的命名规范,数据库表的列名遵循SQL的命名规范。
Java命名规范:首字母小写,后面每个单词首字母大写,遵循驼峰命名方式。
SQL命名规范:全部小写,单词之间采用下划线分割。
比如以下的对应关系:
如何启用该功能,在mybatis-config.xml文件中进行配置:
<!--放在properties标签后面--> <settings> <setting name="mapUnderscoreToCamelCase" value="true"/> </settings>
sql标签与include标签
sql标签用来声明sql片段
include标签用来将声明的sql片段包含到某个sql语句当中
作用:代码复用。易维护。
<sql id="Base_Column_List"> id,car_num,brand, guide_price,produce_time,car_type </sql> <select id="selectAllCar" resultType="com.zhixi.pojo.Car"> select <include refid="Base_Column_List"/> from t_car; </select>
where if标签
提供了可选的查找文本功能。
where 元素只会在子元素返回任何内容的情况下才插入 “WHERE” 子句。
而且,若子句的开头为 “AND” 或 “OR”,where 元素也会将它们去除。
需求:多条件查询。
可能的条件包括:品牌(brand)、指导价格(guide_price)、汽车类型(car_type)
/** * 按照条件进行查询,最多只能够有一个条件成立 * @param carNum 品牌编号 * @param brand 品牌名称 * @param carType 车辆类型 * @return 查询到的数据结果 */ List<Car> selectCarByChoose(@Param("carNum") String carNum, @Param("brand") String brand, @Param("carType") String carType); /**
<select id="selectByMultiCondition" resultType="com.zhixi.pojo.Car"> select <include refid="Base_Column_List"/> from t_car <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>
测试:
@Test public void testSelectByMultiCondition() { SqlSession sqlSession = MybatisUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); List<Car> cars = mapper.selectByMultiCondition("宝马", new BigDecimal("25"), "燃油车"); cars.forEach(System.out::println); }
trim标签
trim标签的属性:
- prefix:在trim标签中的语句前添加内容
- suffix:在trim标签中的语句后添加内容
- prefixOverrides:前缀覆盖掉(去掉)
- suffixOverrides:后缀覆盖掉(去掉)
/** * 插入汽车 * @param car 汽车记录 * @return =1表示插入成功,否则失败 */ int insertSelective(Car car);
<insert id="insertSelective" keyColumn="id" keyProperty="id" parameterType="com.zhixi.pojo.Car" useGeneratedKeys="true"> insert into t_car <trim prefix="(" suffix=")" suffixOverrides=","> <if test="id != null">id,</if> <if test="carNum != null">car_num,</if> <if test="brand != null">brand,</if> <if test="guidePrice != null">guide_price,</if> <if test="produceTime != null">produce_time,</if> <if test="carType != null">car_type,</if> </trim> <trim prefix="values (" suffix=")" suffixOverrides=","> <if test="id != null">#{id,jdbcType=BIGINT},</if> <if test="carNum != null">#{carNum,jdbcType=VARCHAR},</if> <if test="brand != null">#{brand,jdbcType=VARCHAR},</if> <if test="guidePrice != null">#{guidePrice,jdbcType=DECIMAL},</if> <if test="produceTime != null">#{produceTime,jdbcType=CHAR},</if> <if test="carType != null">#{carType,jdbcType=VARCHAR},</if> </trim> </insert>
测试:
@Test public void testInsertSelective() { SqlSession sqlSession = MybatisUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); Car car = Car.builder(). carNum("106") .brand("奥迪A8L") .guidePrice(new BigDecimal("85.00")). produceTime("2018-08-01").carType("燃油车"). build(); int i = mapper.insertSelective(car); System.out.println(i); sqlSession.commit(); sqlSession.close(); }
set标签
主要使用在update语句当中,用来生成set关键字,同时去掉最后多余的“,”
比如我们只更新提交的不为空的字段,如果提交的数据是空或者"",那么这个字段我们将不更新。
/** * 根据id更新car * @param car 汽车实体 * @return =1表示更新成功,否则失败 */ int updateByPrimaryKey(Car car);
<update id="updateByPrimaryKey" parameterType="com.zhixi.pojo.Car"> update t_car <set> <if test="carNum != null"> car_num = #{carNum,jdbcType=VARCHAR}, </if> <if test="brand != null"> brand = #{brand,jdbcType=VARCHAR}, </if> <if test="guidePrice != null"> guide_price = #{guidePrice,jdbcType=DECIMAL}, </if> <if test="produceTime != null"> produce_time = #{produceTime,jdbcType=CHAR}, </if> <if test="carType != null"> car_type = #{carType,jdbcType=VARCHAR}, </if> </set> where id = #{id,jdbcType=BIGINT}; </update>
测试:
@Test public void testUpdateByPrimaryKey() { SqlSession sqlSession = MybatisUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); Car car = Car.builder() .id(9L) .brand("奥迪A4L") .guidePrice(new BigDecimal("35.00")). build(); /* 执行的SQL: ==> Preparing: update t_car SET brand = ?, guide_price = ? where id = ?; ==> Parameters: 奥迪A4L(String), 35.00(BigDecimal), 9(Long) <== Updates: 1 */ int i = mapper.updateByPrimaryKey(car); System.out.println(i); sqlSession.commit(); sqlSession.close(); }
choose、when、otherwise
有时候,我们不想使用所有的条件,而只是想从多个条件中选择一个使用。针对这种情况,MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。
匹配顺序是从第一个进行选择,第一个成立就执行第一个中的匹配,
如果第一个第二个数据都匹配的话,还是按第一个中的执行。
语法格式:
<choose> <when></when> <when></when> <when></when> <otherwise></otherwise> </choose>
需求:
先根据品牌查询,如果没有提供品牌,再根据指导价格查询,如果没有提供指导价格,就根据生产日期查询。
/** * 按照条件进行查询,最多只能够有一个条件成立 * * @param carNum 品牌编号 * @param brand 品牌名称 * @param carType 车辆类型 * @return 查询到的数据结果 */ List<Car> selectCarByChoose(@Param("carNum") String carNum, @Param("brand") String brand, @Param("carType") String carType);
<select id="selectCarByChoose" resultType="com.zhixi.pojo.Car"> select <include refid="Base_Column_List"/> from t_car <where> <choose> <when test="carNum!=null and carNum!=''"> car_num = #{carNum,jdbcType=VARCHAR} </when> <when test="brand!=null and brand!=''"> brand = #{brand,jdbcType=VARCHAR} </when> <otherwise> car_type = #{carType,jdbcType=VARCHAR} </otherwise> </choose> </where> </select>
测试:
@Test public void testSelectCarByChoose() { SqlSession sqlSession = MybatisUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); /* ==> Preparing: select id,car_num,brand, guide_price,produce_time,car_type from t_car WHERE car_num = ? ==> Parameters: 103(String) <== Columns: id, car_num, brand, guide_price, produce_time, car_type <== Row: 5, 103, 丰田, 25.80, 2022-01-01, 燃油车 <== Total: 1 */ List<Car> cars = mapper.selectCarByChoose("103", "丰田", null); cars.forEach(System.out::println); }
foreach标签
场景
批量删除:
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','新能源')
批量删除:使用in
/** * 批量删除 * * @param ids id数组 * @return 删除的记录条数 */ int deleteByIdsToIn(@Param("ids") Long[] ids);
<delete id="deleteByIdsToIn"> delete from t_car where id in <foreach collection="ids" item="id" open="(" close=")" separator=","> #{id} </foreach> </delete>
测试:
@Test public void testDeleteByIds() { SqlSession sqlSession = MybatisUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); Long[] ids = {1L, 2L}; /* ==> Preparing: delete from t_car where id in ( ? , ? ) ==> Parameters: 1(Long), 2(Long) <== Updates: 2 */ int delNum = mapper.deleteByIdsToIn(ids); System.out.println(delNum); sqlSession.commit(); sqlSession.close(); }
批量删除:使用or
/** * 批量删除-or * * @param ids id数组 * @return 删除的记录条数 */ int deleteByIdsToOr(@Param("ids") Long[] ids);
<delete id="deleteByIdsToOr"> delete from t_car where <foreach collection="ids" item="id" separator="or"> id = #{id} </foreach> </delete>
测试:
@Test public void testDeleteByIdsToOr() { SqlSession sqlSession = MybatisUtil.openSession(); CarMapper mapper = sqlSession.getMapper(CarMapper.class); Long[] ids = {5L, 6L}; /* ==> Preparing: delete from t_car where id = ? or id = ? ==> Parameters: 5(Long), 6(Long) <== Updates: 2 */ int delNum = mapper.deleteByIdsToOr(ids); System.out.println(delNum); sqlSession.commit(); sqlSession.close(); }
批量添加:
/** * 批量添加,使用foreach标签 * @param cars 汽车集合 * @return 插入条数 */ int insertBatchByForeach(@Param("cars") List<Car> cars);
<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(){ CarMapper mapper = MybatisUtil.openSession().getMapper(CarMapper.class); Car car1 = new Car(null, "2001", "兰博基尼", new BigDecimal("100.0"), "1998-10-11", "燃油车"); Car car2 = new Car(null, "2001", "兰博基尼", new BigDecimal("100.0"), "1998-10-11", "燃油车"); Car car3 = new Car(null, "2001", "兰博基尼", new BigDecimal("100.0"), "1998-10-11", "燃油车"); List<Car> cars = Arrays.asList(car1, car2, car3); /* ==> Preparing: insert into t_car values (null,?,?,?,?,?) , (null,?,?,?,?,?) , (null,?,?,?,?,?) ==> Parameters: 2001(String), 兰博基尼(String), 100.0(BigDecimal), 1998-10-11(String), 燃油车(String), 2001(String), 兰博基尼(String), 100.0(BigDecimal), 1998-10-11(String), 燃油车(String), 2001(String), 兰博基尼(String), 100.0(BigDecimal), 1998-10-11(String), 燃油车(String) <== Updates: 3 */ int count = mapper.insertBatchByForeach(cars); System.out.println("插入了几条记录" + count); MybatisUtil.openSession().commit(); MybatisUtil.openSession().close(); }