【问题标题】:Database Model Table for each Relationship?每个关系的数据库模型表?
【发布时间】:2012-10-18 00:17:12
【问题描述】:

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

我有一个表“comment”和三个表“user”、“car”、“house”。每个用户都可以评论用户、汽车和房屋。

通常这会导致所有 fk 都保存在表“注释”中的关系,例如 car_id、house_id、user_id。但是这些关系是排他性的,所以不可能有属于汽车和房子的评论。

现在将所有 fks 都放在评论表中是否明智?因此,如果我们想扩展(例如图片上的 cmets),可能会导致很多可为空的 fks。

或者为每个关系(如“UserComment”、“CarComment”和“HouseComment”)创建一个新表是一个不错的选择。

我希望这不是重复的,但我发现很难搜索这个问题。

谢谢!

【问题讨论】:

    标签: hibernate database-design jpa


    【解决方案1】:

    在 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...
    

    【讨论】:

      【解决方案2】:

      为了避免数据库中的冗余和不必要的空值,我建议使用继承,如果在您使用的数据库中可能的话。然后,您创建名为“commented_objects”或类似名称的父表和 3 个从父表继承的具有相同递增序列的表。 在这种情况下,您只需要一个在父表和 cmets 表之间的引用表。

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

      所以代码看起来像(对于 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
      );
      

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-10
        • 2021-06-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多