Изменения, не отраженные после «обновления» объекта с помощью Spring JPA

Я изо всех сил пытаюсь «обновить» объект (Foo), который выглядит так:

public class Foo {

    //...
    @OneToMany(mappedBy = "fooRef", fetch = FetchType.LAZY)
    private List<Bar> bars;
}


public class Bar {

    //...
    @Column(name = "FOO_ID")
    private Long fooRef;
    @Column(name = "STATE")
    @Enumerated(EnumType.STRING)
    private State state;
}

Как Spring JPA не реализует метод обновления, я просто снова запрашиваю объект. Это код, который не работает, и я не знаю почему:

for(int i=0; i<MAX_RETRIES; i++) {

    List<Bar> bars = foo.getBars();

    // check bars state

    if (someBarIsBad) {
        try {
            TimeUnit.SECONDS.sleep(delay);
        } catch (InterruptedException ignored) {

        }
    } else {
        break;
    }

    foo = fooRepo.findById(fooId);  // "refresh"
}

Цель состоит в том, чтобы продолжить повторную попытку, пока все столбцы не достигнут желаемого состояния. Тест, который я выполняю, помещает точку останова в последнюю инструкцию цикла, поэтому, когда она прерывается, я иду к таблице и меняю состояние всех полос на желаемое, чтобы затем выйти из цикла. Дело в том, что возвращенный foo, bars не отражает внесенные мной изменения.

Пробовал убрать сон, но проблема не в этом. Думаю, должно быть что-то с маппингом.

Предполагаю, что проблема в fetch = FetchType.LAZY. bars будет обновлен, когда вы попытаетесь их использовать. Попробуйте сделать что-то подобное после обновления for (Bar bar : foo.getBars()) { sout(bar);} . Надеюсь, это вызовет ленивую инициализацию.

Danila Zharenkov 30.05.2018 11:11

Я тестировал удаление LAZY fetching, но результат тот же. В любом случае, это не должно быть проблемой, поскольку я извлекаю bars с тем же прицелом, что и foo. Что ты имеешь в виду под sout? Это метод jpa?

anat0lius 30.05.2018 11:27

nonono, sout - это ярлык для System.out.println(). Удаление выборки некорректно, причина для отношения OneToMany - тип выборки по умолчанию LAZY. Так что это удаление ничего не меняет. Попробуйте изменить выборку с LAZY на EAGER. И да, вы правы - область действия такая же, но разница в прямом и непрямом использовании таблицы сущностей Bar.

Danila Zharenkov 30.05.2018 11:36

Это действительно странно. Я пробовал с eagger fetch, ничего. Я пробовал напрямую получить barRepo.findByFooRef, но ничего. И я уже уверяю, что вношу изменения напрямую с помощью коммита.

anat0lius 30.05.2018 12:35
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
4
628
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

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

Либо убедитесь, что вы находитесь в новой транзакции при каждом «обновлении», либо исключите объект из сеанса, чтобы он снова перезагружался.

Имеет смысл. Но я не уверен, как мне изолировать транзакцию. Я взял fooRepo.findById(fooId) и обернул его методом, аннотированным @Transactional. Все еще не возвращает мне обновленную версию.

anat0lius 30.05.2018 15:07

Важная часть заключается в том, что код, который вы показали в своем вопросе, НЕ заключен в метод, аннотированный @Transactional.

Jens Schauder 30.05.2018 15:41

Я сделал, и код выше, и getFoo(ID) являются транзакционными. Все тот же :(

anat0lius 30.05.2018 15:49

Ладно, я понял. Я не знал об уровнях изоляции. IN с аннотациями get FooD) с @Transactional(readOnly = true, isolation = Isolation.REPEATABLE_READ)

anat0lius 30.05.2018 16:35

Другие вопросы по теме