OpenJPA:在EntityManager.close()上分离所有实体

时间:2014-01-29 15:13:12

标签: java jpa openjpa

在WebSphere 7上运行OpenJPA 1.2.3应用程序,由于某些原因,我们无法在那里使用依赖注入实体管理器。因此,我们在提交/回滚事务后手动关闭它们。最近我发现调用EntityManager.close()需要相当长的时间(约占整个操作的10%,涉及加载~500个实体)。它的作用是分离在事务期间加载的所有实体。 所以实际上有两个问题:

  1. 为什么我们一般需要将实体经理上的所有实体分开关闭?是因为JPA必须检查所有实体是否脏了?
  2. 因为在某些情况下实体被加载为只读访问 - 是否有可能以某种方式告诉OpenJPA这些实体不应该更新,并且不需要将它们标记为脏,更新到DB等?
  3. 根据要求添加persistence.xml

    <?xml version="1.0" encoding="UTF-8"?>
    <persistence xmlns="http://java.sun.com/xml/ns/persistence"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
        version="1.0">
        <persistence-unit name="DocumentUnit" transaction-type="JTA">
            <provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
            <class>ru.mypackage.Document</class>
            <class>ru.mypackage.DocParam</class>
            <class>ru.mypackage.DocParamPK</class>
            <!-- Some more classes -->
            <exclude-unlisted-classes>true</exclude-unlisted-classes>
            <properties>
            </properties>
        </persistence-unit>
    </persistence>
    

1 个答案:

答案 0 :(得分:1)

  

为什么我们一般需要将实体经理上的所有实体分开关闭?是因为JPA必须检查所有实体是否脏了?

根据JPA规范定义行为。有点简短的故事是,当管理实体时,它与给定的EntityManager相关联。如果/当您关闭该EntityManager时,您必须告诉每个管理实体它的管理器现在已关闭。这应该是一个相当轻量级的操作,但我发现在实践中并非总是如此。原因是OpenJPA插入了一个数据结构来跟踪实体在不再被跟踪时的肮脏。这是针对您可能将其中一个分离的实体合并回另一个持久化上下文(EntityManager)的情况进行优化的。

  

因为在某些情况下实体被加载为只读访问 - 是否有可能以某种方式告诉OpenJPA这些实体不应该更新,并且不需要将它们标记为脏,更新到DB等? / p>

是和否。有一个feature, LiteAutoDetach that was added in OpenJPA 2.0.0会使分离过程的重量轻得多。缺点是,如果您希望将其中一个分离的实体合并回持久性上下文,您将放弃一些性能/功能。

我建议您分析EntityManager.close()操作以查看大部分时间花在哪里。您可能正在使用导致此性能问题的其他一些OpenJPA功能。

对于grins,您可以使用persistence.xml文件的内容更新帖子吗?