Spring Boot: org.hibernate.StaleObjectStateException — строка была обновлена ​​или удалена другой транзакциейJAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Spring Boot: org.hibernate.StaleObjectStateException — строка была обновлена ​​или удалена другой транзакцией

Сообщение Anonymous »

Я столкнулся с ObjectOptimisticLockingFailureException, вызванным StaleObjectStateException при попытке сохранить объект FlightInstance в моем приложении Spring Boot. Полная трассировка стека выглядит следующим образом:

Код: Выделить всё

org.springframework.orm.ObjectOptimisticLockingFailureException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [app.bola.flywell.data.model.flight.FlightInstance#79e7f6b2-9364-49f4-97f6-cf5afa537b6b]
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:325)
at app.bola.flywell.services.flightservice.FlyWellFlightInstanceService.createNew(FlyWellFlightInstanceService.java:59)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
...
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [app.bola.flywell.data.model.flight.FlightInstance#79e7f6b2-9364-49f4-97f6-cf5afa537b6b]
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:426)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:630)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:359)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker$RepositoryFragmentMethodInvoker.lambda$new$0(RepositoryMethodInvoker.java:277)
at org.springframework.data.repository.core.support.RepositoryMethodInvoker.doInvoke(RepositoryMethodInvoker.java:170)
...
Моя установка
Я использую Spring Boot со следующими зависимостями:

Код: Выделить всё

spring-boot-starter-data-jpa
hibernate-core
Субъект FlightInstance наследует от родительского класса FlyWellModel. Вот соответствующий код:
Родительский класс (FlyWellModel): базовый класс для всех моделей в системе

Код: Выделить всё

public class FlyWellModel {

@Id
@GeneratedValue(strategy = GenerationType.UUID)
private String id;
@Column(nullable = false, unique = true)
private String publicId;
@CreatedDate
private LocalDateTime createdDate;
@LastModifiedDate
private LocalDateTime lastModifiedDate;
@CreatedBy
@Builder.Default
private String createdBy = "SYSTEM";
private String createdByRole;
@LastModifiedBy
private String lastModifiedBy;

@PrePersist
protected void onCreate() {
if (publicId == null || publicId.isEmpty()) {
publicId = UUID.randomUUID().toString();
}
}
}
Дочерний класс (FlightInstance): объект FlightInstance имеет поле publicId, заполняемое с помощью Аннотация @PrePersist в методе onCreate базового класса FlyWellModel

Код: Выделить всё

@Entity
@Table(name = "flight_instance")
public class FlightInstance extends FlyWellModel {

@Column(nullable = false)
private String flightNumber;
@ManyToOne(fetch = FetchType.LAZY)
@ToString.Exclude
private Flight flight;
// Other specific fields
}
При вызове метода сохранения хук @PrePersist генерирует значение для publicId, изменяя объект до завершения транзакции. . Я подозреваю, что эта модификация может привести к тому, что Hibernate будет рассматривать объект как «грязный», что приведет к исключению.
Интересно, что аналогичная настройка отлично работает для Flight. сущность, которая имеет следующую структуру:

Код: Выделить всё

@Entity
public class Flight extends FlyWellModel {
private long duration;
private String arrivalCity;
private String departureCity;
private String displayImage;

@OneToOne(cascade = CascadeType.ALL)
private Airport departureAirport;

@OneToOne(cascade = CascadeType.ALL)
private Airport arrivalAirport;

@OneToMany(mappedBy = "flight", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List flightInstances;
}
Проблема
Исключение возникает при вызове метода сохранения в FlightInstanceRepository в уровень обслуживания:
Метод обслуживания:

Код: Выделить всё

@Service
public class FlyWellFlightInstanceService {
@Autowired
private FlightInstanceRepository flightInstanceRepository;

@Override
@Transactional
@Retryable(retryFor = ObjectOptimisticLockingFailureException.class, maxAttempts = 3)
public FlightInstanceResponse createNew(FlightInstanceRequest request) {

Flight flight = flightRepository.findByPublicId(request.getFlightId())
.orElseThrow(() -> new EntityNotFoundException(Constants.ENTITY_NOT_FOUND.formatted("Flight")));

FlightInstance mappedFlightInstance = mapper.map(request, FlightInstance.class);
mappedFlightInstance.setFlight(flight);
mappedFlightInstance.setStatus(SCHEDULED);
mappedFlightInstance.setFlightSeat(new ArrayList());

FlightInstance savedInstance = flightInstanceRepository.save(mappedFlightInstance);

flight.getFlightInstances().add(savedInstance);
flightRepository.save(flight);
return flightInstanceResponse(savedInstance);
}
}
Наблюдения
  • @PrePersist на FlightInstance: Поле publicId заполняется во время сохранения, что изменяет объект во время операции сохранения.
  • Вмешательство в потоки: я подозреваю, что в игре может участвовать несколько потоков. Пока один поток изменяет объект Flight, другой поток может одновременно изменять связанный с ним объект FlightInstance, что приводит к конфликту.
Мой вопрос >
  • Вызывает ли изменение @PrePersist поля publicId исключение StaleObjectStateException? Если да, то как лучше всего с этим справиться?
  • Могут ли несколько потоков одновременно изменять объект FlightInstance, и как я могу проверить или смягчить это в настройке Spring Boot + Hibernate?< /li>
    Почему объект Flight работает без проблем, в то время как объект FlightInstance выдает это исключение при аналогичных условиях?
    4.Как решить эту проблему, чтобы объект FlightInstance был сохранен правильно, не встречая StaleObjectStateException
Будем очень признательны за любые рекомендации и идеи! Спасибо!

Подробнее здесь: https://stackoverflow.com/questions/793 ... -or-delete
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»