SpringData/Hibernate @ManyToOne автоматически каскадирует, когда это не должно

86
9

Учитывая две сущности, такие как

@Entity
public class Thing {
@ManyToOne
private ThingType thingType;
...
}

@Entity
public class ThingType {
private String name;
...
}

Из всего, что я прочитал, каскад по умолчанию должен быть ничем, поэтому, если я получаю ссылку на Thing thing и изменяю поле имени своего ThingType, то с помощью JpaRepository<Thing, Long> call thingRepo.save(thing), я ожидал, что изменение имени ThingType не будет сохранено.

Однако это не так, и это изменение сохраняется. Я не знаю, почему это происходит? Что мне здесь не хватает?

Соответствующие версии:

    org.springframework.boot: весна-ботинки: баночка: 1.5.7.RELEASE org.hibernate: спящий режим жилы: баночка: 5.0.12.Final org.springframework.data:spring-data-jpa:jar:1.11.7.RELEASE

спросил(а) 2018-05-11T04:19:00+03:00 2 года, 2 месяца назад
1
Решение
54

Ну, каскадирование - это что-то еще, позвольте мне кое-что спросить. Делайте следующие вещи:

Thing thing = session.get(Thing .class, someId);
thing.getThingType().setTitle("new title");

и ничего более, снова вы видите hibernate updates thingType.

Он называется грязной проверкой, если объект привязан к активному сеансу спящего режима, а его состояние сохранения состояния hibernate автоматически обновляет связанную с ним строку в базе данных. Событие без вызова сохранения или обновления.

Итак, что такое каскад? Рассмотрим следующий случай:

Thing myThing = new Thing();
ThingType myThingType = new ThingType();
myThing.setThingType(myThingType);
session.save(myThing);

если тип каскада ассоциации не задан, вы получите исключение, потому что вы ссылаетесь на объект переходного объекта thingType. Но если вы настроите тип каскада на сохранение, то сначала спящий режим сохраняет thingType а затем сохраняет thing, и все идет хорошо.

Поэтому помните, что если вы извлекаете объект, а затем обновляете его свойства в том же сеансе, нет необходимости вызывать метод update или saveOrUpdate в сеансе спящего режима (или jpa entityManager), поскольку он уже находится в attached состоянии, и его состояние отслеживается спящий режим.

ответил(а) 2018-05-11T04:56:00+03:00 2 года, 2 месяца назад
54

Ну, я бы ожидал того же самого, но похоже, что Hibernate имеет свое собственное поведение по умолчанию. На форуме Hibernate кто-то задал почти тот же вопрос. Ответ относится к функции "грязной проверки" Hibernate, которая будет обнаруживать и перестроить/слить изменение. Вы можете изменить это поведение, используя аннотацию Hibernate Cascade.

ответил(а) 2018-05-11T04:43:00+03:00 2 года, 2 месяца назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема