如果我尝试从Task
通过TaskList
方法删除removeTask
,我会有以下实体并获得例外。
@Entity
public class TaskList extends GenericModel {
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@OrderColumn(name="position", nullable=false)
public List<Task> tasks = new ArrayList<>();
// ...
public void removeTask(Task task) {
tasks.remove(task);
}
}
@Entity
public class Task extends Model {
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
@JoinColumn(name="task_id")
private List<Reservation> reservations = new ArrayList<>();
@ManyToOne
public TaskList taskList;
// ...
}
@Entity
public class Reservation extends GenericModel {
@Id
private String id = Token.generate(8);
@ManyToOne
private Task task;
// ...
}
例外是:
"CONSTRAINT_INDEX_F ON PUBLIC.TASKLIST_TASK(TASKS_ID)"
Unique index or primary key violation: "CONSTRAINT_INDEX_F ON PUBLIC.TASKLIST_TASK(TASKS_ID)"; SQL statement:
update TaskList_Task set tasks_id=? where TaskList_id=? and position=? [23001-149]
我正在使用JPA 2和Hibernate 3.6.1。我的映射有问题还是Hibernate错误?
更新
这似乎是一个Hibernate问题。具有delete
和update
语句顺序的内容。以下黑客解决了这个问题(部分):
@Entity
public class TaskList extends GenericModel {
// ....
public void removeTask(Task task) {
tasks.remove(task);
tasks = new ArrayList<>(tasks); // only for Hibernate
task.taskList = null;
}
}
但是 orphanRemoval=true
无法解决我的问题。它导致了下一个异常:“拥有实体实例不再引用具有cascade =”all-delete-orphan“的集合”。所以问题并没有真正解决。
答案 0 :(得分:1)
您的双向关联映射两次:一次在TaskList中,一次在Task中。 TaskList中的映射注释应为
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER, mappedBy="task")
@OrderColumn(name="position", nullable=false)
public List<Task> tasks = new ArrayList<>();
没有mappedBy属性,Hibernate认为你有两个独立的关联(我怀疑这是你想要的),而不是双向关联。
此外,修改双向关联时,应修改关联的两端。所以removeTask方法应该是
public void removeTask(Task task) {
tasks.remove(task);
task.setTaskList(null);
}
这一点尤其重要,因为该关联的拥有方是Task
(因为那里没有mappedBy
属性。所以这是Hibernate检查必须删除关联的一面。