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,但仍然导致错误(尽管错误不同)

如何批量插入对象?

在纯休眠中存在托管和非托管环境

Non-managed environment

If an JPA persistence layer runs in a non-managed environment, database >connections are usually handled by Hibernate's pooling mechanism behind the >scenes. The common entity manager and transaction handling idiom looks like > this:

// Non-managed environment idiom

EntityManager em = emf.createEntityManager(); EntityTransaction tx = null; try { 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(); }

Using JTA If you use bean-managed transactions (BMT), the code will look like this:

// BMT idiom @Resource public UserTransaction utx; @Resource public EntityManagerFactory factory;

public void doBusiness() { EntityManager em = factory.createEntityManager(); try {

// do some work
...

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

}

With Container Managed Transactions (CMT) in an EJB3 container, transaction >demarcation is done in session bean annotations or deployment descriptors, not programatically. The EntityManager will automatically be flushed on transaction completion (and if you have injected or lookup the EntityManager, it will be also closed automatically). If an exception occurs during the EntityManager use, transaction rollback occurs automatically if you don't catch the exception. Since EntityManager exceptions are RuntimeExceptions they will rollback the transaction as per the EJB specification (system exception vs. application exception).

你应该跟二太子的。

注释@Transactional 它是spring annotaniot 不休眠。如果您没有配置它(或者您配置了 spring),则无法正常工作。

PC

An EntityManager is an inexpensive, non-threadsafe object that should be used once, for a single business process

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