2012-08-17 283 views
2

我想通過JPA存儲樹結構。該模型由兩個實體類組成:TreeVertex。類Vertex基本上只包含頂點'名稱,類Tree映射名爲parents,它存儲每個子頂點(child -> parent)的父頂點。如何通過JPA存儲樹結構?

此結構使我能夠簡單快速地訪問給定子頂點是否具有父頂點以及實際父級(如果有)的信息。

我用下面的註釋,以指定JPA(EclipseLink的在我的情況)應該如何存儲的關係:

@MapKeyClass(Vertex.class) 
@MapKeyJoinColumn(name = "child_id", nullable = false) 
@OneToMany(targetEntity = Vertex.class, cascade = CascadeType.ALL) 
@JoinTable(name = "bug_492_tree_parents", inverseJoinColumns = { @JoinColumn(name = "parent_id") }) 
private final Map<Vertex, Vertex> parents = Maps.newHashMap(); 

不幸的是,使用上述映射,我不能存儲在具有相同父兩個子頂點像V = {parent, child1, child2}E = {{child1, parent}, {child2, parent}}(因此,child1 -> parentchild2 -> parent),因爲我得到的完整性約束違規:

Internal Exception: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException: Duplicate entry '3-4' for key 'PRIMARY' 
Error Code: 1062 
Call: INSERT INTO bug_492_tree_parents (parent_id, tree_id, child_id) VALUES (?, ?, ?) 

這是通過JPA/EclipseLink的如何specifie引起S IN連接表中的主鍵:

Incorrect primary key definition

不幸的是,的EclipseLink的動產複合鍵(tree_id,parent_id)作爲主鍵。使用這個主鍵,不可能像上面的簡單例子那樣存儲包含兩個具有相同父頂點的不同頂點的樹。

只有在主鍵(在MySQL數據庫架構)手動固定(tree_id,child_id)我能夠存儲樹:

Fixed primary key

我嘗試了許多不同的映射;但是,我總是遇到一些(其他)問題。

最後,我的問題:我該如何或可以通過JPA存儲簡單的樹結構?我必須選擇不同的映射嗎?我必須改變我的模型嗎?

回答

0

我不認爲JPA可以做你想做的事情。

中說稱爲E JPA的實體希望把地圖時要使用V的某些屬性作爲K爲地圖,並建立不K和V.

E之間和V之間的關係一對多最簡單的解決方案是忘記您的地圖,並在您的班級中放置List<Vertex>,其中只包含頂級節點也會在您的頂點類中爲頂點之間的父級父子關係放置一個List<Vertex>

如果你想要更多像你現在有一個結構,我認爲你將不得不引入額外的實體,如:

@Entity 
VertexRelation { 
    private Vertex parent; 
    private Vertex child; 
    ... 
} 

那麼你的地圖可能會成爲一個Map<Vertex, VertexRelation>,你可以使用@MapKey(name="parent")告訴JPA你想使用父母作爲地圖的關鍵。

注:使用額外的實體只是一個想法,我從來沒有嘗試過自己。我一直使用類似於我對樹木的第一個建議。