【问题标题】:Two foreign keys as primary key两个外键作为主键
【发布时间】:2015-09-22 09:20:02
【问题描述】:

如何使用 hibernate 注释实现以下表格?

当前代码是:(为简洁起见)

用户

@Entity
@Table(name = "user")
public class User implements java.io.Serializable {
    @Id
    @GeneratedValue
    public Long getId() {
        return id;
    }
}

社交网络

@Entity
@Table(name = "social_network")
public class SocialNetwork implements java.io.Serializable {
    @Id
    @GeneratedValue
    public int getId() {
        return id;
    }
}

社交档案

@Entity
@Table(name = "social_profile")
public class SocialProfile implements java.io.Serializable {
    @Id
    @ManyToOne
    @JoinColumn(name="user_id")
    public User getUser() {
        return user;
    }

    @Id
    @ManyToOne
    @JoinColumn(name="social_network_id")
    public SocialNetwork getSocialNetwork() {
        return socialNetwork;
    }
}

显然我的代码现在不能正常工作。任何人都可以对此有所了解吗?

【问题讨论】:

  • 您也可以考虑为您的 social_profile 添加一个简单的 ID 列,并在两个 FK 上一起添加一个唯一约束。它几乎相同,但更容易处理,恕我直言
  • @stg 感谢您的提示,我在 social_profile 表中添加了一个 id,并且我使这些字段独一无二且不为空。这种方式简单得多。

标签: hibernate jpa spring-data spring-data-jpa


【解决方案1】:

您需要一个像这样的可嵌入 SocialProfileId:

@Embeddable
public class SocialProfileId implements Serializable {
    @Column(name = "user_id")
    private long userId;
    @Column(name = "social_network_id")
    private long socialNetworkId;
}

然后,您的 SocialProfile 实体将如下所示:

@Entity
@Table(name = "social_profile")
public class SocialProfile implements java.io.Serializable {

    @EmbeddedId
    private SocialProfileId id;

    @ManyToOne
    @JoinColumn(name="user_id")
    public User getUser() {
        return user;
    }

    @ManyToOne
    @JoinColumn(name="social_network_id")
    public SocialNetwork getSocialNetwork() {
        return socialNetwork;
    }
}

编辑抱歉,我在回答中的字段和方法上混杂了注释......永远不要那样做! ;-)

【讨论】:

  • 感谢您的信息。我会接受这一点,但我决定使用上面 cmets 中建议的 stg 之类的代理键,这会使事情变得更简单。
  • 是的,有一个简单的 id 更简单......我刚刚在这里回答了你的问题 ;-)
【解决方案2】:

您似乎需要具有带有额外列的连接表的mamy-to-many 映射。 为此,您需要再创建 2 个类。

仅供参考:http://www.mkyong.com/hibernate/hibernate-many-to-many-example-join-table-extra-column-annotation/

【讨论】:

    【解决方案3】:

    我在 REST 应用程序中遇到的问题与此类似,但略有不同,我将在此处发布。 我有 2 个数据表:SongTag,每个都有一个 id(songid、tagid)。 然后我有一个表用于将它们连接在一起 Tagassignment,它只有 SongTag 的主键。所以我不想加入他们,我想保留两个外键的表。

    我的解决方案来源:http://www.objectdb.com/java/jpa/entity/id


    之前

    歌曲

    @Entity
    @Table(name = "songs")
    data class Song(
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        val id: Int,
    
        ...
    )
    

    标签

    @Entity
    @Table(name = "tags")
    data class Tag(
    
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        val id: Int,
    
        ...
    )
    

    标签分配

     @Entity
     @Table(name = "tagassignment")
     data class Tagassignment(
    
         val songid: Int,
    
         val tagid: Int
    
     )
    

    之后

    我没有更改歌曲标签

    标签分配

    @Entity
    @IdClass(value = TagassignmentKey::class)
    @Table(name = "tagassignment")
    data class Tagassignment(
    
        @Id
        val songid: Int,
    
        @Id
        val tagid: Int
    
    )
    

    我创建了一个 Key 类

    标签分配键

    class TagassignmentKey(val songid: Int, val tagid: Int) : Serializable {
    
        constructor() : this(0, 0)
    
    }
    

    【讨论】:

      【解决方案4】:

      除了 Pras 所说的之外,我们甚至可以将 @ManyToOne 移动到 @Embeddable 类本身中,这样 SocialProfileId 就会看起来像这样,您可以在 Embedded 类本身中清楚地看到它引用了另一个表

      @Embeddable
      public class SocialProfileId implements Serializable {
      
          @ManyToOne
          @JoinColumn(name = "user_id")
          private User userId;
      
      
          @ManyToOne
          @JoinColumn(name = "social_network_id")
          private SocialNetwork socialNetworkId;
      
          public SocialProfileId(User userId, SocialNetwork socialNetworkId) {
              this.userId = userId;
              this.socialNetworkId = socialNetworkId;
          }
      
      }
      

      您的 SocialProfile 实体可以简单地具有嵌入式类和其他字段,如电子邮件等..

      @Entity
      @Table(name = "social_profile")
      public class SocialProfile implements java.io.Serializable {
      
          @EmbeddedId
          private SocialProfileId id;
      
          @Column(name="email")
          private String email;
      }
      

      【讨论】:

        猜你喜欢
        • 2012-06-29
        • 2013-03-06
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-09-17
        • 1970-01-01
        相关资源
        最近更新 更多