使用共享实体管理器的Java批量插入

使用共享实体管理器的Java批量插入,java,database,hibernate,session,bulkinsert,Java,Database,Hibernate,Session,Bulkinsert,我正在尝试编写一个方法,将实体批量添加到数据库中。以下是我的方法: @Transactional protected void bulkInsert(List<?> entities) { int batchSize = 25; AtomicInteger i = new AtomicInteger(0); try { em.getTransaction().begin(); entities.parallelStream().

我正在尝试编写一个方法,将实体批量添加到数据库中。以下是我的方法:

@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();
        }
    }
}
我尝试删除@Transactional注释,但仍然出现相同的错误。我尝试通过执行Session Session=em.unwrapSession.class来使用Session;但这仍然导致了一个错误,尽管错误不同


如何批量插入对象?

在纯hibernate环境中,存在托管和非托管环境

非托管环境

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

//非托管环境习惯用法

EntityManager em=emf.createEntityManager;实体事务tx= 无效的试一试{ 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习语 @资源公共用户事务utx; @公共资源 实体管理工厂

公共事业{ 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异常是运行时异常,因此 将根据EJB规范系统回滚事务 异常与应用程序异常

你应该遵循两个原则

annotation@Transactional它是spring Annotanion而不是hibernate。如果您没有配置它,或者您确实配置了spring,那么它将无法工作

个人电脑

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


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

您是否尝试删除em.getTransaction.begin;/em.getTransaction.commit;并离开@Transactional?@RomanPuchkovskiy?好的,我尝试了,但它给了我一个错误:org.springframework.transaction.TransactionSystemException:无法提交JPA事务;嵌套异常是javax.persistence.RollbackException:org.springframework.orm.jpa.JpaTransactionManager.doCommitJpaTransactionManager.java:526Include@Transactional上标记为rollbackOnly的事务,请检查u添加到哪个包下。它应该是org.springframework….。有时在无意中添加javax.persistence.Transactional时,会发生这种情况。
// do some work
...

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