2011-08-24 33 views
17

Tôi đã định cấu hình ngủ đông để sử dụng trình tự oracle. Trình tự được tạo với bộ nhớ cache = 20, số gia tăng = 1.Hibernate với trình tự Oracle không sử dụng nó

Tất cả đều hoạt động tốt, các thực thể bền vững hibernate. Giá trị id lạ: 50,51 .... 76,201,202 ... 209,1008,1009,5129,5130 ....

Nếu tôi yêu cầu giá trị chuỗi (chọn hibernate_sequence.nextval từ kép), tôi nhận được giá trị như 2,3,4 ....

Nếu tôi bật gỡ lỗi sql hibernate, có thời gian gọi "chọn hibernate_sequence.nextval từ kép" nhưng số được gán bởi hibernate thành ID không chuyển tiếp theo trình tự !

@Id 
@Column(name = "ID", insertable = false, updatable = false) 
@SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "HIBERNATE_SEQUENCE") 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceIdGenerator") 
private Long id; 

Trả lời

30

Điều này là do Trình tạo chuỗi không thực sự là trình tạo trình tự. Đó là một máy phát hi-lo chuỗi. Điều này có nghĩa là lần đầu tiên nó được gọi, nó nhận giá trị tiếp theo từ chuỗi (ví dụ 6), sau đó nhân giá trị này với 50 và cung cấp cho bạn kết quả (300). Lần sau nó được gọi, nó trả về 301 (không đi theo trình tự), và cứ như vậy cho đến khi nó đạt tới 349. Sau đó nó sẽ hỏi chuỗi giá trị tiếp theo và thu được 7, nó nhân với 50 lần nữa để cung cấp cho bạn 350. mô tả thuật toán có thể được tắt bởi một, nhưng bạn có được ý tưởng.

Nếu bạn dừng và khởi động ứng dụng của mình, nó sẽ có khoảng trống. Nhưng nó hiệu quả hơn một trình tạo chuỗi thứ tự thuần túy bởi vì nó chỉ tạo ra một cuộc gọi cơ sở dữ liệu một lần trong 50 thế hệ.

Xem http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-id-enhanced-optimizershttp://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#mapping-declaration-id-generator để biết chi tiết.

+10

Bạn không phải tăng thêm 50 lần mỗi lần. Đó chỉ là mặc định. Sử dụng @SequenceGenerator (tên = "SEQ_ID", sequenceName = "SEQ_ID", allocSize = 1) Để tăng thêm chỉ một. allocSize là khóa. – dseibert

+2

Có cách nào để không sử dụng điều này? Vì nó gây ra một vấn đề lớn đối với tôi, có các trình kích hoạt khác sử dụng cùng trình tự này cho bảng này. Sau đó, họ có thể nhấn số này trong tương lai, phải không? –

+0

Xem nhận xét ngay phía trên của bạn. Sử dụng allocSize. –

6

Tôi mang nó rằng câu hỏi của bạn là các giá trị của cột ID trong cơ sở dữ liệu không phải là một chu kỳ tự nhiên, nhưng những khoảng trống do tại sao bạn đang nhìn thấy:

Một chút nền:

  • Mỗi thời gian bạn gọi là select HIBERNATE_SEQUENCE.nextval from DUAL giá trị của chuỗi được tăng lên.
  • Vì tên trình tự của bạn là chung chung hơn là cụ thể cho bảng, nếu bạn có nhiều thực thể, tất cả đều sử dụng HIBERNATE_SEQUENCE làm trình tạo id, thì các giá trị từ chuỗi được sử dụng trong tất cả các thực thể.
  • Nếu một số ứng dụng khác sử dụng HIBERNATE_SEQUENCE, thì giá trị cũng bị bỏ qua.
  • Khi bạn đang sử dụng CACHE = 20, Oracle sẽ lấy số thứ tự trong các khối 20 và sau đó sử dụng bộ nhớ cache nội bộ để trả về các số. Điều này có thể dẫn đến số bị bỏ qua nếu bộ nhớ cache bị mất (ví dụ: nếu DB bị tắt).
  • Nếu hàng sẽ bị xóa khỏi cơ sở dữ liệu của bạn, giá trị chuỗi không thay đổi

Ví dụ, hãy xem xét các tình huống sau:

Bạn đã có hai thực thể ENTITY1 và ENTITY2 sử dụng HIBERNATE_SEQUENCE như máy phát điện ID :

  1. giá trị HIBERNATE_SEQUENCE hiện tại là 100
  2. Một ENTITY1 được chèn (sử dụng HIBERNATE_SEQUENCE mà trả 101)
  3. 01.235.
  4. Một ENTITY2 được chèn (sử dụng HIBERNATE_SEQUENCE mà trả 102)
  5. Một ENTITY2 được chèn (sử dụng HIBERNATE_SEQUENCE mà trả 103)
  6. Các ENTITY2 với ID 103 sẽ bị xóa
  7. Bạn tự thực hiện select HIBERNATE_SEQUENCE.nextval from DUAL (trả 104)
  8. Một ENTITY1 được chèn (sử dụng HIBERNATE_SEQUENCE mà trả 105)
  9. Một ENTITY2 được chèn (sử dụng HIBERNATE_SEQUENCE mà trả 106)

Vì vậy, ở phần cuối của nó, bạn sẽ có:

  • ENTITY1 với ID (101, 105)
  • ENTITY2 với ID (102, 106)

điều này giải thích những khoảng trống.

EDIT:

Ngay cả khi @SequenceGenerator đã được thiết lập để sử dụng SequenceGenerator chứ không phải là SequenceHiLoGenerator (như được chỉ ra bởi JB Nizet, mà tôi nghĩ là một lời giải thích tốt hơn cho những khoảng trống), những khoảng trống trong ID được tạo ra bởi trình tự là một sự xuất hiện phổ biến.

1
CREATE SEQUENCE SEQ_SEQUENCENAME INCREMENT BY 1 START WITH 1 MINVALUE 1; 
grant all on SEQ_SEQUENCENAME to public; 

@Id 
@Column(name = "ID", unique = true, nullable = false) 
@SequenceGenerator(name = "SequenceIdGenerator", sequenceName = "SEQ_SEQUENCENAME") 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SequenceIdGenerator") 
private int Id; 
Các vấn đề liên quan