OpenJPA: отсоединение всех объектов от EntityManager.close()

В WebSphere 7 работает приложение OpenJPA 1.2.3, и по некоторым причинам мы не можем использовать там внедрение зависимостей для менеджеров сущностей. Таким образом, мы управляем ими вручную, закрывая их после фиксации/отката транзакции. Недавно я обнаружил, что вызов EntityManager.close() занимает значительное время (около 10% всей операции, включающей загрузку ~500 сущностей). Что он делает, так это отсоединяет все объекты, загруженные во время транзакции. Так что собственно 2 вопроса:

  1. Почему вообще нам нужно отсоединять все сущности при закрытии диспетчера сущностей? Это потому, что JPA должен проверять все объекты, грязные они или нет?
  2. Поскольку в некоторых случаях сущности загружаются для доступа только для чтения - можно ли как-то указать OpenJPA, что эти сущности не должны обновляться и нет необходимости помечать их как грязные, обновлять в БД и т.д.?

Добавление моего 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>

person FlasH from Ru    schedule 29.01.2014    source источник


Ответы (1)


Почему вообще нам нужно отсоединять все сущности при закрытии диспетчера сущностей? Это потому, что JPA должен проверять все объекты, грязные они или нет?

Поведение определяется спецификацией JPA. Несколько краткая история заключается в том, что когда Entity управляется, он связан с данным EntityManager. Если/когда вы закрываете этот EntityManager, вы должны сообщить каждому управляемому объекту, что его менеджер теперь закрыт. Это должна быть довольно легкая операция, но на практике я обнаружил, что это не всегда так. Причина в том, что OpenJPA вставляет структуру данных для отслеживания «грязности» Entity, пока она больше не отслеживается. Это оптимизировано для случая, когда вы можете объединить одну из этих отдельных сущностей обратно в другой контекст сохраняемости (EntityManager).

Поскольку в некоторых случаях сущности загружаются для доступа только для чтения - можно ли как-то указать OpenJPA, что эти сущности не должны обновляться и нет необходимости помечать их как грязные, обновлять в БД и т.д.?

Да и нет. Существует функция LiteAutoDetach, добавленная в OpenJPA 2.0. 0, что сделает процесс отсоединения намного легче. Недостатком является то, что вы откажетесь от некоторой производительности/функциональности в случае, если вы захотите объединить одну из отсоединенных сущностей обратно в контекст персистентности.

Я бы посоветовал вам профилировать операцию EntityManager.close(), чтобы увидеть, на что тратится большая часть времени. Возможно, вы используете некоторые другие функции OpenJPA, которые вызывают эту проблему с производительностью.

Ради улыбки, не могли бы вы обновить сообщение, указав содержимое вашего файла persistence.xml?

person Rick    schedule 03.02.2014
comment
Добавил в пост свой файл persistence.xml, но не думаю, что поможет - он простой как кирпич. В любом случае я принимаю ответ, так как это был скорее теоретический вопрос... Я уже профилировал EntityManager.close() и в основном это было причиной этого вопроса) Большая часть времени была потрачена на отсоединение всех известных сущностей (не помню хотя точное имя метода указано как момент ( ).В любом случае, это еще одна причина перейти на JPA 2.0 как можно скорее. - person FlasH from Ru; 04.02.2014