两个外键作为主键
Posted
技术标签:
【中文标题】两个外键作为主键【英文标题】: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
,并且我使这些字段独一无二且不为空。这种方式简单得多。
【参考方案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 个数据表:Song 和 Tag,每个都有一个 id(songid、tagid)。 然后我有一个表用于将它们连接在一起 Tagassignment,它只有 Song 和 Tag 的主键。所以我不想加入他们,我想保留两个外键的表。
我的解决方案来源: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;
【讨论】:
以上是关于两个外键作为主键的主要内容,如果未能解决你的问题,请参考以下文章