У меня простые двусторонние отношения родитель / потомок, где дети находятся в упорядоченном списке.
Родитель:
@Entity
@Table(name = "Parent")
public class Parent {
@Id
private String name;
@OneToMany(mappedBy = "parent", cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = true)
@OrderColumn(name = "childIndex")
private final List<Child> children = new ArrayList<>();
public void setName(final String name) {
this.name = name;
}
public void addChild(final Child child) {
this.children.add(child);
}
}
Ребенок:
@Entity
@Table(name = "Child")
public class Child {
@Id
@GeneratedValue(generator = "hibernate-uuid")
@GenericGenerator(name = "hibernate-uuid", strategy = "uuid2")
private String id;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "parentName")
private Parent parent;
Child() {}
public Child(final Parent parent) {
this.parent = parent;
}
}
Я добавляю экземпляры Parent и Child вот так:
SessionFactory sessionFactory = ...
try (Session session = sessionFactory.openSession()) {
session.beginTransaction();
Parent parent = new Parent();
parent.setName("SomeName");
Child child = new Child(parent);
parent.addChild(child);
session.merge(parent);
session.getTransaction()
.commit();
}
Это отлично работает и приводит к следующему SQL:
Hibernate: select parent0_.name as name1_1_1_, children1_.parentName as parentNa2_0_3_, children1_.id as id1_0_3_, children1_.itemIndex as itemInde3_3_, children1_.id as id1_0_0_, children1_.parentName as parentNa2_0_0_ from Parent parent0_ left outer join Child children1_ on parent0_.name=children1_.parentName where parent0_.name=?
Hibernate: insert into Parent (name) values (?)
Hibernate: insert into Child (parentName, id) values (?, ?)
Hibernate: update Child set itemIndex=? where id=?
Можно ли удалить оператор UPDATE и вместо этого установить childIndex при вставке строки Child?
Я попытался установить nullable=false в аннотации OrderColumn, но это привело к ошибке null value in column "childindex" violates not-null constraint, так как Hibernate все еще пытается вставить столбец Child без установки childindex.
Заранее спасибо!
Редактировать:
Согласно предложению Мика, я явно добавил атрибут childIndex в дочернюю сущность, например:
@Column(nullable = false)
private int childIndex;
Хотя это приводит к тому, что столбец становится ненулевым, лишний оператор UPDATE не удаляется. С этим изменением Hibernate, похоже, устанавливает для childIndex значение 0 на INSERT (независимо от того, какой индекс на самом деле является дочерним; я тестировал это, добавляя больше дочерних элементов), а затем выполняет UPDATE для исправления индекса. Я предполагаю, что Hibernate просто использует любое значение, имеющееся в объекте Child, которое по умолчанию равно 0, а затем обновляет его после завершения INSERT, даже если это правильное значение.
@Mick В настоящий момент JPA создает столбец childIndex, хотя я не определил его явно для объекта Child. Меня беспокоит то, что JPA не устанавливает значение для этого столбца в начальном операторе INSERT для дочернего объекта, а вместо этого устанавливает его в отдельном операторе UPDATE. Явное добавление столбца childIndex к объекту Child приводит к тому, что значение устанавливается равным 0 при первоначальном INSERT (независимо от того, каким должен быть фактический индекс), а затем обновляется до правильного значения.





хорошо, похоже, Hibernate творит здесь немало магии, когда вы объединяете родительский объект. Похоже, что у дочерней сущности должен быть дополнительный атрибут - но этот факт обнаруживается ленивым - отсюда ваше двойное ОБНОВЛЕНИЕ. Как насчет того, чтобы вы также явно определили правильный атрибут childIndex для дочерней сущности? Эта аннотация @Column была бы правильным местом для аннотирования ваших требований, допускающих значение NULL. Также это должно заставить Hibernate сразу же вставить значение с первым оператором UPDATE.
Child-Entity по-прежнему требует определения childIndex, верно? JPA еще не знает об этой колонке, хотя использует ее для упорядочивания.