2011-12-01 63 views
7

我有一個方案的「最佳實踐」問題。休眠映射:從一列到多個表

場景: DB中的多個實體,例如Document,BlogPost,Wiki可以由個人共享。不是爲每個實體創建一個分享表,而是創建一個共享表。問題是,如何將分享表映射到不同的實體?

我有三個選項,請告訴哪個選項最好,如果有更好的選項。

選項1: 創建表股份:

SHARES 
id (unique) 
entityId (non DB enforced FK to DOCUMENTS, WIKIS, POSTS etc.) 
entityType 
sharedBy 
sharedWith 
sharedDate 

這裏,ENTITYID將是一個FK到documentId,wikiId,等帖子ID等,並會的EntityType身份是什麼類型的ENTITYID是。

這具有在休眠建模問題,創造共享時到實體映射,如share.getDocument()或share.getWiki()等等

選項2: 創建表股份其中僅持有共享信息,然後創建將分享與實體關聯的解決表。

SHARES 
id(PK) 
sharedBy 
sharedWith 
sharedDate 
shareType (helper field for searches) 

SHARES_DOCUMENTS 
share_id (unique ID and FK, one to one with SHARES) 
document_id (FK to DOCUMENTS) 

SHARES_POST 
share_id (unique ID and FK, one to one with SHARES) 
post_id (FK to POSTS) 

more share tables here. 

所以,休眠明智的,分享可以有一對一的對每個共享類型(如share.getDocument(),share.getPost(),並且將shareType識別哪個關係是「活性」)

選項3 選項1類似,但創建單獨的列,而不是實體ID

SHARES 
id (unique ID) 
documentId (FK to DOCUMENTS, nullable) 
postId (FK to POSTS, nullable) 
wikiId (FK to WIKIS, nullable) 
sharedBy 
sharedWith 
sharedDate 
sharedType 

在這裏,每列可以映射到相應的實體,但它們是空。 sharedType可以識別哪個關係是「活動的」。因此,問題是,哪種做法最好,既有數據庫智能化,也有hibernate映射(最終查詢,性能明智)。

由於 M.相反

+1

看一看http://docs.jboss.org/hibernate/core/3.3/reference/en/html/inheritance.html –

+0

謝謝,將會看看這個。但這真的是遺產問題嗎?或者可以使用繼承來解決它。如果每個解析表都有附加的派生信息,那麼它們可以有資格獲得繼承,但它們只包含與不同實體的關係。此外,大多數繼承示例/文檔不會嘗試將單個列鏈接到不同的實體。他們確實有獨立的領域,進一步定義他們。 –

+0

第二個想法是,與不同實體的關係確實「進一步定義它們」。我將研究多個具有單表選項的類,並查看它是如何工作的。 –

回答

4

正如TheStijn建議,尋找到不同的方法來設置繼承關係後,我去的方法「每類層次結構單一表」,並結束了與如表:

SHARES 
--------- 
id PK 
shared_by FK to User 
shared_with FK to User 
shared_Date 
document_id nullable FK to Document 
post_id nullable FK to Posts 
... more ids here to link to more entities 
type_discriminator (values, DOCUMENT, POST ...) 

在休眠/ Java的側, 一股抽象類的...

@Entity 
@Table(name="SHARES") 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="TYPE_DISCRIMINATOR", discriminatorType=DiscriminatorType.STRING) 
public abstract class Share { 
    @Id 
    @Column(name="ID", nullable=false) 
    @GeneratedValue(generator="system-uuid") 
    @GenericGenerator(name="system-uuid", strategy = "uuid") 
    private String id; 

    @ManyToOne 
    @JoinColumn(name="SHARED_BY", nullable=false) 
    private User sharedBy; 

    @ManyToOne 
    @JoinColumn(name="SHARED_WITH", nullable=false) 
    private User sharedWith; 

    @Column(name="SHARED_DATE", columnDefinition="TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP", nullable=false) 
    @Temporal(TemporalType.TIMESTAMP) 
    private Date sharedDate;   
    ... 

} 

和兩個正常上課..

@Entity 
@DiscriminatorValue("DOCUMENT") 
public class SharedDocument extends Share { 
    @ManyToOne 
    @JoinColumn(name="DOCUMENT_ID", nullable=true) 
    private Document document; 
    .... 

} 

@Entity 
@DiscriminatorValue("POST") 
public class SharedPost extends Share { 
    @ManyToOne 
    @JoinColumn(name="POST_ID", nullable=true) 
    private Post post; 
    .... 

} 

至於使用情況,使用具體類只:

@Test 
public void saveNewDocumentShare(){ 
    SharedDocument sharedDocument = new SharedDocument(); 
    sharedDocument.setDocument(document1); 
    sharedDocument.setSharedBy(teacher1); 
    sharedDocument.setSharedWith(teacher2); 
    sharedDocument.setSharedDate(new Date()); 

    sharedDocument.setCreatedBy("1"); 
    sharedDocument.setCreatedDate(new Date()); 
    sharedDocument.setModifiedBy("1"); 
    sharedDocument.setModifiedDate(new Date()); 


    SharedDocument savedSharedDocument = dao.saveSharedDocument(sharedDocument); 

    assertNotNull(savedSharedDocument); 
    assertThat(savedSharedDocument.getId(),notNullValue()); 
} 

@Test 
public void saveNewPostShare(){ 
    SharedPost sharedWikiPage = new SharedWikiPage(); 
    sharedPost.setPost(post1); 
    sharedPost.setSharedBy(teacher1); 
    sharedPost.setSharedWith(teacher2); 
    sharedPost.setSharedDate(new Date()); 

    sharedPost.setCreatedBy("1"); 
    sharedPost.setCreatedDate(new Date()); 
    sharedPost.setModifiedBy("1"); 
    sharedPost.setModifiedDate(new Date()); 


    SharedPost savedSharedPost = dao.saveSharedPost(sharedPost); 

    assertNotNull(savedSharedPost); 
    assertThat(savedSharedPost.getId(),notNullValue()); 

} 
0

這顯然是一個多到多的關係。

映射這些類型的東西的默認場景是使用單獨的表來獲取連接信息。 喜歡的東西:

table shared_connections { 
    number owner_id 
    ,number shared_id 
} 

所有對象是可共享應該擴展一些基本的類ex:AbstractSharedObject。 (使用@MappedSuperclass註解並關心@Inheritance策略)。

和個人類中:

private Collection<AbstractSharedObject> shares; 

地圖這個集合作爲ManyToMany關係。

P.S.爲此,您需要保證所有可共享對象的ID都是唯一的。