2012-01-07 65 views
1

如果我嘗試通過removeTask方法嘗試從TaskList中刪除Task,我有以下實體並得到一個異常。使用訂購的休眠列表的唯一約束違規

@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錯誤?

UPDATE

這似乎是一個休眠問題。聲明的順序爲deleteupdate。下面的技巧解決了這個問題(部分):

@Entity 
public class TaskList extends GenericModel { 

    // .... 

    public void removeTask(Task task) { 
    tasks.remove(task); 
    tasks = new ArrayList<>(tasks); // only for Hibernate 
    task.taskList = null; 
    } 
} 

Hibernate - clearing a collection with all-delete-orphan and then adding to it causes ConstraintViolationException導致我在正確的方向。

但是orphanRemoval=true不適用於我的解決方法。它會導致下一個異常:「具有級聯的集合=」all-delete-orphan「不再由擁有的實體實例引用。所以這個問題並沒有真正解決。

+0

很好,黑客爲我工作!我的場景如下:我從列表中刪除了第一個元素,然後將該元素添加到列表的末尾。 – rwitzel 2014-01-23 19:59:25

回答

1

您的雙向關聯被映射兩次:一次在TaskList中,一次在Task中。在任務列表映射註釋應該是

@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檢查知道該關聯必須被刪除的一面。

+0

'mappedBy'不能與'@ OrderColumn'一起使用,因爲Hibernate認爲這是一種糟糕的做法,需要一個連接表來代替。請參閱:http://stackoverflow.com/questions/2956171/我試圖刪除引用建議,但它沒有解決問題。 – deamon 2012-01-08 17:04:25