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

时间:2017-06-07 18:37:34

标签: 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().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 session = em.unwrap(Session.class);,但仍然导致错误(尽管错误不同)

如何批量插入对象?

1 个答案:

答案 0 :(得分:1)

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

  

非托管环境

     

如果JPA持久层在非托管环境中运行,则数据库&gt;连接通常由Hibernate在&gt;场景后面的池化机制处理。公共实体管理器和事务处理习惯用法看起来像&gt;这样:

     

//非托管环境习惯用法

     

EntityManager em = emf.createEntityManager(); EntityTransaction 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成语   @Resource public UserTransaction utx;   @Resource公开   EntityManagerFactory工厂;

     

public void 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),事务&gt;分界在会话bean注释中完成   或部署描述符,而不是以编程方式。 EntityManager会   在交易完成时自动刷新(如果有的话)   注入或查找EntityManager,它也将被关闭   自动)。如果在EntityManager使用期间发生异常,   如果你没有捕获,事务回滚会自动发生   例外。由于EntityManager异常是RuntimeExceptions,因此   将根据EJB规范(系统)回滚事务   异常与应用程序异常)。

你应该继续两个王子。

注释@Transactional它的春天annotaniot不休眠。如果你没有;配置它(或你确实配置了弹簧)不起作用。

PC

  

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

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