使用JPA / EJB3批量插入
JPA / EJB3框架是否提供了批量插入操作的标准方法……? 我们使用hibernate作为持久性框架,所以我可以回退到Hibernate Session并使用组合session.save()/ session.flush()实现批量插入。 但是想知道EJB3是否支持这个……
JPA和Hibernate都没有为批量插入提供特殊支持,而使用JPA批量插入的习惯用法与Hibernate相同:
EntityManager em = ...; EntityTransaction tx = em.getTransaction(); tx.begin(); for ( int i=0; i<100000; i++ ) { Customer customer = new Customer(.....); em.persist(customer); if ( i % 20 == 0 ) { //20, same as the JDBC batch size //flush a batch of inserts and release memory: em.flush(); em.clear(); } } tx.commit(); session.close();
在这种情况下使用Hibernate的专有API并不能提供任何IMO优势。
参考
- JPA 1.0规范
- 第4.10节“批量更新和删除操作”
- Hibernate Core参考指南
- 第13章批处理
具体来说,对于hibernate, 核心手册的第13章解释了这些方法。
但是你说你想通过Hibernate获得EJB方法,所以实体管理器文档在这里也有一章。 我建议您同时阅读(核心和实体经理)。
在EJB中,它只是使用EJB-QL(有一些限制)。 如果你需要更多的灵活性,Hibernate提供了更多的机制。
使用中等记录编号,您可以使用以下方式:
em.getTransaction().begin(); for (int i = 1; i <= 100000; i++) { Point point = new Point(i, i); em.persist(point); if ((i % 10000) == 0) { em.flush(); em.clear(); } } em.getTransaction().commit();
但是对于大记录编号,您应该在多个事务中执行此任务:
em.getTransaction().begin(); for (int i = 1; i <= 1000000; i++) { Point point = new Point(i, i); em.persist(point); if ((i % 10000) == 0) { em.getTransaction().commit(); em.clear(); em.getTransaction().begin(); } } em.getTransaction().commit();
参考: JPA批量商店
是的,如果您希望拥有您定义的控件,则可以回滚到JPA实现。
JPA 1.0在EL-HQL上很丰富,但对Criteria API的支持很少,但这已在2.0中得到解决。
Session session = (Session) entityManager.getDelegate(); session.setFlushMode(FlushMode.MANUAL);
帕斯卡尔
在您的示例中插入100000条记录,它是在单个事务中完成的,因为commit()仅在结束时调用。它是否对数据库施加了很大的压力? 此外,如果有回滚,成本将太高..
以下方法会更好吗?
EntityManager em = ...; for ( int i=0; i<100000; i++ ) { if(!em.getTransaction().isActive()) { em.getTransaction().begin(); } Customer customer = new Customer(.....); em.persist(customer); if ((i+1) % 20 == 0 ) { //20, same as the JDBC batch size //flush and commit of inserts and release memory: em.getTransaction().commit(); em.clear(); } } session.close();