Синхронизировать измененные объекты в одной транзакции - PullRequest
0 голосов
/ 27 апреля 2020

У меня проблема с транзакционным методом, который изменяет сущность и хочет обновить ее другим способом.

Сначала я получаю сущность A из базы данных с помощью управления сущностями метод "получить". Затем я получаю связанный объект B , где от A до B - это тип один к одному (необязательно). (Таким образом, поле id B находится внутри таблицы A). Теперь я хочу удалить сущность B через сервисный метод. Поэтому мне нужно использовать ID из B .

Внутри метода обслуживания i получить B от менеджера сущностей (теперь B ') , Тогда я получаю A ' от добытого B' . Затем я удаляю ссылку A ' на B' , когда она присутствует через A'.setB (null) , за которой следует serviceOfA.save ( A ') .

Затем я удаляю B' через serviceOfB.delete (B ') .

Когда метод удаления B по идентификатору завершен, я хочу изменить свойства экземпляра A. Например, создайте другой экземпляр B . Теперь, когда я get A через entitymanager снова, Hibernate бросает org.hibernate.exception.ConstraintViolationException для объекта, который должен быть добавлен в новый экземпляр B '', который добавляется в A .

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

@Transactional
    public void compeleteSomething(
            @NonNull String location,
            @NonNull String nameOfA) throws SomeException{
        A a= serviceOfA.get(nameOfA);

        B b= a.getB();
        someService.removeBAndLinkToA(b.getId()); // <-- maybe here is the error

        B newInstanceOfB = someService.createBOn(location);
        someService.setBonA(serviceOfA.get(nameOfA), newInstanceOfB); // <-- serviceOfA.get() throws error

        [...]
    }

А вот метод someService.removeBAndLinkToA (#)

@Transactional
    public void removeBAndLinkToA(
            @NonNull Long id) {
        B b = serviceOfB.get(id);

        A a = b.getA();
        if (a!= null) {
            a.setB(null);
            serviceOfA.save(a); // <-- This should cause the error?
        }

        serviceOfB.delete(b);
    }

Как мне избежать этой проблемы? Большое спасибо!

1 Ответ

1 голос
/ 27 апреля 2020

При работе внутри транзакции entitymanager, как ожидается, будет иметь дело со всеми связями до фиксации, при условии, что он введен с соответствующей областью действия. Вам не нужно сохранять сущность на каждом шаге или извлекать ее снова из базы данных: ее состояние управляется диспетчером сущностей (без каламбура).

Короче говоря, ваш метод completeSomething не должен вызывать другой метод обслуживания. Просто сделайте b.setA (ноль), a.setB (новый B ()) и вернитесь. Все должно работать должным образом:

@Transactional
public void completeSomething(String aId) {
    A a = entityManager.find(A.class, aId);
    B b = a.getB();
    a.setB(new B());
    b.setA(null);
} // container should end transaction here, commiting changes to entities

Если транзакция прошла успешно, контейнер будет фиксировать изменения в сущностях, и эти изменения будут отражаться в базе данных, пока @PersistenceContext имеет тип PersistenceContextType.TRANSACTION, который является по умолчанию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...