StaleObjectStateException при попытке добавить @Version в сущность JPA

Я пытаюсь использовать спящий режим в своем проекте для управления версиями. Использовал jpa, репозиторий jpa, spring и hibernate в качестве провайдера.

Есть jpa entity

@Entity
@Audited
@IdClass(CusomerId.class)
@Table(name = "Cusomer", uniqueConstraints = {
        @UniqueConstraint(columnNames = { "name", "surname", "org" })})
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@Getter
@Setter
public class Customer {
    @Id
    @Column(name = "name", length = 100, unique = false, nullable = false)
    private String name;

    @Id
    @Column(name = "surname", length = 100, unique = false, nullable = false)
    private String surname;

    @Id
    @Column(name = "org", length = 100, unique = false, nullable = false)
    private String org;

    @Column(name = "metaInfo", length = 100, unique = false, nullable = true)
    private String metaInfo;

    public Customer(String name, String surname, String org, String metaInfo) {
        this.name=name;
        this.surname=surname;
        this.org=org;
        this.metaInfo=metaInfo;
    }
}

В приложении я использую Jpa Repository, поэтому мой репозиторий выглядит как

@Repository
public interface CustomerRepository extends CrudRepository<Customer, CutomerId>{}

В моем потоке

Customer customer1 = new Customer("aaa", "bbb", "23", "this is secret info1")
Customer customer2 = new Customer("aaa", "bbb", "23", "this is secret info2 updated")
Customer customer3 = new Customer("aaa", "bbb", "23", "this is secret info3")

Я просто звоню

customerRepository.save(customer1); 
customerRepository.save(customer2);
customerRepository.save(customer3);

Код работает нормально, и в базе я обновил объект. Но если я добавлю к своей сущности версию @Version; table, когда я пытаюсь сохранить customer3.

Я ожидаю, что эта проблема связана с методом сохранения в StaleObjectStateException. Если сущность существует, она пытается объединить новую сущность с сущностью с тем же ключом.

P.S. У меня w.a. gor эту проблему, но я верю, что существует правильный способ решить эту проблему. Вместо SimpleJpaRepository и save в других случаях сущности я в первый раз пишу в базе, в других случаях я читаю из базы и обновляю сущность вручную

public void add(String name, String surname, String age,
                    String metaInfo) {
        Customer customer = CustomerRepository.findRiskBustomerByNameAndSurnameAndAge(
                name, surname, age);

        if (customer == null) {
            customer = new Customer(name, surname,
                    age, metaInfo);

            customerRepository.save(customer);
        } else {
            customer.setMetaInfo(metaInfo);

        }
        customerRepository.save(customer);
    }

Вы должны, по крайней мере, правильно реализовать hashCode и equals, иначе спящий режим не сможет обнаружить присутствие объекта. То же и для вашего класса CusomerId.

M. Deinum 01.11.2018 12:40

Также метод save проверяет, существует ли объект в текущем EntityManager, он не проверяет, существует ли он в базе данных !.

M. Deinum 01.11.2018 12:41

Указанная версия @ M.Deinum должна использоваться в hashCode и равна?

Roberto 01.11.2018 12:43

нет, не должно. Ни metaInfo.

M. Deinum 01.11.2018 12:44

@ M.Deinum переопределил хэш-код и равенство не помогло (то же сообщение об ошибке). Что касается EntityManager, может быть, мне нужно выполнить какие-либо операции очистки после сохранения объекта?

Roberto 01.11.2018 13:14

Вы должны сделать то же самое для класса CustomerId.

M. Deinum 01.11.2018 15:17

@ M.Deinum так не работает

Roberto 01.11.2018 15:26

На самом деле он действительно работает и делает именно то, что должен делать, если взглянуть на него еще раз. Вы сохраняете первый Customer, получивший версию. Затем вы сохраняете вторую, у которой нет версии. Следовательно, в спящем режиме не удается указать, что объект, который вы пытаетесь сохранить, устарел, поскольку в базе данных есть более новая версия. Так что в основном это работает так, как должно.

M. Deinum 01.11.2018 15:28
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
8
126
0

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