jpa2 повторно использует entityManager с guice

У меня есть веб-приложение, которое имеет странное поведение, и я не могу его понять. Суть моей проблемы заключается в непоследовательном поведении значений, возвращаемых моими конечными точками отдыха. Когда я запускаю свое приложение, мой запрос возвращает одни и те же значения каждый раз, когда я вызываю эту конечную точку. Когда я обновляю сущность, мой менеджер сущностей начинает вести себя странно. Теперь мой запрос начинает возвращать разные результаты. Один раз он возвращает старые значения вместо значений, которые есть в базе данных, или мой список результатов содержит прокси вместо объектов (смешанный). введите здесь описание изображения

Я проверил, что мои методы @transaction размещены правильно, и в моем стеке отладки я вижу перехватчик транзакций, а диспетчер сущностей создается для каждого запроса к серверной части (поэтому нет фильтра постоянства guice)

Я чувствую, что проблема заключается в контексте сеанса. У меня такое чувство (но я не могу его понять), что он повторно использует мой контекст сохранения по нескольким запросам.

Я собрал несколько фреймворков, чтобы все это работало. Я использую resteasy как реализатор jax-rs. guice (4.0beta4) в качестве средства реализации cdi и hibernate в качестве средства реализации jpa. Поскольку нам нужно использовать провайдера, когда мы внедряем менеджер сущностей (поскольку менеджер сущностей создается для каждой транзакции), я обернул это в EntityManagerProxy. Этот класс реализует интерфейс EntityManager и делегирует все методы в provider.get().method().

public class EntityManagerProxy implements EntityManager {
    private final Provider<EntityManager> entityManagerProvider;

    @Inject
    public EntityManagerProxy(final Provider<EntityManager> entityManagerProvider) {
        this.entityManagerProvider = entityManagerProvider;
    }

    private EntityManager getEntityManager() {
        return entityManagerProvider.get();
    }

    @Override
    public void persist(final Object entity) {
        getEntityManager().persist(entity);
    }
}

Мой модуль guice выглядит так

public class OptiWEEEModule extends ServletModule implements Module {
    @Override
    protected void configureServlets() {

        super.configureServlets();
        bind(EntityManagerProxy.class);
        // JPA
        install(new JpaPersistModule("myPU"));
    }
}

Я знаю, что это расплывчатая проблема, но может ли кто-нибудь помочь мне в правильном направлении? На самом деле это не проблема, для которой я могу предоставить сообщение об ошибке.

редактировать: теперь я указал на проблему. С помощью профилировщика я посмотрел, что контекст сущности повторно используется guice. Это означает, что он не выполняет запрос каждый раз, а использует существующий диспетчер сущностей, который должен создаваться каждый раз при передаче аннотации @transactional.


person jelle    schedule 06.05.2014    source источник
comment
Я только что перешел с guice 4beta4 на guice 3, и возникает та же ошибка.   -  person jelle    schedule 07.05.2014
comment
Идея @Transactional заключается в том, что вы получаете новую транзакцию, а не новый EntityManager. Последний также может справиться с некоторыми из них. Вы не показываете часть обновления вашего прокси-сервера или веб-сервисов, поэтому трудно сказать, что на самом деле вызывает вашу проблему.   -  person mabi    schedule 07.05.2014
comment
Я действительно углубился в проблему. Не часть обновления нарушает мое приложение, а entitymanager повторно используется в каждом потоке. Я предполагаю, что я создаю синглтон, который содержит мой entitymanager. Может ли мой entitymanagerproxy быть причиной этого? это стратегия, которой я следую code.google. com/p/google-guice/wiki/   -  person jelle    schedule 07.05.2014
comment
Этот вопрос звучит похоже.   -  person mabi    schedule 07.05.2014
comment
@mabi Вопрос действительно очень похож, но я уже ввожу провайдера в каждую точку   -  person jelle    schedule 07.05.2014


Ответы (1)


Я получил этот awnser из списков рассылки.

У Guice perstist есть особенность, которая довольно необычная и вызывает некоторые проблемы. Я думаю, вы могли бы просто ударить его

Когда вы запрашиваете диспетчер сущностей за пределами единицы работы, постоянный интерфейс неявно запускает единицу работы для вас. К сожалению, isActive() в UnitOfWork является частным пакетом. И вы не можете проверить, активна ли единица работы.

Есть два способа явного запуска и завершения единицы работы. Вы можете использовать UnitOfWork и методы begin() и end(). Также аннотация @Transactional запускает единицу работы. @Transactional также завершит единицу работы тогда и только тогда, когда она ее начала.

Лучше всего получать диспетчер сущностей только в методе @Transactional.

Я могу только заключить, что аннотация @Transaction не имеет того же уровня зрелости, что и весной. С другой стороны, получение менеджера сущностей в менеджере @Transactional через провайдера на самом деле не решает эту проблему.

Поскольку мы очень скоро переходим к производству, я вернулся к весне, что досадно, но это было единственное разумное решение, чтобы уложиться в срок.

person jelle    schedule 18.06.2014