mybatis编写sql语句时的问题

打印attrList的结果为:[{11=32}, {12=33}]
执行:

    <select id="searchSkus" resultMap="SkuResultMap">
        SELECT DISTINCT s.id, s.sku_name, s.price, s.sku_default_img
        FROM sku s
        INNER JOIN sku_attr_value sav ON s.id = sav.sku_id
        <where>
            s.is_deleted = 0
            <if test="keyword != null and keyword != ''">
                AND s.sku_name LIKE CONCAT('%', #{keyword}, '%')
            </if>
            <if test="tmId != null and tmId != ''">
                AND s.tm_id = #{tmId}
            </if>
            <if test="attrList != null and !attrList.isEmpty()">
                AND (
                <foreach collection="attrList" item="pair" separator=" OR ">
                    (sav.attr_id = #{pair.key} AND sav.value_id = #{pair.value})
                </foreach>
                )
            </if>
        </where>
        <choose>
            <when test="order == '1:asc'">
                ORDER BY s.id ASC
            </when>
            <when test="order == '1:desc'">
                ORDER BY s.id DESC
            </when>
            <when test="order == '2:asc'">
                ORDER BY s.price ASC
            </when>
            <when test="order == '2:desc'">
                ORDER BY s.price DESC
            </when>
            <otherwise>
                ORDER BY s.id
            </otherwise>
        </choose>
        LIMIT #{offset}, #{pageSize}
    </select>

之后,用idea的mybatis log插件打印出的sql语句为:


    SELECT
        DISTINCT s.id,
        s.sku_name,
        s.price,
        s.sku_default_img 
    FROM
        sku s 
    INNER JOIN
        sku_attr_value sav 
            ON s.id = sav.sku_id 
    WHERE
        s.is_deleted = 0 
        AND s.sku_name LIKE CONCAT('%', '手机', '%') 
        AND (
            (
                sav.attr_id = 11 
                AND sav.value_id = 32
            ) 
            OR (
                sav.attr_id = 12 
                AND sav.value_id = 33
            ) 
        ) 
    ORDER BY
        s.id DESC LIMIT 0,
        10;

但将


            <if test="attrList != null and !attrList.isEmpty()">
                AND (
                (sav.attr_id = 11 AND sav.value_id = 32)
                OR
                (sav.attr_id = 12 AND sav.value_id = 33)
                )
            </if>

换为:

            <if test="attrList != null and !attrList.isEmpty()">
                AND (
                <foreach collection="attrList" item="pair" separator=" OR ">
                    (sav.attr_id = #{pair.key} AND sav.value_id = #{pair.value})
                </foreach>
                )
            </if>

之后,打印的sql语句却变成了:

    SELECT
        DISTINCT s.id,
        s.sku_name,
        s.price,
        s.sku_default_img 
    FROM
        sku s 
    INNER JOIN
        sku_attr_value sav 
            ON s.id = sav.sku_id 
    WHERE
        s.is_deleted = 0 
        AND s.sku_name LIKE CONCAT('%', ?, '%') 
        AND (
            (
                sav.attr_id = '手机' 
                AND sav.value_id = null
            ) 
            OR (
                sav.attr_id = null 
                AND sav.value_id = null
            ) 
        ) 
    ORDER BY
        s.id DESC LIMIT null,
        0,
        10;

这个sql语句完全错了,为什么?难道

            <if test="attrList != null and !attrList.isEmpty()">
                AND (
                (sav.attr_id = 11 AND sav.value_id = 32)
                OR
                (sav.attr_id = 12 AND sav.value_id = 33)
                )
            </if>

            <if test="attrList != null and !attrList.isEmpty()">
                AND (
                <foreach collection="attrList" item="pair" separator=" OR ">
                    (sav.attr_id = #{pair.key} AND sav.value_id = #{pair.value})
                </foreach>
                )
            </if>

不等价吗?还是attrList的格式需要更改?

想问下题主,这个attrList里面的对象类型是map吗?

控制台打印下实际的sql,应该很容易看出来是啥问题。
参考这个博客开启控制台sql

引用chatGPT作答,两个代码片段并不完全等价。在第一个代码片段中,SQL语句是硬编码的,检查特定的属性-值对,而在第二个代码片段中,属性-值对是通过foreach循环动态提供的。

根据你得到的第二个代码片段中空的“goodsList”响应,可能是“attrList”参数未正确传递到SQL语句。以下是几个可以检查的问题,以排除此问题:

1.确保在Java代码中正确定义了“attrList”参数,并将其传递给MyBatis mapper方法。
2.检查在传递给mapper方法时,“attrList”参数不为null或为空。
3.确保MyBatis mapper方法正确映射到包含foreach循环的SQL语句。
4.尝试打印MyBatis生成的SQL语句,以查看其是否基于“attrList”参数符合您的预期。
通过检查这些问题,您可能能够确定问题并解决第二个代码片段的问题。

以下答案由GPT-3.5大模型与博主波罗歌共同编写:
根据您提供的代码和打印的SQL语句,我认为出现错误的原因是attrList的格式问题。

在第一个SQL语句中,我们可以看到attrList是这样的:[{11=32}, {12=33}],可以看出是一个由Map组成的List。而在第二个SQL语句中,我们可以看到attrList被换成了占位符(?)的形式,也就是说,MyBatis会将它转换为一个含有占位符的字符串,然后再执行SQL语句。

因此,为了让第二个SQL语句能够正确执行,我们需要将attrList的格式修改为一个List,每个元素是一个Map,其中key表示attr_id,value表示value_id。修改后的attrList格式应该为:

[
    {"key": 11, "value": 32},
    {"key": 12, "value": 33}
]

然后在SQL语句中使用#{pair.key}#{pair.value}来获取数据即可,如下所示:

<if test="attrList != null and !attrList.isEmpty()">
    AND (
    <foreach collection="attrList" item="pair" separator=" OR ">
        (sav.attr_id = #{pair.key} AND sav.value_id = #{pair.value})
    </foreach>
    )
</if>

这样就能够正常执行SQL语句了。
如果我的回答解决了您的问题,请采纳!