SpringBoot+MyBatis进行XML中循环处理List参数的终极指南

 更新时间:2025年07月06日 09:56:29   作者:一勺菠萝丶  
这篇文章主要为大家详细介绍了SpringBoot整合MyBatis进行XML中循环处理List参数的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下

重要提醒:使用@Param注解时,务必导入正确的包!

import org.apache.ibatis.annotations.Param;

很多开发者容易错误导入Spring的@Param,导致参数绑定失败!

一、为什么需要传递List参数?

最常见的场景是动态构建IN查询

SELECT * FROM users WHERE id IN (1, 2, 3, 4)

当我们需要根据前端传入的多个值查询时,就需要将List集合作为参数传递给Mapper。

二、基础版:MyBatis原生List传参

1. Mapper接口定义(注意@Param导入)

// !!!必须导入MyBatis的@Param包!!!
import org.apache.ibatis.annotations.Param;

public interface UserMapper {
    // 使用@Param注解指定参数名
    List<User> selectByIds(@Param("idList") List<Long> idList);
}

2. XML映射文件实现

<select id="selectByIds" resultType="User">
    SELECT * FROM users
    WHERE id IN
    <foreach collection="idList" item="id" 
             open="(" separator="," close=")">
        #{id}
    </foreach>
</select>

核心标签解析:

属性说明示例值
collection传入的集合参数名idList
item循环中当前元素的别名id
open循环开始前的字符串(
separator元素间的分隔符,
close循环结束后的字符串)

3. 实际生成的SQL

当传入List<Long> ids = Arrays.asList(1L, 2L, 3L)时:

SELECT * FROM users WHERE id IN (1, 2, 3)

三、避坑重点:@Param的正确使用

常见错误1:导入错误包

// ❌ 错误:导入了Spring的Param包
import org.springframework.data.repository.query.Param;

// ✅ 正确:必须使用MyBatis的Param包
import org.apache.ibatis.annotations.Param;

常见错误2:忘记添加@Param注解

// ❌ 错误:缺少@Param注解会导致XML中无法识别参数
List<User> selectByIds(List<Long> idList);

// ✅ 正确:必须添加@Param注解
List<User> selectByIds(@Param("idList") List<Long> idList);

四、MyBatis Plus的优雅实现

1. 使用QueryWrapper(无需XML)

public List<User> getUsersByIds(List<Long> ids) {
    return userMapper.selectList(
        new QueryWrapper<User>().in("id", ids)
    );
}

2. Lambda表达式写法(推荐)

public List<User> getUsersByIds(List<Long> ids) {
    return userMapper.selectList(
        Wrappers.<User>lambdaQuery()
            .in(User::getId, ids)
    );
}

注意:MyBatis Plus的Wrapper方式不需要@Param注解

五、扩展应用场景

场景1:List处理

// Mapper
List<User> selectByNames(@Param("nameList") List<String> nameList);

// XML
<foreach collection="nameList" item="name" open="(" separator="," close=")">
    #{name}
</foreach>

场景2:List<实体对象>

// Mapper
List<User> selectByConditions(@Param("userList") List<User> userList);

