spring-data-jpa-2.3.9 版本 <S extends T> List<S> saveAll(Iterable<S> var1);
saveAll是JpaRepository提供的一个用于批量保存实体的方法其核心功能是遍历迭代器中的每个实体根据其 ID 状态决定执行persist新增还是merge更新最终返回所有已保存的实体列表。下面我们来深入拆解它的行为。1. 方法定义javaS extends T ListS saveAll(IterableS var1);功能批量保存给定的实体集合。返回所有已保存的实体顺序与传入的Iterable顺序一致。2. 源码实现在SimpleJpaRepository中saveAll的实现是一个循环调用savejava// SimpleJpaRepository.java (Spring Data JPA 2.3.9) Transactional public S extends T ListS saveAll(IterableS entities) { Assert.notNull(entities, Entities must not be null!); ListS result new ArrayList(); for (S entity : entities) { result.add(save(entity)); } return result; }关键点它是一个逐条循环保存的操作并不是真正的“批量插入 SQL”性能可能不如预期。3.saveAll的判定逻辑对于每一个实体save()会走以下逻辑检查实体是否为新实体isNew()是执行EntityManager.persist()触发INSERT。否执行EntityManager.merge()触发UPDATE。isNew()的判定逻辑若Id字段是null或基础类型long/int的默认值0通常判断为新实体。若使用了GeneratedValueID 一旦被赋值非null/ 非0就视为已存在实体走UPDATE。4. 示例代码javaService public class UserService { Autowired private UserRepository userRepository; Transactional public ListUser batchSave() { // 1. 新增两个用户ID 为 null走 INSERT User user1 new User(); user1.setName(张三); User user2 new User(); user2.setName(李四); ListUser saved userRepository.saveAll(Arrays.asList(user1, user2)); // saved 中的用户会被自动赋上生成的 ID // 2. 更新两个用户ID 有值走 UPDATE User user3 new User(); user3.setId(1L); user3.setName(张三-更新); User user4 new User(); user4.setId(2L); user4.setName(李四-更新); return userRepository.saveAll(Arrays.asList(user3, user4)); } }5. 性能注意事项saveAll在 2.3.9 版本中不是真正的批量插入它每一条数据都会单独发送 SQL并且每条数据都会触发一次EntityManager的生命周期操作。性能问题数据量实际执行方式性能10 条10 条单独 INSERT✅ 影响不大100 条100 条单独 INSERT⚠️ 一般1000 条1000 条单独 INSERT❌ 极慢可能超时优化建议如果数据量较大100条建议使用原生 SQL 的批量插入javaModifying Query(value INSERT INTO user (name) VALUES (?1), (?2), (?3), nativeQuery true) void batchInsert(ListString names);开启 Hibernate 批量插入配置yamlspring: jpa: properties: hibernate: jdbc: batch_size: 50 order_inserts: true6. 关键注意事项关注点说明返回顺序返回的List顺序与传入的Iterable顺序一致事务saveAll默认在Transactional下执行Repository 层有事务注解ID 生成如果 ID 使用GeneratedValue返回的实体会包含生成的 ID部分失败如果某个实体保存失败会导致整个事务回滚同一个事务中7.saveAll的常见陷阱java// ❌ 陷阱用一个已存在的实体对象去新增 User existingUser userRepository.findById(1L).orElse(null); existingUser.setId(null); // 试图强行重置 ID userRepository.saveAll(Arrays.asList(existingUser)); // 可能仍然走 UPDATE在saveAll循环调用save时即使你setId(null)Hibernate 可能会因为该对象来自同一个 Session 上下文而认为它是持久态执行merge而不是persist。最佳做法用new创建新对象而不是复用查询出的对象。8. 总结维度说明功能批量保存自动判断新增INSERT或更新UPDATE判断依据基于isNew()通常是 ID 是否为null/0性能2.3.9 版本逐条循环数据量大时性能差返回保存后的实体列表顺序与输入一致推荐用法小批量数据100条可用大批量建议用原生 SQL 或EntityManager手动批量操作如果你有批量插入 1000 条以上数据的需求我可以给你写一个基于 Hibernate 批量插入的优化方案。

相关新闻

spring-data-jpa-2.3.9 版本中,JpaRepository 的 findAllById(Iterable<ID> var1)

spring-data-jpa-2.3.9 版本中,JpaRepository 的 findAllById(Iterable<ID> var1)

spring-data-jpa-2.3.9 版本中&#xff0c;JpaRepository 的 findAllById(Iterable<ID> var1) 方法会根据传入的 ID 集合&#xff0c;查询出所有匹配的实体&#xff0c;并以 List<T> 的形式返回。这个方法的行为很直接&#xff1a;它等价于执行一个 IN 查询&#x…

