2011-12-01 57 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都是唯一的。