Почему Hibernate объединяет несвязанные объекты при сохранении () - PullRequest
0 голосов
/ 02 марта 2020

В моем проекте Spring Boot 2.1.8 у меня есть следующие сущности:

@Entity
@Table(name = "teacher")
@Where(clause = "active = true")
class TeacherEntity {
  @Id
  @Column(name = "id")
  public String id;

  @Basic
  @Column(name = "active")
  public boolean active;

  @Basic
  @Column(name = "name")
  public String name;
}

@Entity
@Table(name = "course")
class CourseEntity {
  @Id
  @Column(name = "id")
  public int id;

  @ManyToOne
  @JoinColumn(name = "course_id")
  public TeacherEntity teacher;
}

@Entity
@Table(name = "seat")
class SeatEntity {
  @Id
  @Column(name = "id")
  public int id;

  @ManyToOne
  @JoinColumn(name = "parent_id")
  public CourseEntity course;

  @Basic
  @Column(name = "blabla")
  public String blabla;
}

Ситуация: SeatEntity был создан и сохранен для действительного курса, имеющего действующего учителя. Позже мы загрузили SeatEntity из базы данных, изменили ее поле blabla и попытались сохранить его.

public void updateSeats() {
  List<SeatEntity> seats = seatRepository.findAllBy____();
  seats.forEach(seat -> {
    seat.blabla = "new blabla!";
    seat = seatRepository.save(seat); // Exception if Teacher.active = false!
  });
}

Исключение, которое я получаю:

Причина: javax.persistence.EntityNotFoundException: Невозможно найти com.company.TeacherEntity с идентификатором 5770d5e3-d7e8-401e-84c5-bb3d83e2e484 в org.hibernate.jpa.boot.internal.EntityManagerFactoryNactFact в org.hibernate.event.internal.DefaultLoadEventListener.load (DefaultLoadEventListener. java: 216) в org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad (DefaultLoadEventListener. javah. .DefaultLoadEventListener.doOnLoad (DefaultLoadEventListener. java: 108) в org.hibernate.event.internal.DefaultLoadEventListener.onLoad (DefaultLoadEventListener. java: 74) в org.hibernate.pl : 1298) в org.hibernate.internal.SessionImpl.internalLoad (S essionImpl. java: 1161) в org.hibernate.type.EntityType.resolveIdentifier (EntityType. java: 687) в org.hibernate.type.EntityType.resolve (EntityType. java: 464) в org.hibernate. .type. . java: 160) в org.hibernate.loader.Loader.initializeEntitiesAndCollections (Loader. java: 1179) в org.hibernate.loader.Loader.processResultSet (Loader. java: 1028) в org.hibernate. loader.Loader. 324) в org.hibernate.loader.Loader.loadEntity (Loader. java: 2401) в org.hibernate.loader.entity.AbstractEntityLoader.load (AbstractEntityLoader. java: 64) в org.hibernate.loader.entity .AbstractEntityLoader .load (AbstractEntityLoader. java: 54) по адресу org.hibernate.persister.entity.AbstractEntityPersister.load (AbstractEntityPersister. java: 4312) по адресу org.hibernate.event.internal.DefaultLoadEventListener.loadFromDatasventELererLaderEventLot : 570) в org.hibernate.event.internal.DefaultLoadEventListener.doLoad (DefaultLoadEventListener. java: 538) в org.hibernate.event.internal.DefaultLoadEventListener.load (DefaultLoadEventListener. java: 20): 208): 20). event.internal.DefaultLoadEventListener.proxyOrLoad (DefaultLoadEventListener. java: 333) в org.hibernate.event.internal.DefaultLoadEventListener.doOnLoad (DefaultLoadEventListener. java: 108). DefaultLoadEventListener. java: 74) в org.hibernate.internal.SessionImpl.fireLoadNoChecks (SessionImpl. java: 1298) в org.hibernate.internal.SessionImpl.internalLoad (SessionImpl. java: 1161 at) или 661 at). .type.EntityType.resolveIdentifier (EntityType. java: 687) в org.hib ernate.type.EntityType.resolve (EntityType. java: 464) в org.hibernate.type.ManyToOneType.resolve (ManyToOneType. java: 240) в org.hibernate.engine.internal.TwoPhaseLoad.hadeLad.Oit java: 226) в org.hibernate.engine.internal.TwoPhaseLoad.initializeEntity (TwoPhaseLoad. java: 160) в org.hibernate.loader.Loader.initializeEntitiesAndCollections (Loader. java: 1179) или .loader.Loader. processResultSet (Loader. java: 1028) в org.hibernate.loader.Loader.doQuery (Loader. java: 964) в org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections (Loader. java: 354) .hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections (Loader. java: 324)

Почему Hibernate жалуется на загрузку объединенной таблицы, не связанной с данными, которые я пытаюсь использовать сохранить? Какое решение этой проблемы? Нужно ли писать собственный запрос на обновление, чтобы обойти бессмысленное объединение и сохранить данные?

1 Ответ

0 голосов
/ 03 марта 2020

Оказывается, что проблема была решена путем включения метода в транзакцию:

@Transactional
public void updateSeats() {
  // same code as above
}

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

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