// XML
<foreach collection="userList" item="user" separator=" OR ">
    (name = #{user.name} AND age > #{user.age})
</foreach>

场景3:多List参数

// Mapper
List<User> searchUsers(@Param("ids") List<Long> ids, 
                      @Param("names") List<String> names);

// XML
<where>
    <if test="ids != null and !ids.isEmpty()">
        id IN
        <foreach collection="ids" item="id" open="(" separator="," close=")">
            #{id}
        </foreach>
    </if>
    <if test="names != null and !names.isEmpty()">
        AND name IN
        <foreach collection="names" item="name" open="(" separator="," close=")">
            #{name}
        </foreach>
    </if>
</where>

六、特殊类型处理技巧

1. 枚举类型处理

// Mapper
List<User> selectByStatus(@Param("statusList") List<UserStatus> statusList);

// XML
<foreach collection="statusList" item="status" open="(" separator="," close=")">
    #{status, typeHandler=org.apache.ibatis.type.EnumTypeHandler}
</foreach>

2. 日期范围查询

// Mapper
List<User> selectByDates(@Param("dateList") List<Date> dates);

// XML
<foreach collection="dateList" item="date" separator=" OR ">
    create_time BETWEEN #{date} AND DATE_ADD(#{date}, INTERVAL 1 DAY)
</foreach>

七、性能优化与避坑指南

1. 空集合安全处理

<select id="safeSelect">
    SELECT * FROM users
    <where>
        <if test="idList != null and !idList.isEmpty()">
            id IN
            <foreach collection="idList" ... />
        </if>
    </where>
</select>

2. 大数据量分批查询

// 每500条执行一次查询
public List<User> batchSelect(List<Long> allIds) {
    List<User> result = new ArrayList<>();
    int batchSize = 500;
    
    for (int i = 0; i < allIds.size(); i += batchSize) {
        List<Long> batchIds = allIds.subList(i, Math.min(i + batchSize, allIds.size()));
        result.addAll(userMapper.selectByIds(batchIds));
    }
    return result;
}

3. SQL注入防护

<!-- 安全写法:使用#{}预编译 -->
<foreach collection="names" item="name">
    #{name}  <!-- 安全 -->
</foreach>

<!-- 危险写法:${}直接拼接 -->
<foreach collection="names" item="name">
    '${name}' <!-- 存在SQL注入风险! -->
</foreach>

八、完整可运行示例

Controller

@RestController
@RequestMapping("/users")
public class UserController {
    
    @PostMapping("/by-ids")
    public List<User> getUsersByIds(@RequestBody List<Long> ids) {
        return userService.getUsersByIds(ids);
    }
}

Service

@Service
@RequiredArgsConstructor
public class UserService {
    private final UserMapper userMapper;

    public List<User> getUsersByIds(List<Long> ids) {
        if (ids == null || ids.isEmpty()) {
            return Collections.emptyList();
        }
        // 超过1000条自动分批
        return ids.size() > 1000 ? batchSelect(ids) : userMapper.selectByIds(ids);
    }
}

Mapper XML

<mapper namespace="com.example.mapper.UserMapper">
    
    <select id="selectByIds" resultType="User">
        SELECT id, name, email 
        FROM users
        <where>
            <if test="idList != null and !idList.isEmpty()">
                id IN
                <foreach collection="idList" item="id" 
                         open="(" separator="," close=")">
                    #{id}
                </foreach>
            </if>
        </where>
    </select>
</mapper>

总结:核心要点回顾

1.必须使用正确的@Param包 import org.apache.ibatis.annotations.Param;

2.XML循环核心语法

<foreach collection="参数名" item="元素名" 
         open="开始符" separator="分隔符" close="结束符">
     #{元素名}
</foreach>

3.最佳实践选择

  • 简单查询:MyBatis Plus Wrapper
  • 复杂SQL:MyBatis XML + foreach
  • 超大数据:分批查询

4.安全防护

  • 始终使用#{}防止SQL注入
  • 空集合检查避免全表扫描

5.特殊类型处理

  • 枚举:添加typeHandler
  • 日期:指定jdbcType=TIMESTAMP

最后提醒: 当遇到参数绑定问题时,首先检查@Param导入的包是否正确,这是最常见的错误根源!

到此这篇关于SpringBoot+MyBatis进行XML中循环处理List参数的终极指南的文章就介绍到这了,更多相关SpringBoot处理List参数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 深入剖析Java编程中的序列化

    深入剖析Java编程中的序列化

    这篇文章主要介绍了深入剖析Java编程中的序列化,文中谈到了序列化时对象的继承等各种问题,案例详尽,强烈推荐!需要的朋友可以参考下
    2015-07-07
  • Java中实现日期时间字符串转换为Date对象的方法

    Java中实现日期时间字符串转换为Date对象的方法

    在 Java 编程中,日期时间的处理是一项常见且重要的任务,无论是数据存储、日志记录还是业务逻辑处理,准确地表示和操作日期时间都是不可或缺的,本文给大家介绍了Java中实现日期时间字符串转换为Date对象的方法,需要的朋友可以参考下
    2025-01-01
  • Spring源码学习之动态代理实现流程

    Spring源码学习之动态代理实现流程

    这篇文章主要给大家介绍了关于Spring源码学习之动态代理实现流程的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-03-03
  • Java类加载器ClassLoader源码层面分析讲解

    Java类加载器ClassLoader源码层面分析讲解

    ClassLoader翻译过来就是类加载器,普通的java开发者其实用到的不多,但对于某些框架开发者来说却非常常见。理解ClassLoader的加载机制,也有利于我们编写出更高效的代码。ClassLoader的具体作用就是将class文件加载到jvm虚拟机中去,程序就可以正确运行了
    2022-09-09
  • Java 实战项目锤炼之小区物业管理系统的实现流程

    Java 实战项目锤炼之小区物业管理系统的实现流程

    读万卷书不如行万里路,只学书上的理论是远远不够的,只有在实战中才能获得能力的提升,本篇文章手把手带你用java+SSM+jsp+mysql+maven实现一个小区物业管理系统,大家可以在过程中查缺补漏,提升水平
    2021-11-11
  • Java程序去调用并执行shell脚本及问题总结(推荐)

    Java程序去调用并执行shell脚本及问题总结(推荐)

    这篇文章主要介绍了Java程序去调用并执行shell脚本及问题总结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-06-06
  • IDEA启动tomcat状态404的解决

    IDEA启动tomcat状态404的解决

    在使用Idea进行Java Web开发过程中,经常会遇到Tomcat出现404错误的问题,本文就来介绍了IDEA启动tomcat状态404的解决,具有一定的参考价值,感兴趣的可以了解一下
    2023-10-10
  • Java8 HashMap的实现原理分析

    Java8 HashMap的实现原理分析

    Java8之后新增挺多新东西,接下来通过本文给大家介绍Java8 HashMap的实现原理分析,对java8 hashmap实现原理相关知识感兴趣的朋友一起学习吧
    2016-03-03
  • Java受检异常的一些思考

    Java受检异常的一些思考

    受检异常是否真的有必要?这是一个争论了很久的问题,至今仍然没有一个确定的答案。Java的受检异常,被很多人吐槽,也被很多人喜爱,当然他们都可以拿出很多的理由来证明自己的观点。
    2020-12-12
  • 详解Spring中的@PropertySource注解使用

    详解Spring中的@PropertySource注解使用

    这篇文章主要介绍了Spring的@PropertySource注解使用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-08-08

最新评论