سؤال

There's an OpenJPA 1.2.3 application running on WebSphere 7 and for some reasons we can't use dependency injection for entity managers there. So we manage them manually closing them after the transaction is commited/rolled back. Recently I've found that call to EntityManager.close() takes a considerable amount of time (about 10% of the whole operation involving loading of ~500 entities). What it does is detaching all entities loaded during the transaction. So there are actually 2 questions:

  1. Why in general do we need to detach all entities on entity manager close? Is it because JPA have to check all entities whether they are dirty or not?
  2. Since in some cases entities are loaded for read-only access - is it possible to somehow tell OpenJPA that these entities are not supposed to be updated and there's no need to mark them as dirty, update to DB, etc.?

Adding my persistence.xml as requested:

<?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>
هل كانت مفيدة؟

المحلول

Why in general do we need to detach all entities on entity manager close? Is it because JPA have to check all entities whether they are dirty or not?

The behavior is defined per the JPA spec. The somewhat short story is that when an Entity is managed, it is associated with a given EntityManager. If/when you close that EntityManager you must tell each managed Entity that it's Manager is now closed. This should be a fairly lightweight operation, but I've found in practice that isn't always the case. The reason is that OpenJPA inserts a data structure to track the dirtiness of an Entity while it is no longer tracked. This is optimized for the case where you might merge one of these detached Entities back into another persistence context (EntityManager).

Since in some cases entities are loaded for read-only access - is it possible to somehow tell OpenJPA that these entities are not supposed to be updated and there's no need to mark them as dirty, update to DB, etc.?

Yes and no. There is a feature, LiteAutoDetach that was added in OpenJPA 2.0.0 that will make the detach process much lighter weight. The downside is that you will give up some performance/functionality in the case where you might want to merge one of the detached Entities back into a persistence context.

I would suggest that you profile the EntityManager.close() operation to see where a majority of the time is being spent. It is possible that you are using some other OpenJPA features that are causing this performance problem.

For grins, could you update the post with the contents of your persistence.xml file?

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top