繁体   English   中英

带有共享实体管理器的Java批量插入

[英]Java Bulk Insert with Shared Entity Manager

我正在尝试编写一种将实体批量添加到数据库的方法。 这是我的方法:

@Transactional
protected void bulkInsert(List<?> entities) {
    int batchSize = 25;
    AtomicInteger i = new AtomicInteger(0);
    try {
        em.getTransaction().begin();
        entities.parallelStream().forEach(e -> {
            em.persist(e);
            if ( i.get() > 0 && i.get() % batchSize == 0 ) {
                em.flush();
                em.clear();
            }
            i.incrementAndGet();
        });
        em.getTransaction().commit();
    } catch (RuntimeException e) {
        LOG.error("Error", e);
    } finally {
        if (em != null) {
            em.close();
        }
    }
}

但是当我运行它时,出现以下错误:

java.lang.IllegalStateException: Not allowed to create transaction on shared EntityManager - use Spring transactions or EJB CMT instead
    at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:248) ~[spring-orm-4.3.5.RELEASE.jar:4.3.5.RELEASE]
    at com.sun.proxy.$Proxy145.getTransaction(Unknown Source) ~[na:na]

我尝试删除@Transactional批注,但仍然是相同的错误。 我尝试通过执行Session session = em.unwrap(Session.class);使用Session Session session = em.unwrap(Session.class); 但这仍然导致错误(尽管有不同的错误)

如何批量插入对象?

在纯休眠状态下,存在托管和非托管环境

非托管环境

如果JPA持久层在非托管环境中运行,则数据库>连接通常由>场景后面的Hibernate的池化机制处理。 通用实体管理器和事务处理习惯用法如下所示:

//非托管环境习语

EntityManager em = emf.createEntityManager(); EntityTransaction tx = null; 尝试{tx = em.getTransaction(); tx.begin();

  // do some work ... tx.commit(); } catch (RuntimeException e) { if ( tx != null && tx.isActive() ) tx.rollback(); throw e; // or display error message } finally { em.close(); } 

使用JTA如果使用bean管理的事务(BMT),代码将如下所示:

// BMT成语@Resource public UserTransaction utx; @Resource公共EntityManagerFactory工厂;

公共无效doBusiness(){EntityManager em = factory.createEntityManager(); 尝试{

 // do some work ... utx.commit(); } catch (RuntimeException e) { if (utx != null) utx.rollback(); throw e; // or display error message } finally { em.close(); 

}

使用EJB3容器中的容器管理的事务(CMT),事务>分界是在会话bean注释或部署描述符中完成的,而不是通过编程实现的。 事务完成时,将自动刷新EntityManager(如果您已注入或查找EntityManager,它也将自动关闭)。 如果在使用EntityManager的过程中发生异常,那么如果您没有捕获到异常,则事务回滚会自动发生。 由于EntityManager异常是RuntimeException,因此它们将根据EJB规范回滚事务(系统异常与应用程序异常)。

您应该跟随两个王子。

注解@Transactional是春天的annotaniot不休眠。 如果您没有配置它(或您已经配置了spring),则无法使用。

个人电脑

EntityManager是廉价的,非线程安全的对象,对于单个业务流程应使用一次

调用em.flush(),em.clear()可能很危险。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM