批量数据查询,会遇到“栈溢出”的问题,文章末尾我给出了解决方案。
在日常工作中,有时数据库表中某个字段以 "英文半角逗号拼接多个值" 存放在这个字段中,我们根据入参查找到对应的数据。在这里,使用 FIND_IN_SET() 函数即可解决问题。可以参考我之前的文章: Mysql中 find_in_set() 函数用法详解
如果是多个入参,可以使用 FIND_IN_ SET() 函数与 OR 关键字联用,来解决多个入参批量查询问题。如下面SQL、图一、图二所示。
本篇文章使用的数据库表、表数据,参见文章最后给出的 user2 表表结构、表数据。
SELECT
u.*
FROM `user2` u
WHERE
1 = 1
AND (
FIND_IN_SET('二狗', u.many_name)
OR FIND_IN_SET('大肚包', u.many_name)
OR FIND_IN_SET('李四', u.many_name)
)
;
图一
图二
在Java项目中,我们可以借助 Mybatis框架中的 <foreach> 标签来完成多参数批量查询问题。考虑到性能问题,根据《阿里巴巴Java编程规范》,入参的参数应该 小于等于 1000.
在下列XML类型的SQL中,我们主要关注 manyNameList 参数。使用 <foreach> 标签、OR 关键字作为分隔符,与 FIND_IN_SET() 函数联用,以此来实现批量查询。
<select id="listUser" resultType="com.moon.UserVO">
SELECT
u.id,
u.name,
u.age,
u.create_date,
u.many_name
FROM user2 u
<where>
1 = 1
<if test="paramDTO.id != null">
AND u.id = #{paramDTO.id, jdbcType=BIGINT}
</if>
<if test="paramDTO.userId != null">
AND u.id = #{paramDTO.userId, jdbcType=BIGINT}
<if test="paramDTO.name != null and paramDTO.name != ''">
AND u.name = #{paramDTO.name,jdbcType=VARCHAR}
</if>
<if test="paramDTO.nameLike != null and paramDTO.nameLike != ''">
AND u.name LIKE CONCAT('%', #{paramDTO.nameLike, jdbcType=VARCHAR}, '%')
</if>
<if test="paramDTO.nameList != null and paramDTO.nameList.size() != 0">
AND u.name IN
<foreach collection="paramDTO.nameList" item="item" separator="," index="index" open="(" close=")">
#{item}
</foreach>
</if>
<if test="paramDTO.manyNameList != null and paramDTO.manyNameList.size() != 0">
AND
<foreach collection="paramDTO.manyNameList" item="item" separator="OR" index="index" open="(" close=")">
FIND_IN_SET(#{item}, u.many_name)
</foreach>
</if>
ORDER BY u.id DESC
</where>
</select>
user2表的表结构、表数据
CREATE TABLE user2 (
id bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'ID, 主键.',
name varchar(100) DEFAULT NULL COMMENT '姓名',
age int(3) DEFAULT NULL COMMENT '年龄',
create_date datetime DEFAULT NULL COMMENT '创建时间',
many_name varchar(200) DEFAULT NULL COMMENT '多个姓名',
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COMMENT='用户表2';
INSERT INTO user2(id, name, age, create_date, many_name) VALUES (1, '张三', 20, '2020-04-02 09:54:23', '李桃,二狗,王大锤');
INSERT INTO user2(id, name, age, create_date, many_name) VALUES (2, '张三', 20, '2020-01-05 11:20:00', '张三丰,宋曼玉');
INSERT INTO user2(id, name, age, create_date, many_name) VALUES (4, '李四', 25, '2019-10-22 16:27:03', '李四,袁冲,李雪玲');
INSERT INTO user2(id, name, age, create_date, many_name) VALUES (5, '刘涛', 22, '2020-04-06 08:07:30', '二狗,章子怡');
INSERT INTO user2(id, name, age, create_date, many_name) VALUES (6, '张曼玉', 18, '2020-04-09 17:21:45', '李二狗,王小二,李四');
INSERT INTO user2(id, name, age, create_date, many_name) VALUES (7, '周润发', 30, '2022-06-21 10:25:42', '步惊云,神风腿,排云掌');
INSERT INTO user2(id, name, age, create_date, many_name) VALUES (8, '刘德华', 32, '2022-06-24 10:02:16', '二道杠,夜猫子,撸串');
批量数据查询“栈溢出”的问题解决方案参考下文。
Mybatis批量查询,报错:Handler dispatch failed; nested exception is java.lang.StackOverflowError