@OrderColumn в Hibernate / JPA приводит к избыточному SQL-запросу UPDATE

У меня простые двусторонние отношения родитель / потомок, где дети находятся в упорядоченном списке.

Родитель:

@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, даже если это правильное значение.

Child-Entity по-прежнему требует определения childIndex, верно? JPA еще не знает об этой колонке, хотя использует ее для упорядочивания.

Mick 11.12.2018 10:39

@Mick В настоящий момент JPA создает столбец childIndex, хотя я не определил его явно для объекта Child. Меня беспокоит то, что JPA не устанавливает значение для этого столбца в начальном операторе INSERT для дочернего объекта, а вместо этого устанавливает его в отдельном операторе UPDATE. Явное добавление столбца childIndex к объекту Child приводит к тому, что значение устанавливается равным 0 при первоначальном INSERT (независимо от того, каким должен быть фактический индекс), а затем обновляется до правильного значения.

Jacob Karshin 11.12.2018 15:13
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
2
693
1

Ответы 1

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

Другие вопросы по теме