想立即将数据保存到数据库中的 table
Want to save data into table in database immediately
我在使用 Spring Data JPA 存储库将数据保存到数据库时遇到问题。
我的场景:我正在使用一个循环来一个接一个地收集和保存数据。收集所有数据需要花费大量时间。因此我想立即将每条记录的数据保存到 table 到数据库中。我正在使用 saveAndFlush
方法,但数据没有立即保存到 table 中。
我等不及收集完所有数据,因为收集所有数据可能需要一整天。
您的方法可能有一个@Transactional 注释,并且它可能会等待所有实体准备就绪,以便在一个事务中一次性保存所有实体。
JPA 有一个 'saveAll' 方法,您可以在其中一次保存整个集合,我建议您使用这个方法,这样您就不必为每个实体发送单独的请求并增加数据库工作负载和网络带宽。
我不是 100% 确定你是如何测试数据没有立即写入数据库的,但我猜你正在检查一个单独的数据库连接。
这可能意味着您的数据实际上已写入数据库,但未提交,因此对其他会话不可见。
确保事务范围仅在内部您用于写入的循环中。
为此,包含 for 循环的方法不应具有 @Transactional
注释或以任何其他方式包含在事务中,而对 save
的调用是在事务中。 saveAndFlush
不是必需的,因为事务已提交并且无论如何都会触发刷新。
如果调用 save
与数据库的唯一交互 Spring 实际上会自动将其包装在一个事务中,因为存储库用开箱即用的 @Transactional
注释。否则,您将需要使用 the transaction support of Spring 来实现此目的。
我不认为一次保存每条记录是个好主意,尽管这是可能的。
Flushing是将持久化上下文的状态与底层数据库同步的过程。如果发生预期的事情,事务将回滚,不保留任何数据。
针对您的情况,天真的解决方案是使用单独的事务 (Propagation.REQUIRES_NEW)。请注意,这会造成巨大的性能消耗。因此,我个人建议在单个事务(批处理)中保存多条记录。 https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#batch
因此,无论在何处使用循环,都要确保它在与前一个单独的事务中运行。
或
如果您使用的是spring-data-jpa,还有更简单的方法来批量处理实体。你只需要完成两件事:
- 在您的 属性 文件中,设置选项
spring.jpa.properties.hibernate.jdbc.batch_size=any_size
- 将您的存储库的
saveAll()
方法与准备插入的实体列表一起使用。
在这里查看更多 https://dzone.com/articles/50-best-performance-practices-for-hibernate-5-amp
查看以下图片,了解 REQUIRES_NEW 和 REQUIRED 如何完成工作:
AND REQUIRES_NEW
我在使用 Spring Data JPA 存储库将数据保存到数据库时遇到问题。
我的场景:我正在使用一个循环来一个接一个地收集和保存数据。收集所有数据需要花费大量时间。因此我想立即将每条记录的数据保存到 table 到数据库中。我正在使用 saveAndFlush
方法,但数据没有立即保存到 table 中。
我等不及收集完所有数据,因为收集所有数据可能需要一整天。
您的方法可能有一个@Transactional 注释,并且它可能会等待所有实体准备就绪,以便在一个事务中一次性保存所有实体。
JPA 有一个 'saveAll' 方法,您可以在其中一次保存整个集合,我建议您使用这个方法,这样您就不必为每个实体发送单独的请求并增加数据库工作负载和网络带宽。
我不是 100% 确定你是如何测试数据没有立即写入数据库的,但我猜你正在检查一个单独的数据库连接。
这可能意味着您的数据实际上已写入数据库,但未提交,因此对其他会话不可见。
确保事务范围仅在内部您用于写入的循环中。
为此,包含 for 循环的方法不应具有 @Transactional
注释或以任何其他方式包含在事务中,而对 save
的调用是在事务中。 saveAndFlush
不是必需的,因为事务已提交并且无论如何都会触发刷新。
如果调用 save
与数据库的唯一交互 Spring 实际上会自动将其包装在一个事务中,因为存储库用开箱即用的 @Transactional
注释。否则,您将需要使用 the transaction support of Spring 来实现此目的。
我不认为一次保存每条记录是个好主意,尽管这是可能的。
Flushing是将持久化上下文的状态与底层数据库同步的过程。如果发生预期的事情,事务将回滚,不保留任何数据。
针对您的情况,天真的解决方案是使用单独的事务 (Propagation.REQUIRES_NEW)。请注意,这会造成巨大的性能消耗。因此,我个人建议在单个事务(批处理)中保存多条记录。 https://docs.jboss.org/hibernate/orm/5.4/userguide/html_single/Hibernate_User_Guide.html#batch
因此,无论在何处使用循环,都要确保它在与前一个单独的事务中运行。
或
如果您使用的是spring-data-jpa,还有更简单的方法来批量处理实体。你只需要完成两件事:
- 在您的 属性 文件中,设置选项
spring.jpa.properties.hibernate.jdbc.batch_size=any_size
- 将您的存储库的
saveAll()
方法与准备插入的实体列表一起使用。 在这里查看更多 https://dzone.com/articles/50-best-performance-practices-for-hibernate-5-amp
查看以下图片,了解 REQUIRES_NEW 和 REQUIRED 如何完成工作:
AND REQUIRES_NEW