2009-11-30 52 views
10

nhìn tổ chức khóa chính của tôi như dưới đâyJPA tự động khóa chính tạo

@GeneratedValue(strategy= GenerationType.TABLE) 
private Long id; 

khi tôi chạy, tôi nhận được lỗi

không thể có được hoặc cập nhật giá trị tiếp theo; lồng nhau ngoại lệ là org.hibernate.exception. SQLGrammerException: không thể có được hoặc cập nhật giá trị tiếp theo

nhưng khi tôi chỉ cần thay đổi để

@GeneratedValue 
private Long id; 

không có lỗi ném. Tôi muốn tạo khóa chính duy nhất cho mỗi bảng trên oracle db.

Trả lời

28

@GeneratedValue(strategy=GenerationType.TABLE) yêu cầu nhà cung cấp JPA sử dụng bảng để lấy ID từ khi chèn thực thể mới được tạo vào cơ sở dữ liệu.

Khi sử dụng Hibernate làm nhà cung cấp, điều này sẽ dẫn đến một bảng hibernate_sequences có hai cột: tên thực thể và danh tính tối đa đã được gán cho thực thể này. Ở đây, có vẻ như Hibernate không thành công để có được ID tiếp theo từ nó cho thực thể của bạn nhưng thật khó để nói chính xác lý do tại sao bởi vì bạn đã không cung cấp đủ thông tin cho điều đó.

Vì vậy, bạn có thể vui lòng cung cấp toàn bộ stacktrace không? Ngoài ra, vui lòng bật tính năng ghi nhật ký với thuộc tính hibernate.show_sql được đặt thành true và đặt mức nhật ký thích hợp log4j.logger.org.hibernate.SQL=DEBUG. Tham gia nhật ký cho câu hỏi của bạn nếu có thể.

Có thể chỉ cần kiểm tra xem bạn đã định cấu hình đúng hibernate.dialect cho Oracle chưa. Trên thực tế, hãy tham gia cấu hình ngủ đông của bạn nếu có thể.

PS: Cách "truyền thống" để tạo PK với Oracle là sử dụng chuỗi (bạn có thể để Hibernate đoán chiến lược tốt nhất cho loại cơ sở dữ liệu của bạn bằng cách sử dụng GenerationType.AUTO hoặc ép nó bằng cách sử dụng SEQUENCE) nhưng tôi cho rằng bạn muốn kết quả cấu trúc dữ liệu là cơ sở dữ liệu bất khả tri. Nếu không, tôi đề nghị đi cho chuỗi thay thế.

EDIT: Trả lời nhận xét từ OP về GenerationType.AUTO. Thật vậy, mặc định là một chuỗi toàn cầu duy nhất được gọi là hibernate_sequence và điều này có thể là một vấn đề. Nhưng, với các thiết lập hiển thị dưới đây, bạn có thể sử dụng GenerationType.AUTO và vẫn kiểm soát tên của dãy cho các trường hợp cơ sở dữ liệu sử dụng các trình tự:

@Id 
@GeneratedValue(strategy=GenerationType.AUTO, generator="my_entity_seq_gen") 
@SequenceGenerator(name="my_entity_seq_gen", sequenceName="MY_ENTITY_SEQ") 
private long id; 

Nói cách khác, bạn có thể sử dụng sử dụng một tên chuỗi khác nhau cho mỗi bảng mà không mất tính di động.

+2

nếu tôi đặt GenerationType.Auto, nó sẽ sử dụng số gia tăng toàn cầu, có nghĩa là tất cả các thực thể của tôi sẽ tăng cùng một số. Các mã chạy tốt, nhưng nó sẽ chạy ra khỏi số gia tăng? – cometta

+0

@Pascal: Nếu chúng tôi đang cung cấp Trình tạo chuỗi, nó có giúp xác định startegy là AUTO không? – Nrj

+0

@Nrj Trên thực tế, nếu bạn sử dụng 'AUTO' và nếu cơ sở dữ liệu sử dụng chuỗi,' @ SequenceGenerator' sẽ giúp kiểm soát tên của chuỗi. Nhưng nó sẽ bị "bỏ qua" nếu cơ sở dữ liệu không (ví dụ với HSQLDB). Vì vậy, không giống như 'SEQUENCE', điều này vẫn còn cầm tay. –

7

Có 4 chiến lược cho thế hệ tự động trong JPA:

  • Auto
  • nhận dạng
  • Chuỗi
  • Bảng

Đối với Oracle tự động phát điện đầu tiên quan trọng chú thích, trình tự và Bảng là sự lựa chọn của bạn.Logic cơ bản là định nghĩa một trình tạo đầu tiên, sử dụng lần lượt là @SequenceGenerator hoặc @TableGenerator, sau đó sử dụng trình tạo làm thuộc tính trong @GeneratedValue.

Đây là một mẫu về cách sử dụng chiến lược Chuỗi:

@Id 
    @SequenceGenerator(name="SEQ_GEN", sequenceName="SEQ_JUST_FOR_TEST", allocationSize=1) 
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_GEN") 
    private long id; 

Dưới đây là một ví dụ về cách sử dụng chiến lược bảng:

@Id 
    @TableGenerator(name="TABLE_GEN",table="T_GENERATOR", pkColumnName = "GEN_KEY", pkColumnValue = "MONITOR2012.T_JUST_FOR_TEST", valueColumnName = "GEN_VALUE", initialValue = 1, allocationSize = 1) 
    @GeneratedValue(strategy = GenerationType.TABLE, generator="TABLE_GEN") 
    private long id; 

Nếu không có máy phát điện quy định tại @GeneratedValue chú thích , sự lựa chọn sẽ để lại cho việc thực hiện JPA.

Nếu bạn đang làm việc trên cơ sở dữ liệu với các bảng hiện có, hãy đảm bảo trình tự hoặc bảng được xác định trong cơ sở dữ liệu trước khi bạn chạy ứng dụng của mình. Trình tạo bảng cũng sẽ cần bạn chèn một dòng vào bảng trước khi chú thích @GeneratedValue có thể hoạt động bình thường.

Đây là hướng dẫn về how to configure primary key auto generation in JPA for Oracle database.

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