Hibernate orphanRemoval удаляет мою родительскую сущность - PullRequest
2 голосов
/ 07 февраля 2020

У меня есть древовидная структура , которую я называю графом и использующий список смежности . Класс Graph имеет

@OneToMany(mappedBy = "graphEntry", cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@OptimisticLock(excluded = true)
public List<GraphNode> getStartNodes() {
    return startNodes;
}

public void addStartNode(GraphNode graphNode){
    startNodes.add(graphNode);
    graphNode.setGraphEntry(this);
}

public void removeStartNode(GraphNode graphNode){
    startNodes.remove(graphNode);
    graphNode.setGraphEntry(null);
}

и GraphNode имеет:

@ManyToOne
@JoinColumn(name = "graphEntry")
public Graph getGraphEntry() {
    return graphEntry;
}

@ManyToOne(fetch = FetchType.LAZY, targetEntity = GraphNode.class)
@JoinColumn(name = "parent")
@OptimisticLock(excluded = true)
public GraphNode getParentNode() {
    return parentNode;
}

@OneToMany(mappedBy = "parentNode", cascade = CascadeType.ALL, orphanRemoval = true) 
@OptimisticLock(excluded = true)
public List<GraphNode> getChildNodes() {
    return childNodes;
}

Когда я заменяю startNode другим узлом, я получаю

PersistentObjectException: detached entity passed to persist: ...GraphNode

Когда я меняю порядок 2 узлов, мои данные правильно сохраняются в БД.

Я пытался изменить тип каскада на PERSIST и MERGE вместо ВСЕ, но это не помогло. Похоже, что hibernate удаляет Graph, когда старый startNode больше не указывает на него.

Как я могу убедиться, что мой график не удаляется и замена узла работает?

enter image description here

1 Ответ

1 голос
/ 07 февраля 2020

Это правильное поведение, если для orphanRemoval установлено значение true; он говорит, если ребенок осиротел. его также следует удалить из базы данных.

Давайте разберемся с этим на примере. Допустим, у вас есть Employee сущность, а Employee может иметь несколько учетных записей.

@Entity
@Table(name = "Employee")
public class Employee
{
    @Id
    private Integer employeeId;

    @OneToMany(orphanRemoval = true, mappedBy = "employee")
    private Set<Account> accounts;
}

По сути это означает, что всякий раз, когда мы удаляем «учетная запись из набора учетных записей» (что означает, что я удаляю отношения между этой учетной записью и Сотрудником); объект учетной записи, который не связан с каким-либо другим сотрудником в базе данных (т. е. сиротой), также должен быть удален.

...