如何在 JPA 中创建和处理复合主键
Posted
技术标签:
【中文标题】如何在 JPA 中创建和处理复合主键【英文标题】:How to create and handle composite primary key in JPA 【发布时间】:2012-10-13 12:47:23 【问题描述】:我想拥有来自同一数据条目的版本。换句话说,我想用另一个版本号复制条目。
id - Version
将是主键。
实体应该是什么样子?如何将其复制到另一个版本?
id Version ColumnA
1 0 Some data
1 1 Some Other data
2 0 Data 2. Entry
2 1 Data
【问题讨论】:
当使用@IdClass
注释时,我发现的另一个提示是@Column
注释应该进入实体类的字段(YourEntity
在 RohitJan 的示例代码中)。
【参考方案1】:
MyKey 类 (@Embeddable) 不应有类似 @ManyToOne 的任何关系
【讨论】:
为什么不呢?你看过这个example吗?【参考方案2】:您可以创建一个 Embedded class
,其中包含您的两个密钥,然后在您的 Entity
中将该类作为 EmbeddedId
的引用。
您需要@EmbeddedId
和@Embeddable
注释。
@Entity
public class YourEntity
@EmbeddedId
private MyKey myKey;
@Column(name = "ColumnA")
private String columnA;
/** Your getters and setters **/
@Embeddable
public class MyKey implements Serializable
@Column(name = "Id", nullable = false)
private int id;
@Column(name = "Version", nullable = false)
private int version;
/** getters and setters **/
实现此任务的另一种方法是使用@IdClass
注释,并将您的id
放在那个IdClass
中。现在您可以在两个属性上使用普通的@Id
注释
@Entity
@IdClass(MyKey.class)
public class YourEntity
@Id
private int id;
@Id
private int version;
public class MyKey implements Serializable
private int id;
private int version;
【讨论】:
EmbeddedId 是否可以使用@Generatedvalue
作为Id
@Kayser。据我所知。不,您必须在 KeyClass 实例中显式设置它们的值,然后在您的实体中设置该键类实例。
@Kayser。 @GeneratedValue
只能用于生成主键的键值,不能生成复合键的组合。
@Kayser。请参阅 JPA 2.0 规范的 Section - 11.1.17 GeneratedValue Annotation
。它清楚地表明,@GeneratedValue
只能与简单的主键一起使用。
@RohitJain 只有一件事:您实际上不能将嵌入式类公开(需要在其自己的文件中才能公开)【参考方案3】:
关键类:
@Embeddable
@Access (AccessType.FIELD)
public class EntryKey implements Serializable
public EntryKey()
public EntryKey(final Long id, final Long version)
this.id = id;
this.version = version;
public Long getId()
return this.id;
public void setId(Long id)
this.id = id;
public Long getVersion()
return this.version;
public void setVersion(Long version)
this.version = version;
public boolean equals(Object other)
if (this == other)
return true;
if (!(other instanceof EntryKey))
return false;
EntryKey castOther = (EntryKey) other;
return id.equals(castOther.id) && version.equals(castOther.version);
public int hashCode()
final int prime = 31;
int hash = 17;
hash = hash * prime + this.id.hashCode();
hash = hash * prime + this.version.hashCode();
return hash;
@Column (name = "ID")
private Long id;
@Column (name = "VERSION")
private Long operatorId;
实体类:
@Entity
@Table (name = "YOUR_TABLE_NAME")
public class Entry implements Serializable
@EmbeddedId
public EntryKey getKey()
return this.key;
public void setKey(EntryKey id)
this.id = id;
...
private EntryKey key;
...
如何将其复制到另一个版本?
您可以分离从提供者检索到的实体,更改 Entry 的键,然后将其作为新实体持久化。
【讨论】:
是否可以在EntrykeyAUTOGENERATED
中定义id。或者类似的东西@GeneratedValue(strategy = GenerationType.IDENTITY)
我也想知道如何计算 2 个长主键的哈希值。至于EntryKey
类中hashCode
方法中的hash
和prime
,你能告诉我这个想法是从哪里来的吗?【参考方案4】:
如果你使用@IdClass
,MyKey 类必须实现Serializable
【讨论】:
以上是关于如何在 JPA 中创建和处理复合主键的主要内容,如果未能解决你的问题,请参考以下文章