问题:
有的时候我们需要实现批量删除: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 …;
以上情况地sql语句都是动态的,因此需要我们来进行SQL语句的动态拼接。在MyBatis中是通过不同标签来实现SQL语句的动态的。下面来一一讨论使用标签。
准备工作
几种常用标签
if标签
需求:多条件查询。
可能的条件包括:记录id(id)、指导价格(guide_price)、汽⻋类型(car_type)
实战
CarMapper接口中方法
/***
* 多条件查询
* @param id
* @param brand
* @param guidePrice
* @return
*/
List<Car> multiConditionSelect(@Param("id") Long id,@Param("brand") String brand,@Param("guidePrice") Double guidePrice);
SQL语句映射文件代码
<select id="multiConditionSelect" resultType="Car">
select * from t_car where
<if test="id != null and id != ''">
id = #{id}
</if>
<if test="brand != null and brand != ''">
and brand like "%"#{brand}"%"
</if>
<if test="guidePrice != null and guidePrice != ''">
and guide_price > #{guidePrice}
</if>
</select>
基本语法:test后面语句的结果如果为true,则该if标签的语句生效,否则不生效。
细节:if标签test后面中的变量是@param起的别名,如果没用@param就是系统默认的arf0…param1…,如果参数是bean类则test后面的变量是bean类的属性名。
测试代码
@Test
public void testMultiConditionSelect(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.multiConditionSelect(59L,"大众",5.0);
cars.forEach(car -> System.out.println(car));
sqlSession.close();
}
可以看出三个参数都不为空,且不为null,执行一下看一下结果
可以看出sql语句和预想的一样。
我们将测试代码中
List<Car> cars = mapper.multiConditionSelect(59L,"大众",5.0);
的第一个参数置空,并再次执行,结果如下
因为我们将第一个参数置空后SQL语句变为了 select * from t_car where and brand like “%”?“%” and guide_price > ? 可以看出多了一个and,如何解决呢?很简单,我们只需要在where后面加上 1=1 就可以了。更改后再次执行,结果如下
成功解决
但是这样的话我们需要在第一个条件前面也加上and,否则第一个条件不为空的时候也会出错
where标签
where标签的作⽤:让where⼦句更加动态智能。
所有条件都为空时,where标签保证不会⽣成where⼦句。
⾃动去除某些条件前⾯多余的and或or。
在上面if语句的使用中我们发现每个条件前面加不加and是个麻烦的事情,where标签很好地解决了上面地问题
CarMapper接口中方法
/***
* 使用Where标签,使Where子句更加智能
* @param id
* @param brand
* @param guidePrice
* @return
*/
List<Car> multiConditionSelectWithWhere(@Param("id") Long id,@Param("brand") String brand,@Param("guidePrice") Double guidePrice);
SQL映射文件中代码
<select id="multiConditionSelectWithWhere" resultType="Car">
select * from t_car
<where>
<if test="id != null and id != ''">
and id = #{id}
</if>
<if test="brand != null and brand != ''">
and brand like "%"#{brand}"%"
</if>
<if test="guidePrice != null and guidePrice != ''">
and guide_price > #{guidePrice}
</if>
</where>
</select>
细节解析:使用where标签,会自动地在t_car后面添加去除where,当后面条件为空,where不会生成,反之生成,同时还会智能去除某些情况下if子句中前面地and但后面地不会去除。
测试代码:
@Test
public void testMultiConditionSelectWithWhere(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.multiConditionSelectWithWhere(null,"",null);
cars.forEach(car -> System.out.println(car));
sqlSession.close();
}
执行结果
可以看出在三个参数都为空地情况下where子句智能地没有添加,其他情况不在一一测试。
trim 标签
基本语法
trim标签的属性:
prefix:在trim标签中的语句前添加内容
suffix:在trim标签中的语句后添加内容
prefixOverrides:前缀覆盖掉(去掉)
suffixOverrides:后缀覆盖掉(去掉)
实战
CarMapper接口中方法代码
/***
* 根据多条件啊查询使用trim标签
* @param id
* @param brand
* @param guidePrice
* @return
*/
List<Car> multiConditionSelectWithTrim(@Param("id") Long id,@Param("brand") String brand,@Param("guidePrice") Double guidePrice);
SQL语句映射文件中代码
<select id="multiConditionSelectWithTrim" resultType="Car">
select * from t_car
<trim prefix="where" suffixOverrides="and">
<if test="id != null and id != ''">
id = #{id} and
</if>
<if test="brand != null and brand != ''">
brand like "%"#{brand}"%" and
</if>
<if test="guidePrice != null and guidePrice != ''">
guide_price > #{guidePrice}
</if>
</trim>
</select>
prefix="where"加一个前缀,在t_car后面我们就不用自己写where了
suffixOverrides=“and” 去除某些条件后面地and,如果第一个第三个参数都为空,第二个条件后面地and会不会智能去除?
测试代码
@Test
public void testMultiConditionSelectWithTrim(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.multiConditionSelectWithTrim(null,"大众",null);
cars.forEach(car -> System.out.println(car));
sqlSession.close();
}
测试结果
显然智能去除了第二个条件后面的and,如果三个条件都为空,前缀where还会添加吗?答案是否定地,不会添加,trim标签还是很智能地
set标签
语法
1.主要使⽤在update语句当中,⽤来⽣成set关键字,同时去掉最后多余的“,”
需求:⽐如我们只更新提交的不为空的字段,如果提交的数据是空或者"",那么这个字段我们将不更新。(set标签if标签混用)
实战
CarMapper接口中方法代码
/***
* 使用set标签完成根据id修改记录
* <set><set/>生成set同时去掉多余 ,
* @return
*/
int updateBySet(Car car);
SQL语句映射文件中代码
<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}
</update>
测试代码
@Test
public void TestUpdateBySet(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Car car = new Car(59L,"7777",null,null,null,null);
int count = mapper.updateBySet(car);
System.out.println("成功" + count + "条");
sqlSession.commit();
sqlSession.close();
}
执行结果
可以看出生成了set并且语句后面多余地’ , '被智能去除
choose when oterwise标签
基本语法
三者一块使用
语法格式
<choose>
<when></when>
<when></when>
<when></when>
<otherwise></otherwise>
</choose>
相当于
if(){
}else if(){
}else if(){
}else if(){
}else{
}
只有⼀个分⽀会被选择!!!!
需求:先根据品牌查询,如果没有提供品牌,再根据指导价格查询,如果没有提供指导价格,就根据⽣
产⽇期查询。
实战
CarMapper接口中方法
/***
* 使用choose 标签进行查询
* @return
*/
List<Car> selectWithChoose(@Param("brand") String brand,@Param("guidePrice") Double guidePrice,@Param("carType") String carType);
SQL映射文件中代码
<select id="selectWithChoose" resultType="Car">
select * from t_car
<where>
<choose>
<when test="brand != '' and brand != null">
brand like "%"#{brand}"%"
</when>
<when test="guidePrice != '' and guidePrice != null">
guide_price > #{guidePrice}
</when>
<otherwise>
car_type = #{carType}
</otherwise>
</choose>
</where>
</select>
测试代码
@Test
public void testSelectWithChoose(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
List<Car> cars = mapper.selectWithChoose("",null,"新能源");
cars.forEach(car -> System.out.println(car));
sqlSession.close();
}
执行结果
foreach标签
基本用法
和java中地foreach类似,一共有五个参数,解释如下
collection:集合或数组
item:集合或数组中的元素
separator:分隔符
open:foreach标签中所有内容的开始
close:foreach标签中所有内容的结束
需求
批量添加
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','新能源')
实战
CarMapper接口中方法代码
/***
* 利用foreach标签进行批量插入
* @return
*/
int insertBatchByForeach(@Param("cars") List<Car> cars);
SQL映射文件中代码
<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(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Car car1 = new Car(null,"1100","拖拉机1",10.0,"2001-10-11","燃油车");
Car car2 = new Car(null,"1100","拖拉机2",10.0,"2001-10-11","燃油车");
Car car3 = new Car(null,"1100","拖拉机3",10.0,"2001-10-11","燃油车");
List<Car> cars = new ArrayList<>();
cars.add(car1);
cars.add(car2);
cars.add(car3);
mapper.insertBatchByForeach(cars);
sqlSession.commit();
sqlSession.close();
}
执行结果
大家注意拼接成地sql语句还是很好理解的
需求
批量删除 分别使用or和in
delete from t_car where id in(1,2,3);
delete from t_car where id = 1 or id = 2 or id = 3;
实战1(使用in)
CarMapper接口中的方法代码
/***
* 利用foreach进行批量删除
* in(id1,id2.....)
* @param ids
* @return
*/
int deleteBatchByForeach(@Param("ids") Long[] ids);
SQL映射文件代码
<delete id="deleteBatchByForeach">
delete from t_car
<where>
id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</where>
</delete>
测试代码
@Test
public void testDeleteBatchByForeach(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Long[] ids = {68L,69L,70L};
int count = mapper.deleteBatchByForeach(ids);
System.out.println(count);
sqlSession.commit();
sqlSession.close();
}
执行结果
实战2 使用or实现批量删除
CarMapper接口中方法代码
/***
* 利用foreach进行批量删除
* or
* @param ids
* @return
*/
int deleteBatchByForeach2(@Param("ids") Long[] ids);
SQL映射文件中代码
<delete id="deleteBatchByForeach2">
delete from t_car where
<foreach collection="ids" item="id" separator="or">
id = #{id}
</foreach>
</delete>
测试代码
@Test
public void testDeleteBatchByForeach2(){
SqlSession sqlSession = SqlSessionUtil.openSession();
CarMapper mapper = sqlSession.getMapper(CarMapper.class);
Long[] ids = {71L,72L,73L};
int count = mapper.deleteBatchByForeach2(ids);
System.out.println(count);
sqlSession.commit();
sqlSession.close();
}
测试结果
将基本语法与测试结果中拼接的sql语句一块理解,还是很好理解的😊
sql标签与include标签
基本用法:
sql标签⽤来声明sql⽚段
include标签⽤来将声明的sql⽚段包含到某个sql语句当中
作⽤:代码复⽤。易维护。
SQL映射文件中代码
<sql id="carCols">id,car_num carNum,brand,guide_price guidePrice,produce_t
ime produceTime,car_type carType</sql>
<select id="selectAllRetMap" resultType="map">
select <include refid="carCols"/> from t_car
</select>
<select id="selectAllRetListMap" resultType="map">
select <include refid="carCols"/> carType from t_car
</select>
<select id="selectByIdRetMap" resultType="map">
select <include refid="carCols"/> from t_car where id = #{id}
</select>
总结结束,希望对你能有所帮助