需求:
有2张表,一张活动信息表(activity_info), 一张参加活动的商品表(activity_sku)
查询当前在活动期间的,且存在于我输入的商品(sku)列表中的商品(sku)的编号id
参考:63 尚上优选项目-平台管理端-营销活动管理-营销活动接口(开发匹配sku列表接口)_哔哩哔哩_bilibili
SQL语句:
sql语句:
<?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.atguigu.ssyx.activity.mapper.ActivityInfoMapper"><!--如果之前参加过,且活动正在进行-当前时间在活动有效期时间内,则排除商品--><!-- SQL 语句:select asku.sku_idfrom activity_info activityinner join activity_sku asku on activity.id=asku.activity_idwhere asku.sku_id in (1,2,3) #下面的 foreach 将List<long>变成SQL中的数组形式(1,2,3)and now() between activity.start_time and activity.end_time--><select id="selectSkuInfoIdListExist" resultType="Long">select asku.sku_idfrom activity_info activityinner join activity_sku asku on activity.id=asku.activity_id<where> <!--where, if标签:MyBatis框架的动态SQL元素, 用于根据条件构建SQL语句的一部分--><if test="skuIdList != null">and asku.sku_id in <!--这里的and是为了说明和if的并列关系--><foreach collection="skuIdList" item="skuId" index="index" open="(" separator="," close=")">#{skuId}</foreach></if></where>and now() between activity.start_time and activity.end_time</select>
</mapper>
java mapper定义部分:
java">package com.atguigu.ssyx.activity.mapper;import com.atguigu.ssyx.model.activity.ActivityInfo;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Repository;import java.util.List;/*** <p>* 活动表 Mapper 接口*/
@Repository
public interface ActivityInfoMapper extends BaseMapper<ActivityInfo> {List<Long> selectSkuInfoIdListExist(@Param("skuIdList") List<Long> skuInfoIdList);
}
执行下面sql语句,效果如下:
sql">select *
from activity_info activity
inner join activity_sku asku on activity.id=asku.activity_id
where asku.sku_id in (1,2,3)
and now() between activity.start_time and activity.end_time
解释:
这段SQL语句是在尝试结合MyBatis框架的XML映射文件语法和普通SQL语句来查询数据。下面是对这段代码的逐部分解释,以及关于<where>
标签下使用and
的原因和#{}
的用法。
SQL语句解释
- 基本查询结构:
- 从
activity_info
表(别名为activity
)和activity_sku
表(别名为asku
)中选择asku.sku_id
。 - 使用
INNER JOIN
来连接这两个表,条件是activity.id = asku.activity_id
。
- 从
- 条件查询:
<where>
标签和<if>
标签是MyBatis框架的动态SQL元素,用于根据条件构建SQL语句的一部分。<if test="skuIdList != null">
检查skuIdList
变量是否不为null
。如果条件为真,则执行内部的SQL片段。<foreach>
标签用于遍历skuIdList
集合,并为每个元素生成一个sku_id
的值,这些值被用于IN
查询中,以检查asku.sku_id
是否在这些值中。
- 固定条件:
and now() between activity.start_time and activity.end_time
是另一个固定条件,检查当前时间是否在活动的时间范围内。
为什么 <where>
标签下要用 and
?
在MyBatis中,<where>
标签用于智能地添加WHERE
关键字到SQL语句中,并且会自动处理前面的逻辑运算符(如AND
或OR
),以避免语法错误。当你在<where>
标签内部开始添加条件时,如果<where>
是第一个条件(即没有前面的条件),它不会添加WHERE
关键字前的AND
或OR
。但是,如果<where>
标签内部有多个条件或者前面已经有条件(比如通过<if>
标签添加的条件),并且你想在这些条件之间使用AND
来连接,那么你就需要在第一个条件前显式地加上AND
。这是因为<where>
标签只负责智能地添加WHERE
关键字,而不负责处理条件之间的逻辑连接符。
#{}
的惯例用法
在MyBatis中,#{}
用于参数替换,并防止SQL注入。它告诉MyBatis将变量值安全地插入到SQL语句中。例如,#{skuId}
会被替换为skuIdList
集合中当前遍历到的skuId
的值。这种方式比直接使用字符串拼接来构建SQL语句要安全得多,因为它可以自动处理参数值的转义,从而防止SQL注入攻击。
总结
<where>
标签下的and
是为了在添加多个条件时,确保SQL语句的逻辑正确性。#{}
用于参数替换,是MyBatis中防止SQL注入的推荐做法。- 注意,原SQL语句中的
where asku.sku_id in (1,2,3)
部分看起来是一个错误或遗留代码,因为它与<where>
和<if>
标签的逻辑冲突。在实际应用中,应该只使用其中一种方式来指定条件。