Cách tạo và xử lý khóa chính tổng hợp trong JPA


108

Tôi muốn có các phiên bản từ cùng một mục nhập dữ liệu. Nói cách khác, tôi muốn sao chép mục nhập với một số phiên bản khác.

id - Version sẽ là khóa chính.

Thực thể phải trông như thế nào? Làm cách nào để nhân bản nó với một phiên bản khác?

id Version ColumnA

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

Khi sử dụng @IdClasschú thích, một mẹo khác mà tôi tìm thấy là @Columnchú thích nên đi vào các trường của lớp Thực thể ( YourEntitytrong mã mẫu của RohitJan).
KenSV

Câu trả lời:


231

Bạn có thể tạo một Embedded class, chứa hai khóa của bạn và sau đó có một tham chiếu đến lớp đó như EmbeddedIdtrong của bạn Entity.

Bạn sẽ cần @EmbeddedId@Embeddablechú thích.

@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 **/
}

Một cách khác để đạt được nhiệm vụ này là sử dụng @IdClasschú thích và đặt cả chú thích của bạn idvào đó IdClass. Bây giờ bạn có thể sử dụng @Idchú thích bình thường trên cả hai thuộc tính

@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
Là nó có thể sử dụng @Generatedvaluecho Id bởi EmbeddedId của
Kayser

1
@Kayser. Theo như tôi biết. Không. Bạn phải đặt rõ ràng giá trị cho chúng trong cá thể KeyClass của mình, rồi đặt cá thể lớp khóa đó trong Thực thể của bạn.
Rohit Jain

@Kayser. @GeneratedValuechỉ có thể được sử dụng để tạo giá trị khóa cho khóa chính, nó không thể tạo tổ hợp cho khóa tổng hợp.
Rohit Jain

1
@RohitJain chỉ một điều: bạn thực sự không thể đặt lớp nhúng ở chế độ công khai (cần phải nằm trong tệp riêng của nó để công khai)
Lucas

1
@FastEngy Nó vẫn có thể được truy cập thông qua Wayback Machine: web.archive.org/web/20170123035517/http://uaihebert.com/… . Có vẻ như bài viết này được thay thế bởi web.archive.org/web/20170202203555/http://uaihebert.com/…web.archive.org/web/20161014051056/http://uaihebert.com/… và cũng đã biến mất …
radlan

9

Lớp MyKey phải triển khai Serializablenếu bạn đang sử dụng@IdClass


5

Lớp chính:

@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;
}

Lớp thực thể:

@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;
    ...
}

Làm cách nào để nhân bản nó với một Phiên bản khác?

Bạn có thể tách thực thể được truy xuất từ ​​trình cung cấp, thay đổi khóa của Mục nhập và sau đó duy trì nó như một thực thể mới.


Tôi có thể xác định id trong Entrykey AUTOGENERATED. đặt hàng một cái gì đó tương tự @GeneratedValue(strategy = GenerationType.IDENTITY)
Kayser

1
Tôi cũng đang tự hỏi làm thế nào để tính toán băm cho 2 khóa chính dài. Về hashprimephương pháp hashCodetrên lớp EntryKey, bạn có thể cho mình biết ý tưởng đó xuất phát từ đâu không?
Bruce Sun

1

Lớp MyKey (@Embeddable) không được có bất kỳ mối quan hệ nào như @ManyToOne


Tại sao không? Bạn đã xem ví dụ này chưa?
Buhake Sindi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.