2013-07-24 26 views
6

Tôi đã xác định một số đối tượng Hibernate bằng cách sử dụng các chú thích JPA thuần túy. Chúng sử dụng một Oracle Sequence được xác định trước trên cơ sở dữ liệu của tôi để tự động tạo ra các giá trị khóa chính.JBoss EAP 6.x với Hibernate Oracle Sequence Giá trị trùng lặp trên khóa chính

@Id 
@SequenceGenerator(name = "USERS_ID_GENERATOR", sequenceName = "MY_SEQ") 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "USERS_ID_GENERATOR") 
@Column(name = "U_ID", updatable = false, unique = true, nullable = false, precision = 19) 
private Long id; 

Khi điều này được triển khai lên JBoss EAP 6.1, tất cả hoạt động tốt ban đầu sau một khoảng thời gian ngắn Hibernate bắt đầu tạo khóa trùng lặp trên các lỗi (lỗi ORA-00001).

Tôi không quan tâm đến thứ tự id hoặc khoảng trống, nhưng không thể chịu đựng được các khóa trùng lặp ... Điều gì đang xảy ra ở đây?

Trả lời

13

Đây không phải là tài liệu tốt, nhiều giải pháp trên đây và các trang web khác liên quan đến các phiên bản cũ hơn của ngủ đông, nơi trình tự tuần tự HiLo là mặc định. Nhưng sau khi điều tra tôi thấy nguyên nhân cơ bản là JBoss EAP 6 bộ

hibernate.id.new_generator_mappings=true 

theo mặc định, trong đó sử dụng một org.org.hibernate.id.enhanced.SequenceStyleGenerator thay vì phiên bản cũ hơn.

Tăng mặc định Hibernate SequenceStyleGenerator là 1 (kiểm tra mã!), Tuy nhiên JPA ghi đè giá trị tăng trong máy phát này lên 50. Điều này có nghĩa là Máy phát sẽ xem xét chuỗi tiếp theo và giữ bộ nhớ cache gồm 50 id để sử dụng, bắt đầu từ kế tiếp - 49. Khi chúng bị cạn kiệt, máy phát sẽ đọc chuỗi tiếp theo từ oracle, và lặp lại quá trình. Vì vậy, khi chuỗi id đầu tiên bị cạn kiệt, chúng tôi bắt đầu thấy các khóa trùng lặp.

Vì vậy, độ phân giải là:

1) Hoặc là xác định Oracle chuỗi của bạn (s) với giá trị thặng dư của 50 để phù hợp với JPA mặc định

CREATE SEQUENCE MY_SEQ 
START WITH 50 
MAXVALUE 9999999999999999999 
INCREMENT BY 50 
NOCYCLE; 

hoặc

2) Thêm allocationSize = 1 đến chú thích @SequenceGenerator - điều này buộc Trình tự sắp xếp quay trở lại để đọc giá trị tiếp theo từ chuỗi oracle cho mỗi ID mà nó yêu cầu (với tác động hiệu suất tiềm năng)

@SequenceGenerator(name = "USERS_ID_GENERATOR", sequenceName = "MY_SEQ", allocationSize = 1) 

hoặc

3) xác định chuỗi Oracle INCREMENT BY một số giá trị khác và đảm bảo phân bổKích thước phù hợp.

Đã trả lời câu hỏi của riêng tôi với hy vọng giúp những người khác tấn công vấn đề này.

+0

Mặc dù tôi đang tìm kiếm một số thông tin khác, cách bạn thêm thông tin làm câu trả lời để giúp người khác xứng đáng +1. – kosa

1

Câu trả lời của bạn là chính xác; chỉ một số chi tiết.

Một số bài đăng đề xuất tắt hibernate.id.new_generator_mappings = false.

Nhưng theo https://docs.jboss.org/author/display/AS71/JPA+Reference+Guide#JPAReferenceGuide-Persistenceunitproperties

Có sự khác biệt giữa GenerationType.AUTO và GenerationType.SEQUENCE

nếu bạn chọn AUTO, bạn sẽ chọn bản địa hibernate. và nếu bạn chọn SEQUENCE, bạn sẽ khớp với thuật toán hilo để phân bổ chuỗi hoàn toàn không giống với SequenceStyleGenerator. Điều này sẽ KHÔNG tương thích nếu bạn chuyển đổi hibernate.id.new_generator_mappings = true/false.

Vì vậy, câu trả lời 1) chắc chắn là đúng/theo các đề xuất Hibernate/Jboss hiện tại.

... và phân bổ cài đặt trả lờiSize = 1 cho tất cả các thực thể không phải là giải pháp tốt. Xem http://itdevworld.wordpress.com/2009/12/20/hibernate-sequencegenerator-with-allocationsize1-leads-to-huge-contention/

+1

Cảm ơn @skay, tôi đã thêm một làm rõ để trả lời 2) về tác động hiệu suất tiềm năng của đơn allocaionts. Điều này đặc biệt đáng chú ý trong môi trường RAC nếu chuỗi được thiết lập với 'thứ tự'. –

+0

Lưu ý - tài liệu JBoss trong liên kết đề cập rằng đây là cài đặt Hibernate 4.x. Nó cũng được hỗ trợ trong Hibernate 3. Sử dụng nó với 3.6.0.Final trong ứng dụng của chúng tôi .. JBoss AS 7 tàu với 4.x do đó làm thế nào tài liệu của họ đề cập đến nó. –

Các vấn đề liên quan