简介:本文详细解析MyBatis框架中模糊查询与IN条件查询的实现方法,结合XML映射文件与注解开发两种方式,提供完整代码示例与性能优化建议。
MyBatis的模糊查询主要通过SQL语句中的LIKE
关键字实现,结合动态SQL功能可构建灵活的查询条件。在MyBatis中实现模糊查询有两种典型方式:
<!-- UserMapper.xml -->
<select id="selectByNameLike" resultType="User">
SELECT * FROM user
WHERE name LIKE CONCAT('%', #{keyword}, '%')
</select>
这种方式通过MySQL的CONCAT
函数直接拼接通配符,适用于简单场景。但存在SQL注入风险,需确保参数经过严格校验。
<select id="selectByDynamicPattern" resultType="User">
SELECT * FROM user
WHERE name LIKE
<bind name="pattern" value="'%' + keyword + '%'" />
#{pattern}
</select>
或使用<if>
标签构建更复杂的条件:
<select id="searchUsers" resultType="User">
SELECT * FROM user
WHERE 1=1
<if test="name != null">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="email != null">
AND email LIKE '%' || #{email} || '%'
</if>
</select>
关键点:
CONCAT
,Oracle用||
)<bind>
标签预处理参数,提升可读性<where>
标签自动处理AND/OR前缀IN查询用于匹配多个离散值,在MyBatis中有三种实现方式:
<select id="selectByIds" resultType="User">
SELECT * FROM user
WHERE id IN (1, 2, 3, 5, 8)
</select>
适用于固定值列表的场景,但实际开发中极少使用。
// Mapper接口
List<User> selectByIdList(@Param("ids") List<Long> ids);
<select id="selectByIdList" resultType="User">
SELECT * FROM user
WHERE id IN
<foreach item="id" collection="ids" open="(" separator="," close=")">
#{id}
</foreach>
</select>
实现细节:
collection
属性对应方法参数名,若使用@Param
注解则写注解值item
定义循环变量名,open/close
定义括号,separator
定义分隔符WHERE id IN ()
导致语法错误,需配合<if>
处理:
<select id="safeSelectByIdList" resultType="User">
SELECT * FROM user
WHERE
<if test="ids != null and ids.size() > 0">
id IN
<foreach item="id" collection="ids" open="(" separator="," close=")">
#{id}
</foreach>
</if>
<if test="ids == null or ids.size() == 0">
1=0 <!-- 返回空结果集 -->
</if>
</select>
@Select({
"<script>",
"SELECT * FROM user",
"WHERE id IN",
"<foreach item='id' collection='ids' open='(' separator=',' close=')'>",
"#{id}",
"</foreach>",
"</script>"
})
List<User> selectByIdListAnnotated(@Param("ids") List<Long> ids);
注意事项:
<script>
标签包裹动态SQLLIKE '%keyword'
无法使用索引,应设计为LIKE 'keyword%'
或全字段匹配CREATE INDEX idx_name_fuzzy ON user((name))
-- 创建临时表
CREATE TEMPORARY TABLE temp_ids (id BIGINT);
-- 批量插入
INSERT INTO temp_ids VALUES (1),(2),(3);
-- 关联查询
SELECT u.* FROM user u JOIN temp_ids t ON u.id = t.id;
ROW_NUMBER()
或LIMIT
分批处理#{}
而非${}
处理参数
# application.properties
logging.level.org.mybatis=DEBUG
<select id="complexSearch" resultType="User">
SELECT * FROM user
<where>
<if test="name != null">
AND name LIKE CONCAT('%', #{name}, '%')
</if>
<if test="statusList != null and statusList.size() > 0">
AND status IN
<foreach item="status" collection="statusList" open="(" separator="," close=")">
#{status}
</foreach>
</if>
<if test="minAge != null">
AND age >= #{minAge}
</if>
</where>
ORDER BY create_time DESC
</select>
@Transactional
public void batchUpdateStatus(List<Long> ids, Integer newStatus) {
// 先查询存在性(可选)
List<User> users = userMapper.selectByIdList(ids);
if(users.size() != ids.size()) {
throw new RuntimeException("部分ID不存在");
}
// 批量更新
userMapper.batchUpdateStatus(
ids,
newStatus,
new Date() // 更新时间
);
}
<update id="batchUpdateStatus">
UPDATE user
SET status = #{newStatus},
update_time = #{updateTime}
WHERE id IN
<foreach item="id" collection="ids" open="(" separator="," close=")">
#{id}
</foreach>
</update>
原因分析:
解决方案:
<!-- 强制转换为小写比较 -->
<select id="caseInsensitiveSearch" resultType="User">
SELECT * FROM user
WHERE LOWER(name) LIKE CONCAT('%', LOWER(#{keyword}), '%')
</select>
错误表现:
ORA-01795: maximum number of expressions in a list is 1000
解决方案:
public List<User> selectInBatches(List<Long> allIds, int batchSize) {
List<User> result = new ArrayList<>();
for(int i=0; i<allIds.size(); i+=batchSize) {
List<Long> batch = allIds.subList(i, Math.min(i+batchSize, allIds.size()));
result.addAll(userMapper.selectByIdList(batch));
}
return result;
}
对于使用MyBatis-Plus的项目,可简化操作:
// 模糊查询
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
wrapper.like(User::getName, "张")
.in(User::getStatus, Arrays.asList(1, 2, 3));
List<User> users = userMapper.selectList(wrapper);
// 批量操作
userMapper.update(
null,
new LambdaUpdateWrapper<User>()
.set(User::getStatus, 2)
.in(User::getId, Arrays.asList(1L, 2L, 3L))
);
总结:本文系统阐述了MyBatis中模糊查询与IN条件查询的实现方法,从基础语法到性能优化提供了完整解决方案。实际开发中,应结合业务场景选择合适方案,特别注意SQL注入防护和大数据量处理。通过合理使用动态SQL和数据库特性,可显著提升查询效率与系统稳定性。