Почему hibernate / jpa устанавливает для поля @OrderColumn значение null для удаленного элемента в отображенном списке перед его удалением? - PullRequest
3 голосов
/ 01 декабря 2010

Я хотел бы отобразить древовидную структуру "глав". Каждая глава имеет ссылку на своего родителя и упорядоченный список (по «позиции») подразделов. В JPA 2.0, Hibernate 3.5 сущность «Глава» выглядит следующим образом:

@Entity
public class Chapter {

    @Id
    @GeneratedValue
    private long id;

    @Column(name="position", nullable=false)
    private int position;

    @ManyToOne
    @JoinColumn(name="parentChapter_id", updatable=false, insertable=false)
    private Chapter parentChapter;

    @OneToMany(cascade=CascadeType.ALL, orphanRemoval=true)
    @OrderColumn(name="position")
    @JoinColumn(name="parentChapter_id")
    private List<Chapter> subChapters = new ArrayList<Chapter>();

    public List<Chapter> getSubChapters() {
            return subChapters;
    }
}

Проблема в том, что если один из элементов subChapters удален

// EntityManager em
Chapter parent = em.find(Chapter.class, 1);
subChapters = parent.getSubChapters();
subChapters.remove(1);
EntityTransaction tx = em.getTransaction();
tx.begin();
em.persist(parent);
tx.commit();

затем Hibernate пытается выполнить этот оператор

update
    Chapter 
set
    parentChapter_id=null,
    position=null 
where
    parentChapter_id=? 
    and id=?

, что не удается из-за ограничения NOT NULL position. Если @OrderColumn(name="position") удален, Hibernate не обновляет position (и, следовательно, он работает), а затем удаляет (sub) Chapter. Что заставляет Hibernate сначала обновить будущую сироту и , а затем удалить ее?

1 Ответ

2 голосов
/ 01 декабря 2010

Проблема носит концептуальный характер, особенно в отношении свойства position :-) Это свойство самого списка, а не элемента списка (глава).Итак, я бы сделал это по-другому:

@Entity 
public class Chapter {
  @Id @GeneratedValue
  private long id;

  @ManyToOne
  private Chapter parent;

  @OneToMany(mappedBy="parent")
  @OrderColumn(name="position")
  private List<Chapter> children;
}

Обратите внимание, что у вас есть две структуры здесь: глава и список.Дело в том, что состояние списка также должно быть постоянным, но оно не связано со структурой Chapter.Таким образом, он заслуживает таблицы для себя (и именно это Hibernate попытается сделать, если вы включите «generate ddl»).

Вы можете увидеть этот пример из их набора тестов: https://github.com/hibernate/hibernate-core/tree/master/hibernate-core/src/test/java/org/hibernate/test/collection/list/

Вы увидите, что они не используют аннотации, но вы можете легко перевести это :-)

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