每个关系的数据库模型表?

时间:2012-10-16 07:16:29

标签: hibernate database-design jpa

我有一个在我的数据库中建模关系的问题。

我有一个表“评论”和三个表“用户”,“汽车”,“房子”。每个用户都可以评论用户,汽车和房屋。

通常这会产生一种关系,即所有fks都保存在表“注释”中,如car_id,house_id,user_id。但这些关系是独一无二的,所以不可能有一个属于汽车和房子的评论。

现在在评论表中包含所有fks是明智的吗?因此,如果我们想要扩展(例如对图片的评论),可能会导致很多可以为空的fks。

或者为每个关系设置一个新表是一个不错的选择,如“UserComment”,“CarComment”和“HouseComment”。

我希望这不是重复,但我发现很难找到这个问题。

谢谢!

2 个答案:

答案 0 :(得分:0)

为了避免冗余并且db中没有必要的空值,我建议使用继承,如果你可以在db中使用它。然后创建名为'commented_objects'的父表或类似的表,以及从父表继承的具有相同递增顺序的3个表。 在这种情况下,父表和注释表之间只需要一个引用表。

如果您的数据库不允许使用组合和公共序列,则可以模拟继承。

所以代码看起来像(对于PostgreSQL):

CREATE TABLE commented_objects(
    id int,
    comment text
);


CREATE TABLE cars(
    some_fields text
) INHERITS (commented_objects);


CREATE TABLE houses(
    some_fields text
) INHERITS (commented_objects);

CREATE TABLE users(
    some_fields text
) INHERITS (commented_objects);

CREATE TABLE ref_table(
    id int,
    comment_id
);

如果您想通过添加新的继承表,可以轻松扩展结构。

答案 1 :(得分:0)

在Roman的回答中,它不一定是表名。真的有一个鉴别家的想法。

所以就表而言,这看起来像是:

create table house ( id .., ..., primary key (id) )
create table user ( id .., ..., primary key (id) )
create table car ( id .., ..., primary key (id) )
create table comment( id ..., commenter ..., commented_id ..., commented_type ... )

有几种方法可以将歧视应用于这种关系。

首先,您可以将Comment本身作为层次结构并使用基于鉴别器的子类。这种方法的缺点是子类完全没用,只满足持久性的需要。这种方法的优点是它可以与任何JPA提供商一起使用。要使用这种方法,您需要:

@Entity
@Table( name="comment" )
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name="commented_type")
public abstract class Comment {
    @Id
    @Column( name="id" )
    private Long id;
    ...
}

@Entity
public class HouseComment extends Comment {
    @ManyToOne
    @JoinColumn(name="commented_id")
    private House getHouse();
    ...
}

etc...
像我说的那样,有点难过。

Hibernate,特别为您提供了其他选项来处理这个问题。例如,使用其“任意”映射的概念:

@Entity
@Table( name="comment" )
public class Comment {
    @Id
    @Column( name="id" )
    private Long id;

    @Any( metaColumn = @Column( name="commented_type" ) )
    @AnyMetDef(
        idType = "long"
        metaValues = {
            @MetaValue( value="C", targetEntity=Carclass ),
            @MetaValue( value="H", targetEntity=House.class ),
            @MetaValue( value="U", targetEntity=User.class )
        }
    )
    pubic Commentable getCommentTarget { ... }
}

public interface Commentable {
    ...
}

@Entity
public House implements Commentable {
   ...
}

etc...