Я пытаюсь использовать JPA (с Hibernate), чтобы сохранить 2 объекта.Данные Spring предоставляют интерфейс, но я не думаю, что это имеет значение здесь.
У меня есть основная сущность под названием «Модель».Эта модель имеет много связанных объектов «Параметр».Я пишу метод для сохранения модели и ее параметров.
Это метод:
private void cascadeSave(Model model) {
modelRepository.save(model);
for (ParameterValue value : model.getParameterValues()) {
parameterValueRepository.save(value);
}
}
Это проблема:
Когда я загружаю модельчто уже существовало до , добавьте в него некоторые новые параметры и затем вызовите этот метод для сохранения их обоих, что-то странное происходит:
Перед первым сохранением (modelRepository.save) это то, чтоДанные модели при отладке выглядят так:
Модель имеет 2 параметра с заполненными значениями (имя и модель заполнены).
Теперь, после сохранения модели первого сохранения в моем методе, это происходит.Обратите внимание, что ссылка на объект является другой, поэтому Hibernate должен был сделать что-то волшебное и воссоздать значения, а не оставлять их в покое:
Почему-тоhibernate очистил все атрибуты параметров в наборе.
Теперь, когда сохранение нового параметра происходит в следующем коде, происходит сбой из-за ненулевых ограничений и т. д.
Мой вопрос: почемуhibernate очищает все поля?
Вот соответствующие сопоставления:
ParameterValue
@Entity
@Table(name = "tbl_parameter_value")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "PARAMETER_TYPE")
public abstract class ParameterValue extends AbstractBaseObject {
@Column(nullable = false)
@NotBlank
private String name;
private String stringValue;
private Double doubleValue;
private Integer intValue;
private Boolean booleanValue;
@Enumerated(EnumType.STRING)
private ModelType modelParameterType;
@Column(precision = 7, scale = 6)
private BigDecimal bigDecimalValue;
@Lob
private byte[] blobValue;
ParameterValue() {
}
ParameterValue(String name) {
this.name = name;
}
ModelParameterValue
@Entity
@DiscriminatorValue(value = "MODEL")
public class ModelParameterValue extends ParameterValue {
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "model_id", foreignKey = @ForeignKey(name = "FK_VALUE_MODEL"))
private Model model;
ModelParameterValue() {
super();
}
ModelParameterValue(String name) {
super(name);
}
Модель
@Entity
@Table(name = "tbl_model")
public class Model extends AbstractBaseObject implements Auditable {
@OneToMany(fetch = FetchType.LAZY, mappedBy = "model")
private Set<ModelParameterValue> parameterValues = new HashSet<>();
РЕДАКТИРОВАТЬ
Мне удалось воспроизвести это на минимальном примере.Если вы замените все данные Spring, то это то, что произошло под капотом (например, JPA EntityManager):
public Model simpleTest() {
Model model = new Model("My Test Model");
em.persist(model);
model.addParameter(new Parameter("Param 1"));
em.merge(model);
for (Parameter child : model.getParameters()) {
em.persist(child);
}
return model;
}
При выполнении слияния все атрибуты параметров устанавливаются в ноль.На самом деле они просто заменены совершенно новыми параметрами.