如何在JPA中创建和处理复合主键


108

我想要具有来自同一数据条目的版本。换句话说,我想用另一个版本号复制该条目。

id - Version 将是主键。

实体看起来如何?如何将其复制到另一个版本?

id Version ColumnA

1   0      Some data
1   1      Some Other data
2   0      Data 2. Entry
2   1      Data

使用@IdClass注解时,我发现的另一个技巧是@Column注解应进入Entity类的字段(YourEntity在RohitJan的示例代码中)。
KenSV '17

Answers:


231

您可以制作一个Embedded class,其中包含两个键,然后像EmbeddedId中一样引用该类Entity

您将需要@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;
}

4
是否可以将@GeneratedvalueEmbeddedId用作ID?
Kayser,2012年

1
@凯瑟 我所知道的。不能。您必须在KeyClass实例中显式设置它们的值,然后在Entity中设置该键类实例。
罗希特·贾因

@凯瑟 @GeneratedValue只能用于为主键生成键值,而不能为组合键生成组合键。
罗希特·贾因

1
@RohitJain只是一件事:您实际上无法公开嵌入式类(需要在其自己的文件中公开)
Lucas

1
@FastEngy仍然可以通过Wayback Machine进行访问:web.archive.org/web/20170123035517/http : //uaihebert.com/…。似乎本文已被web.archive.org/web/20170202203555/http://uaihebert.com/…web.archive.org/web/20161014051056/http://uaihebert.com/…取代,但该文章也消失了…
radlan


5

关键类别:

@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的键,然后将其持久保存为新实体。


可以在Entrykey中定义id AUTOGENERATED。像这样的事情 @GeneratedValue(strategy = GenerationType.IDENTITY)
凯塞尔(Kayser)2012年

1
我也想知道如何计算2个长主键的哈希值。至于hashprime在方法hashCode在课堂上EntryKey,你能告诉我这种想法从何而来?
Bruce Sun'Mar

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.