2013-05-06 34 views
1

我有一個可以由自己的實體:一對多+ JoinTable + OrderColumn:順序書寫正確,但不讀

class Group { 
    // ... 
    @OneToMany(cascade = CascadeType.ALL, orphanRemoval = true) 
    @JoinTable(
     name = "group_group", 
     joinColumns = @JoinColumn(name = "id"), 
     inverseJoinColumns = @JoinColumn(name = "parentgroup_id") 
    ) 
    @OrderColumn 
    private List<Group> groups = new ArrayList<Group>(); 

    @ManyToOne 
    private Group parentGroup; 

    public List<Group> getGroups() { 
     return groups; 
    } 

    public Group getGroup() { 
     return parentGroup; 
    } 
} 

我可以創建一個組,並添加兩個子組:

Group parent = new Group(); 
Group child1 = new Group(); 
Group child2 = new Group(); 

parent.getGroups().add(child1); 
parent.getGroups().add(child2); 

parent = groupRepository.save(parent); 

// parent.getGroups().get(0).getId() == child1.getId() 
// parent.getGroups().get(1).getId() == child2.getId() 

但這似乎是巧合。我能夠更新訂單(例如使用Collections.sort),並且連接錶行也能正確更新。

無論我如何加載父組,子組始終按創建順序排列。執行的SQL查詢是:

SELECT t1.ID, t1.PARENTGROUP_ID FROM GROUP t0, GROUP t1 WHERE ((t1.PARENTGROUP_ID = ?) AND (t0.ID = t1.PARENTGROUP_ID)) 

沒有ORDER BY,這似乎是錯誤的。我如何說服EclipseLink添加它?

+0

您顯示的SQL語句不適用於使用OrderColumn爲OneToMany映射定義的「group_group」連接表。默認情況下是懶惰的,因此請嘗試訪問組關係並顯示生成的SQL。請注意,只有在從數據庫讀取集合時纔會對集合進行排序。一旦實體被緩存,您必須在應用程序中維護排序或強制刷新父實體以從數據庫重新加載集合。 – Chris 2013-05-06 13:30:12

+0

這是我日誌中唯一顯示的SQL語句。 – 2013-05-08 19:06:15

回答

1

問題是我試圖使用CrudRepository加載子組實體。存儲庫將忽略@OrderColumn註釋。我通過提取父組並使用getGroups()來修復它。

0

嘗試使用不依賴數據庫的@OrderBy。您需要提供Group的訂單(注意字段不是列)。

@OrderBy("fieldNameGoesHere DESC") 
private List<Group> groups = new ArrayList<Group>(); 

OrderColumn將保持在數據庫中的表,它帶有額外的性能和維護開銷的順序。 OrderBy將責任置於持久性提供者上以維護實體的順序,但是順序不會持久存在於持久性上下文中。

欲瞭解更多信息,結帳這blog post我創建了關於@OrderBy。