PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

ngủ đông không thể nhận giá trị trình tự tiếp theo

Phương ngữ PostgreSQL của Hibernate không sáng sủa lắm. Nó không biết về trình tự mỗi SERIAL của bạn và đang giả định rằng có một chuỗi toàn cơ sở dữ liệu toàn cầu được gọi là "hibernate_sequence" mà nó có thể sử dụng.

( CẬP NHẬT :Có vẻ như các phiên bản Hibernate mới hơn có thể sử dụng trình tự mặc định cho mỗi bảng khi GenerationType.IDENTITY được quy định. Kiểm tra phiên bản của bạn và sử dụng phiên bản này thay vì phiên bản bên dưới nếu nó phù hợp với bạn.)

Bạn cần thay đổi ánh xạ của mình để chỉ định rõ ràng từng trình tự. Nó khó chịu, lặp đi lặp lại và vô nghĩa.

@Entity
@Table(name = "JUDGEMENTS")
public class Judgement implements Serializable, Cloneable {

    private static final long serialVersionUID = -7049957706738879274L;

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="judgements_id_seq")
    @SequenceGenerator(name="judgements_id_seq", sequenceName="judgements_id_seq", allocationSize=1)
    @Column(name = "JUD_ID")
    private Long _judId;
...

allocationSize=1 là khá quan trọng. Nếu bạn bỏ qua nó, Hibernate sẽ mù quáng cho rằng trình tự được xác định bằng INCREMENT 50 vì vậy, khi nó nhận một giá trị từ một chuỗi, nó có thể sử dụng giá trị đó và 49 giá trị bên dưới nó dưới dạng các khóa được tạo duy nhất. Nếu chuỗi cơ sở dữ liệu của bạn tăng lên 1 - mặc định - thì điều này sẽ dẫn đến các vi phạm duy nhất vì Hibernate cố gắng sử dụng lại các khóa hiện có.

Lưu ý rằng việc nhận một khóa tại một thời điểm sẽ dẫn đến một chuyến đi khứ hồi bổ sung cho mỗi lần chèn. Theo như tôi có thể nói thì Hibernate không có khả năng sử dụng INSERT ... RETURNING để trả về các khóa đã tạo một cách hiệu quả, cũng như không thể sử dụng giao diện khóa được tạo JDBC. Nếu bạn yêu cầu nó sử dụng một chuỗi, nó sẽ gọi nextval để nhận giá trị thì insert một cách rõ ràng, dẫn đến hai chuyến đi khứ hồi. Để giảm chi phí của việc đó, bạn có thể đặt mức tăng lớn hơn cho các chuỗi khóa có nhiều phần chèn, hãy nhớ đặt mức này trên ánh xạ trình tự cơ sở dữ liệu cơ bản. Điều đó sẽ khiến Hibernate gọi nextval ít thường xuyên hơn và bộ nhớ cache các khối khóa để phát khi nó hoạt động.

Tôi chắc rằng bạn có thể thấy ở trên rằng tôi không đồng ý với các lựa chọn thiết kế Hibernate được thực hiện ở đây, ít nhất là từ góc độ sử dụng nó với PostgreSQL. Họ nên sử dụng getGeneratedKeys hoặc sử dụng INSERT ... RETURNING với DEFAULT đối với khóa, cho phép cơ sở dữ liệu xử lý việc này mà không cần Hibernate gặp rắc rối với chính nó về tên của các trình tự hoặc quyền truy cập rõ ràng vào chúng.

BTW, nếu bạn đang sử dụng Hibernate với Pg, bạn cũng có thể muốn một trình kích hoạt oplock cho Pg để cho phép khóa lạc quan của Hibernate tương tác an toàn với khóa cơ sở dữ liệu thông thường. Nếu không có nó hoặc những thứ tương tự như vậy, các bản cập nhật Hibernate của bạn sẽ có xu hướng che lấp những thay đổi được thực hiện thông qua các ứng dụng SQL thông thường khác. Hỏi tôi làm sao tôi biết được.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Chuyển id người dùng đến trình kích hoạt PostgreSQL

  2. Làm thế nào để đếm ngày trừ Chủ nhật giữa hai ngày trong Postgres?

  3. Tạo dữ liệu và chất lượng phần cứng

  4. lastInsertId không hoạt động trong Postgresql

  5. SQLAlchemy nhiều khóa ngoại trong một lớp được ánh xạ tới cùng một khóa chính