12、动态SQL
什么是动态SQL?
动态 SQL 是 MyBatis 的强大特性之一。例如拼接时要确保不能忘记添加必要的空格,还要注意去掉列表最后一个列名的逗号。利用动态 SQL,可以彻底摆脱这种痛苦。
如果你之前用过 JSTL 或任何基于类 XML 语言的文本处理器,你对动态 SQL 元素可能会感觉似曾相识。在 MyBatis 之前的版本中,需要花时间了解大量的元素。借助功能强大的基于 OGNL 的表达式,MyBatis 3 替换了之前的大部分元素,大大精简了元素种类,现在要学习的元素种类比原来的一半还要少。
- if
- choose (when, otherwise)
- trim (where, set)
- foreach
环境搭建:
依赖:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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
1 2 3 4 | 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标签?
1 2 3 4 5 6 | /** * 查询所有的记录 * * @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
就是将数据库属性与实体类属性做一一对应
1 2 3 4 5 6 7 8 | <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文件中进行配置:
1 2 3 4 | <!--放在properties标签后面--> <settings> <setting name= "mapUnderscoreToCamelCase" value= "true" /> </settings> |
sql标签与include标签
sql标签用来声明sql片段
include标签用来将声明的sql片段包含到某个sql语句当中
作用:代码复用。易维护。
1 2 3 4 5 6 7 8 | <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)
1 2 3 4 5 6 7 8 9 | /** * 按照条件进行查询,最多只能够有一个条件成立 * @param carNum 品牌编号 * @param brand 品牌名称 * @param carType 车辆类型 * @return 查询到的数据结果 */ List<Car> selectCarByChoose( @Param ( "carNum" ) String carNum, @Param ( "brand" ) String brand, @Param ( "carType" ) String carType); /** |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <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> |
测试:
1 2 3 4 5 6 7 | @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:后缀覆盖掉(去掉)
1 2 3 4 5 6 | /** * 插入汽车 * @param car 汽车记录 * @return =1表示插入成功,否则失败 */ int insertSelective(Car car); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <br><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> |
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @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关键字,同时去掉最后多余的“,”
比如我们只更新提交的不为空的字段,如果提交的数据是空或者"",那么这个字段我们将不更新。
1 2 3 4 5 6 | /** * 根据id更新car * @param car 汽车实体 * @return =1表示更新成功,否则失败 */ int updateByPrimaryKey(Car car); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <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> |
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | @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 语句。
匹配顺序是从第一个进行选择,第一个成立就执行第一个中的匹配,
如果第一个第二个数据都匹配的话,还是按第一个中的执行。
语法格式:
1 2 3 4 5 6 | <choose> <when></when> <when></when> <when></when> <otherwise></otherwise> </choose> |
需求:
先根据品牌查询,如果没有提供品牌,再根据指导价格查询,如果没有提供指导价格,就根据生产日期查询。
1 2 3 4 5 6 7 8 9 | /** * 按照条件进行查询,最多只能够有一个条件成立 * * @param carNum 品牌编号 * @param brand 品牌名称 * @param carType 车辆类型 * @return 查询到的数据结果 */ List<Car> selectCarByChoose( @Param ( "carNum" ) String carNum, @Param ( "brand" ) String brand, @Param ( "carType" ) String carType); |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <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> |
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | @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标签
场景
批量删除:
1 2 | delete from t_car where id in (1,2,3); delete from t_car where id = 1 or id = 2 or id = 3; |
批量添加:
1 2 3 4 | 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
1 2 3 4 5 6 7 | /** * 批量删除 * * @param ids id数组 * @return 删除的记录条数 */ int deleteByIdsToIn( @Param ( "ids" ) Long[] ids); |
1 2 3 4 5 6 7 8 | <delete id= "deleteByIdsToIn" > delete from t_car where id in <foreach collection= "ids" item= "id" open= "(" close= ")" separator= "," > #{id} </foreach> </delete> |
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @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
1 2 3 4 5 6 7 | /** * 批量删除-or * * @param ids id数组 * @return 删除的记录条数 */ int deleteByIdsToOr( @Param ( "ids" ) Long[] ids); |
1 2 3 4 5 6 7 8 | <delete id= "deleteByIdsToOr" > delete from t_car where <foreach collection= "ids" item= "id" separator= "or" > id = #{id} </foreach> </delete> |
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | @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(); } |
批量添加:
1 2 3 4 5 6 | /** * 批量添加,使用foreach标签 * @param cars 汽车集合 * @return 插入条数 */ int insertBatchByForeach( @Param ( "cars" ) List<Car> cars); |
1 2 3 4 5 6 | <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> |
测试:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @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(); } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?