我正在尝试编写一个批量添加实体到数据库的方法。这是我的方法:
@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);
,但仍然导致错误(尽管错误不同)
如何批量插入对象?
答案 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()可能很危险。