EclipseLink批处理写入不适用于JPA / JTA应用程序

时间:2013-04-11 21:32:56

标签: spring jpa eclipselink

我正在Glassfish 3.1.2.2,EclipseLink 2.3.2上编写JPA应用程序。我也使用Spring MVC,容器管理的EntityManager(@PersistenceContext由Spring注入,但是由容器通过jee:jndi-lookup创建)

我在persistence.xml中将eclipselink.jdbc.batch-writing设置为JDBC,但它没有按预期工作。

我的代码有一个相当简单的循环来编写一堆对象

 UserTransaction tx = ...;
 tx.begin();
 for (MyObject obj : list) { 
   entityManager.persist(obj);
 }
 tx.commit();

如果我将UserTransaction替换为方法周围的@Transactional注释,则批量编写 可以正常工作!

我看到为每个持久呼叫创建了一个单独的工作单元:

FINER: client acquired: 3418589
FINER: TX binding to tx mgr, status=STATUS_ACTIVE
FINER: acquire unit of work: 11053522
FINEST: persist() operation called on: mypkg.MyClass@1252ed8
....
FINER: client acquired: 23361578
FINER: TX binding to tx mgr, status=STATUS_ACTIVE
FINER: acquire unit of work: 17636998
FINEST: persist() operation called on: mypkg.MyClass@1252ed8

在提交之前,数据库操作实际上并不按预期执行 - 但每个工作单元都有自己的批处理:

FINER: TX beforeCompletion callback, status=STATUS_ACTIVE
FINER: begin unit of work commit
FINER: TX beginTransaction, status=STATUS_ACTIVE
FINEST: Execute query InsertObjectQuery(mypkg.MyClass@12a46ef)
FINEST: Connection acquired from connection pool [default].
FINEST: Execute query  
FINER: Begin batch statements
FINE: INSERT INTO ....
FINE:   bind => [24 parameters bound]
FINER: End Batch Statements

我缺少什么想法?我认为问题的根源是每个持续存在的单独工作单元。

注意执行查看在单个工作单元中通过单个持久性级联的子实体的批处理工作。但每组父母/子女都会产生一个单独的批次。

2 个答案:

答案 0 :(得分:0)

  • 对于Oracle,您可以尝试在persistence.xml中配置它。

    <property name="eclipselink.jdbc.batch-writing" value="Oracle-JDBC"/>

    来自文档:

      

    oracle-jdbc :使用Oracle平台的本机批量写入。在属性映射中,使用OracleJDBC。

         

    注意:这需要Oracle JDBC驱动程序。

  • 否则,也可以通过属性进行配置。

    propertyMap.put(PersistenceUnitProperties.BATCH_WRITING, BatchWriting.OracleJDBC);

与批量写入相结合,可以eclipselink.jdbc.batch-writing.size指定批量大小。

[帖子是EclipseLink特有的,我对Spring不太熟悉]

答案 1 :(得分:0)

您似乎在混合Java EE事务和Spring事务。你需要使用其中一个。

如果要使用JTA,则需要配置persistence.xml以使用JTA,并确保正确设置“eclipselink.target-server”(如果从Glassfish访问它,将默认设置它) ,但如果你从Spring访问它,它将不会。)