2026/10/25 13:10:19 阅读更多 →
云苍穹RK3576开发资料大全:嵌入式物联网开发实战指南

云苍穹RK3576开发资料大全:嵌入式物联网开发实战指南

1. 项目概述&#xff1a;为什么你需要一份“云苍穹”开发资料大全&#xff1f; 如果你是一名嵌入式或物联网方向的开发者&#xff0c;最近在项目选型时&#xff0c;肯定对“云苍穹”这个名字不陌生。它不是一个具体的芯片型号&#xff0c;而更像是一个围绕特定核心平台&#xf…

2026/10/25 18:16:29 阅读更多 →
电容器ESR参数详解:从原理到选型,解决电源纹波与高频去耦难题

电容器ESR参数详解:从原理到选型,解决电源纹波与高频去耦难题

1. 电容器ESR参数&#xff1a;一个被忽视的“隐形杀手” 在电路设计&#xff0c;尤其是电源和信号处理领域&#xff0c;我们常常把注意力集中在电容的容值、耐压和封装上。选型时&#xff0c;一个100μF/25V的电解电容&#xff0c;似乎只要容值和电压对得上&#xff0c;从不同供…

2026/10/28 6:58:21 阅读更多 →

最新新闻

Electron桌面应用开发实战:从环境搭建到打包发布全流程

Electron桌面应用开发实战:从环境搭建到打包发布全流程

做前端这些年&#xff0c;我大部分时间都在跟浏览器标签页打交道&#xff0c;直到第一次把桌面应用跑起来&#xff0c;才发现原来自己一直被限制在地址栏和刷新按钮围起来的框框里。Electron这个词&#xff0c;最开始是在某段时间频繁出现在同事的讨论里&#xff0c;一个用HTML…

2026/10/27 17:33:32 阅读更多 →
滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

滑盖智能锁T109深度解析:结构原理、安装调试与故障排查

简介&#xff1a;亚太天能T109滑盖智能锁产品说明书是一份PDF格式的官方技术文档&#xff0c;主要面向智能锁安装人员、终端用户及售后维护者&#xff0c;帮助快速掌握产品安装、配置与常见故障处理。全包仅1个PDF文件&#xff0c;大小4.37MB&#xff0c;内容结构清晰&#xff…

2026/10/28 7:28:00 阅读更多 →
PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

PMSM弱磁控制原理与Simulink建模:高速AGV驱动系统设计指南

上个月我在调试一台高速AGV的驱动系统&#xff0c;整车要求空载跑到8m/s&#xff0c;电机转速已经拉到额定点&#xff0c;驱动器的输出电压也顶到了母线电压极限附近。再往上踩速度指令&#xff0c;转速纹丝不动&#xff0c;三相电流反而开始震荡。那会儿我的第一反应就是&…

2026/10/27 7:21:53 阅读更多 →
C++核心知识点:从内存管理到STL的实战指南

C++核心知识点:从内存管理到STL的实战指南

C 这门语言我前前后后折腾了十几年&#xff0c;用它写过嵌入式驱动、做过游戏服务端&#xff0c;也搭过基础组件库。每次看到新人一头扎进"C 核心知识点"这个搜索词&#xff0c;我其实挺感慨的——这门语言的难点从来不是语法多&#xff0c;而是知识点之间的耦合太深…

2026/10/27 18:20:50 阅读更多 →
T109滑盖智能锁怎么装?安装调试与故障排查全攻略

T109滑盖智能锁怎么装?安装调试与故障排查全攻略

简介&#xff1a;亚太天能T109滑盖智能锁产品说明书以PDF格式发布&#xff0c;适合智能锁用户、安装人员与售后维修人员阅读。内容围绕T109系列指纹密码刷卡锁展开&#xff0c;先介绍前面板、后面板、锁体、机械钥匙、电池盒盖等部件名称与功能&#xff0c;再给出完整安装步骤&…

2026/10/27 6:20:47 阅读更多 →
LLM知识降熵:从信息垄断到理解权下放

LLM知识降熵:从信息垄断到理解权下放

你有没有过这种经历&#xff1a;翻开源码注释、论文摘要或者一份专业报告&#xff0c;每个字都认识&#xff0c;连在一起却像天书。想找人聊聊&#xff0c;身边要么没人懂&#xff0c;要么懂的懒得跟你解释。后来我试着把同一段内容丢给一个大语言模型&#xff0c;几秒钟之后&a…

2026/10/28 7:29:02 阅读更多 →

日新闻

周新闻

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 13:55:19 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 7:21:50 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/27 19:19:37 阅读更多 →