- 动态SQL
- if 标签
- where 标签
- trim 标签
- set 标签
- choose when otherwise
- foreach 标签
- sql 标签与include 标签
十二、★动态SQL
- 准备工作:
- 模块名:
mybatis-009-dynamic-sql
- 打包方式:
jar
- 引入依赖:
mysql
驱动依赖、mybatis
依赖、logback
依赖、junit
依赖。 - 引入配置文件:
jdbc.properties
、mybatis-config.xml
、logback.xml
- 创建
pojo
类:Car
- 创建
Mapper
接口:com.f.mybatis.mapper.CarMapper
- 创建
Mapper
接口对应的映射文件:com/f/mybatis/mapper/CarMapper.xml
- 创建单元测试:
CarMapperTest
- 创建工具类:
SqlSessionUtil
- 模块名:
12.1 if 标签
需求:多条件查询。可能的条件包括:品牌(
brand
)、指导价格(guide_price
)、汽车类型(car_type
)。还是像
10.1
小节所说的三步走:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package com.f.mybatis.mapper;
import com.f.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author fzy
* @date 2024/1/10 15:29
*/
public interface CarMapper {
/**
* 多条件查询
* @param brand 品牌
* @param guidePrice 指导价
* @param carType 汽车类型
* @return
*/
List<Car> selectByMultiCondition( String brand,
Double guidePrice,
; String carType)
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<mapper namespace="com.f.mybatis.mapper.CarMapper">
<select id="selectByMultiCondition" resultType="Car">
SELECT *
FROM t_car
WHERE 1 = 1 # 1 = 1是为了避免下面三个test都为false的情况
<!--
1.if标签中的test属性是必须的
2,if标签中test属性的值是true或者false
3.如果test是true,则if标签中的sql内容就会拼接,反正则不会拼接。
4.test中可以使用的是:
多参数:当使用了@Param注解,那么test中要出现的就是@Param注解指定的参数名,例如@Param("brand"),那么这里只能使用brand
多参数:当没有使用@Param注解,那么test中要出现的是:param1、param2、param3... arg0、arg1、arg2...
单参数:当使用了POJO,那么test中要出现的就是POJO类的属性名
5.在mybatis的动态sql的test表达式中,不能使用&&,只能使用and
-->
<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>1
2
3
4
5
6
7
8
9
10
public void testSelectByMultiCondition() {
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.selectByMultiCondition("问界", null, "新能源");
cars.forEach(car -> {
System.out.println(car);
});
SqlSessionUtil.close(sqlSession);
}
12.2 where 标签
where
标签的作用:让where
子句更加动态智能。- 所有条件都为空时,
where
标签保证不会生成where
子句。 - 自动去除某些条件前面多余的
and
或or
。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package com.f.mybatis.mapper;
import com.f.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author fzy
* @date 2024/1/10 15:29
*/
public interface CarMapper {
/**
* 多条件查询,使用where标签,让where子句更加智能
*
* @param brand
* @param guidePrice
* @param carType
* @return
*/
List<Car> selectByMultiConditionWithWhere( String brand,
Double guidePrice,
; String carType)
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<mapper namespace="com.f.mybatis.mapper.CarMapper">
<select id="selectByMultiConditionWithWhere" resultType="Car">
SELECT * FROM t_car
/*where标签是专门负责where子句动态生成的*/
<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>1
2
3
4
5
6
7
8
9
10
public void testSelectByMultiConditionWithWhere() {
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.selectByMultiConditionWithWhere("问界", null, "新能源");
cars.forEach(car -> {
System.out.println(car);
});
SqlSessionUtil.close(sqlSession);
}- 所有条件都为空时,
12.3 trim 标签
trim
标签的属性:prefix
:在trim
标签中的语句前添加内容suffix
:在trim
标签中的语句后添加内容prefixOverrides
:前缀覆盖掉(去掉)suffixOverrides
:后缀覆盖掉(去掉)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package com.f.mybatis.mapper;
import com.f.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author fzy
* @date 2024/1/10 15:29
*/
public interface CarMapper {
/**
* 多条件查询,使用trim标签
*
* @param brand
* @param guidePrice
* @param carType
* @return
*/
List<Car> selectByMultiConditionWithTrim( String brand,
Double guidePrice,
; String carType)
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<mapper namespace="com.f.mybatis.mapper.CarMapper">
<select id="selectByMultiConditionWithTrim" resultType="Car">
SELECT * FROM t_car
<!--
prefix: 加前缀
prefixOverrides: 删除前缀
suffix: 加后缀
suffixOverrides: 删除后缀
<trim prefix="" prefixOverrides="" suffix="" suffixOverrides=""></trim>
-->
<!--prefix="where" 是在trim标签所有内容的前面添加 where-->
<!--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>1
2
3
4
5
6
7
8
9
10
public void testSelectByMultiConditionWithTrim() {
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.selectByMultiConditionWithTrim("问界", null, "新能源");
cars.forEach(car -> {
System.out.println(car);
});
SqlSessionUtil.close(sqlSession);
}
12.4 set 标签
主要使用在
update
语句当中,用来生成set
关键字,同时去掉最后多余的,
。比如我们只更新提交的不为空的字段,如果提交的数据是空或者
""
,那么这个字段我们将不更新。(set
+if
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20package com.f.mybatis.mapper;
import com.f.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author fzy
* @date 2024/1/10 15:29
*/
public interface CarMapper {
/**
* 更新数据,使用set标签
*
* @param car
* @return
*/
int updateBySet(Car car);
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<mapper namespace="com.f.mybatis.mapper.CarMapper">
<update id="updateBySet">
UPDATE t_car
<set>
<if test="carNum != null and carNum != ''">car_num = #{carNum},</if>
<if test="brand != null and brand != ''">brand = #{brand},</if>
<if test="guidePrice != null and guidePrice != ''">guide_price = #{guidePrice},</if>
<if test="produceTime != null and produceTime != ''">produce_time = #{produceTime},</if>
<if test="carType != null and carType != ''">car_type = #{carType},</if>
</set>
<where>
id = #{id}
</where>
</update>
</mapper>1
2
3
4
5
6
7
8
9
10
11
12
public void testUpdateBySet() {
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Car car = new Car();
car.setId(4L);
car.setCarType("氢能");
int count = mapper.updateBySet(car);
System.out.println(count);
sqlSession.commit();
SqlSessionUtil.close(sqlSession);
}
12.5 choose when otherwise
这三个标签是在一起使用的:
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
10
11if(){
}else if(){
}else if(){
}else if(){
}else{
}只有一个分支会被选择。
需求:先根据品牌查询,如果没有提供品牌,再根据指导价格查询,如果没有提供指导价格,就根据汽车类型查询。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24package com.f.mybatis.mapper;
import com.f.mybatis.pojo.Car;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* @author fzy
* @date 2024/1/10 15:29
*/
public interface CarMapper {
/**
* 使用choose when otherwise标签
*
* @param brand
* @param guidePrice
* @param carType
* @return
*/
List<Car> selectByChoose( String brand,
Double guidePrice,
; String carType)
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<mapper namespace="com.f.mybatis.mapper.CarMapper">
<select id="selectByChoose" resultType="Car">
SELECT * FROM t_car
<where>
<choose>
<when test="brand != null and brand != ''">brand = #{brand}</when>
<when test="guidePrice != null and guidePrice != ''">guide_price > #{guidePrice}</when>
<otherwise>car_type = #{carType}</otherwise>
</choose>
</where>
</select>
</mapper>1
2
3
4
5
6
7
8
9
10
public void testSelectByChoose() {
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.selectByChoose("问界", null, "新能源");
cars.forEach(car -> {
System.out.println(car);
});
SqlSessionUtil.close(sqlSession);
}
12.6 foreach 标签
- 循环数组或集合,动态生成 sql。
批量删除
1 | package com.f.mybatis.mapper; |
1 |
|
1 |
|
批量添加
1 | package com.f.mybatis.mapper; |
1 |
|
1 |
|
12.7 sql 标签与include 标签
sql 标签用来声明 sql 片段。
include 标签用来将声明的 sql 片段包含到某个 sql 语句当中。
- 作用:代码复用,易维护。
1
2
3
4
5
6
7
8
9
10
11
12
13<sql id="carColumnName">id,car_num AS carNum,brand,guide_price AS guidePrice,produce_time AS produceTime,car_type AS carType</sql>
<select id="selectAllRetMap" resultType="map">
select <include refid="carColumnName"/> from t_car
</select>
<select id="selectAllRetListMap" resultType="map">
select <include refid="carColumnName"/> carType from t_car
</select>
<select id="selectByIdRetMap" resultType="map">
select <include refid="carColumnName"/> from t_car where id = #{id}
</select>