hibernate 批量保存数据

本文介绍在使用Hibernate进行大量数据保存时遇到的问题及解决方案。详细解释了一级缓存的工作原理及其可能导致的问题,并提供了一种通过定期flush和clear缓存来提高性能的方法。
部署运行你感兴趣的模型镜像

1.基本思想

基本的思想是保存对象是及时将hibernate的一级缓存同步到数据库中,并且清空一级缓存。(关于一级缓存和二级缓存的区别可以参照

一级缓存是Session级别的,也可以说是线程级别,一个线程对数据库进行的操作都放在一级缓存中。使用Hibernate的session.save保存对象时,该对象其实是保存在一级缓存中的,没有更新到数据库中,后面如果该线程继续对数据库进行操作时,会检查要操作的对象是否在这个一级缓存中,如果在,那么就不用去访问数据库了(加快了数据访问速度),如果不在一级缓存中,才去访问数据库。使用Hibernate大量保存数据时,一级缓存会越积越多,有两个风险:

  • 可能会导致Hibernate占用内存过多,造成OOM错误。
  • 由于后面的数据库操作时,每次都会检查这个一级缓存,一级缓存越大,检查的时间越长,所以导致“数据越存越慢”的情况,前1W条五分钟,后1W面可能就要10分钟了,时间都用来检查这个一级缓存去了。

2.解决办法

	session = HibernateUtil.getSession(); 
	session.beginTransaction(); 
	Object object = null; 
	for (int i = 0; i < list.size(); i++) {  
		object = list.get(i);
		session.save(object); 
		if (i % 10 == 0) {  
			session.flush();  
			session.clear();  
		}  
	}  
	session.getTransaction().commit(); 

就是每保存一定数量的对象后,将更改同步到数据库,并清除缓存。一个更加完整的例子可以 参照
有人说可以用batch_size来解决,但有的数据库(例如mysql)是不支持batchsize的

您可能感兴趣的与本文相关的镜像

Python3.10

Python3.10

Conda
Python

Python 是一种高级、解释型、通用的编程语言,以其简洁易读的语法而闻名,适用于广泛的应用,包括Web开发、数据分析、人工智能和自动化脚本

在使用 Hibernate 进行批量插入数据时,为了提升性能,需要避免 Hibernate 默认的逐条插入行为,转而采用更高效的批量处理机制。以下是一些最佳实践和示例代码。 ### 配置优化 首先,确保在 `hibernate.cfg.xml` 或 `persistence.xml` 中启用批量操作支持。可以配置以下参数: - `hibernate.jdbc.batch_size`:设置批量插入的大小。 - `hibernate.order_inserts` 和 `hibernate.order_updates`:启用批量插入和更新的排序,减少数据库的切换开销。 ```xml <property name="hibernate.jdbc.batch_size" value="50"/> <property name="hibernate.order_inserts" value="true"/> <property name="hibernate.order_updates" value="true"/> ``` ### 使用 Hibernate批量插入示例 在代码中,可以通过 `Session` 接口进行批量插入,并结合事务管理以确保数据一致性。以下是一个简单的批量插入示例: ```java Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); for (int i = 0; i < 1000; i++) { MyEntity entity = new MyEntity("value" + i); session.save(entity); // 每插入一定数量的数据后刷新一次 if (i % 50 == 0 && i != 0) { session.flush(); session.clear(); } } transaction.commit(); session.close(); ``` ### 使用原生 SQL 批量插入 如果需要更高的性能,可以直接使用 JDBC 的 `PreparedStatement` 来执行批量插入操作。这种方式绕过了 Hibernate 的对象状态管理,减少了内存消耗和性能开销。 ```java Session session = sessionFactory.openSession(); Connection connection = session.connection(); connection.setAutoCommit(false); String sql = "INSERT INTO my_table (column1) VALUES (?)"; try (PreparedStatement ps = connection.prepareStatement(sql)) { for (int i = 0; i < 1000; i++) { ps.setString(1, "value" + i); ps.addBatch(); if (i % 50 == 0) { ps.executeBatch(); } } ps.executeBatch(); // 提交剩余的数据 connection.commit(); } catch (SQLException e) { connection.rollback(); } ``` ### 使用多线程提升性能 对于非常大的数据集,可以考虑使用线程池来并行处理数据插入。以下是一个使用 `CompletableFuture` 和线程池的示例: ```java ExecutorService executor = Executors.newFixedThreadPool(4); List<CompletableFuture<Void>> futures = new ArrayList<>(); List<List<MyEntity>> batches = splitDataIntoBatches(allData, 1000); // 数据分片 for (List<MyEntity> batch : batches) { futures.add(CompletableFuture.runAsync(() -> { try (Session session = sessionFactory.openSession()) { Transaction tx = session.beginTransaction(); for (MyEntity entity : batch) { session.save(entity); } tx.commit(); } catch (Exception e) { // 异常处理 } }, executor)); } CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])).join(); executor.shutdown(); ``` ### 相关问题 1. Hibernate 中如何配置批量更新的最佳实践? 2. 如何在 Hibernate 中使用缓存机制提升性能? 3. 如何通过 Hibernate 进行高效的批量删除操作? 4. 在 Hibernate 中,如何结合事务管理进行批量操作? 5. 如何使用 Hibernate 的原生 SQL 查询来优化批量操作?
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值