1

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

我在persistence.xml 中设置eclipselink.jdbc.batch-writingJDBC但它没有按预期工作。

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

 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

有什么我想念的想法吗?我认为问题的根源是每个持久化的单独工作单元。

注意确实看到在单个工作单元中通过单个持久性级联的子实体的批处理工作。但是每组父/子都是一个单独的批次。

4

2 回答 2

0

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

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

于 2013-04-15T13:31:31.587 回答
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不太熟悉]

于 2013-04-13T10:56:06.443 回答