@UniqueConstraint và @Column (unique = true) trong chú thích ngủ đông


104

Sự khác biệt giữa @UniqueConstraint@Column (unique = true) là gì?

Ví dụ:

@Table(
   name = "product_serial_group_mask", 
   uniqueConstraints = {@UniqueConstraint(columnNames = {"mask", "group"})}
)

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private ProductSerialMask mask;

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private Group group;

2
Lưu ý: Với Hibernate 5.4, khi tôi thêm vào unique=true, chỉ mục không được thêm bởi trình cập nhật tự động lược đồ. @UniqueConstraintlàm cho nó xuất hiện. Có thể là một lỗi.
Ondra Žižka

Câu trả lời:


147

Như đã nói trước đây, @Column(unique = true)là một phím tắt UniqueConstraintkhi nó chỉ là một trường duy nhất.

Từ ví dụ bạn đưa ra, có sự khác biệt rất lớn giữa cả hai.

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private ProductSerialMask mask;

@Column(unique = true)
@ManyToOne(optional = false, fetch = FetchType.EAGER)
private Group group;

Mã này ngụ ý rằng cả hai maskgroupphải là duy nhất, nhưng riêng biệt. Điều đó có nghĩa là nếu bạn có một bản ghi với mask.id = 1 và cố gắng chèn một bản ghi khác có mask.id = 1 , thì bạn sẽ gặp lỗi vì cột đó phải có các giá trị duy nhất. Ứng dụng tương tự cho nhóm.

Mặt khác,

@Table(
   name = "product_serial_group_mask", 
   uniqueConstraints = {@UniqueConstraint(columnNames = {"mask", "group"})}
)

Ngụ ý rằng các giá trị của mặt nạ + nhóm được kết hợp phải là duy nhất. Điều đó có nghĩa là bạn có thể có, ví dụ, một bản ghi với mask.id = 1group.id = 1 , và nếu bạn cố gắng chèn một bản ghi khác với mask.id = 1group.id = 2 , nó sẽ được chèn thành công, trong khi trong trường hợp đầu tiên thì không.

Nếu bạn muốn có cả mặt nạ và nhóm là duy nhất riêng biệt và ở cấp lớp, bạn phải viết mã như sau:

@Table(
        name = "product_serial_group_mask",
        uniqueConstraints = {
                @UniqueConstraint(columnNames = "mask"),
                @UniqueConstraint(columnNames = "group")
        }
)

Điều này có tác dụng tương tự như khối mã đầu tiên.


Khi ràng buộc duy nhất được tạo, tôi có thể tham chiếu đến ràng buộc theo tên trong Kho lưu trữ JPA của mình để truy vấn về điều đó không?
jDub9

@ jDub9 Bạn không thể truy vấn chỉ mục. Bạn có thể truy vấn mặt nạ và nhóm cột, trong một truy vấn và nó sẽ sử dụng chỉ mục đó để xử lý nhanh hơn (nếu bạn may mắn), nhưng bạn không thể chỉ truy vấn một chỉ mục.
Dalibor Filus

Hãy cẩn thận mặc dù tên columnName phải là tên thực trong cơ sở dữ liệu. Nó nên được mask_idgroup_idnếu bạn sử dụng chiến lược đặt tên mặc định.
vitro

27

Từ tài liệu Java EE:

public abstract boolean unique

(Tùy chọn) Thuộc tính có phải là khóa duy nhất hay không. Đây là một phím tắt cho chú thích UniqueConstraint ở cấp bảng và hữu ích khi ràng buộc khóa duy nhất chỉ là một trường duy nhất. Ràng buộc này áp dụng bổ sung cho bất kỳ ràng buộc nào có trong ánh xạ khóa chính và các ràng buộc được chỉ định ở cấp bảng.

Xem doc


vì vậy khi tôi sử dụng mã này: @Column (unique = true) @ManyToOne (option = false, fetch = FetchType.EAGER) private ProductSerialMask mask; @Column (unique = true) @ManyToOne (option = false, fetch = FetchType.EAGER) private Group group; Tôi có hai chỉ mục nhưng khi sử dụng theo cách khác, tôi có một chỉ mục rằng nó là kết hợp của hai cột?
navid_gh

22

Ngoài câu trả lời của Boaz….

@UniqueConstraintcho phép bạn đặt tên cho ràng buộc , trong khi @Column(unique = true)tạo một tên ngẫu nhiên (ví dụ UK_3u5h7y36qqa13y3mauc5xxayq).

Đôi khi có thể hữu ích nếu biết bảng ràng buộc nào được liên kết với. Ví dụ:

@Table(
   name = "product_serial_group_mask", 
   uniqueConstraints = {
      @UniqueConstraint(
          columnNames = {"mask", "group"},
          name="uk_product_serial_group_mask"
      )
   }
)

5

Ngoài câu trả lời của @ Boaz và @ vegemite4me ....

Bằng cách triển khai, ImplicitNamingStrategybạn có thể tạo các quy tắc để tự động đặt tên cho các ràng buộc. Lưu ý rằng bạn thêm chiến lược đặt tên của mình vào metadataBuildertrong quá trình khởi tạo Hibernate:

metadataBuilder.applyImplicitNamingStrategy(new MyImplicitNamingStrategy());

Nó hoạt động cho @UniqueConstraint, nhưng không hoạt động @Column(unique = true), luôn tạo ra một tên ngẫu nhiên (ví dụ: UK_3u5h7y36qqa13y3mauc5xxayq).

Có một báo cáo lỗi để giải quyết vấn đề này, vì vậy nếu bạn có thể, vui lòng bỏ phiếu ở đó để việc này được triển khai. Tại đây: https://hibernate.atlassian.net/browse/HHH-11586

Cảm ơn.

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.