Thật là một mớ hỗn độn ... AUTO_INCREMENT là chuỗi ẩn của MySQL. Vấn đề cơ bản là MySQL không thể chèn và trả lại PK cùng một lúc, nhưng Hibernate cần điều này trong khi INSERT nhập một Thực thể mới.
Các vấn đề bạn gặp phải:
- Nếu Hibernate lưu một Thực thể mới, anh ta sẽ cố gắng đặt id không chính xác thành EntityBean mới. Do đó, hibernate phải đọc ID nào mà Database sẽ sử dụng trước khi hibernate lưu Tuple mới vào Table.
- Nếu bạn có nhiều Máy chủ truy cập vào cơ sở dữ liệu, bạn phải để nhà máy phiên của chế độ ngủ đông quyết định sử dụng trình tự cài sẵn (AUTO-INCREMENT) hoặc để chế độ ngủ đông quyết định (
GenerationType.AUTO/GenerationType.IDENTITY) phạm vi mở của PK dành riêng lớn như thế nào (Công việc của một Kiến trúc sư DB). (Chúng tôi có khoảng 20 máy chủ cho một Cơ sở dữ liệu, vì vậy trên một bảng được sử dụng tốt, chúng tôi sử dụng khoảng cách PK là +100). Nếu chỉ một máy chủ có quyền truy cập vào cơ sở dữ liệuGenerationType.TABLEsẽ đúng.
Hibernate phải tự mình tính toán id tiếp theo bằng cách sử dụng max(*)+1 nhưng:
- Điều gì sẽ xảy ra nếu hai yêu cầu yêu cầu
max(*)+1cùng một lúc / với cùng một kết quả? Đúng:Lần thử cuối cùng đểinsertsẽ thất bại.
Vì vậy, bạn cần có một Bảng LAST_IDS trong cơ sở dữ liệu lưu trữ Table-PK's cuối cùng. Nếu bạn muốn thêm một, bạn phải thực hiện các bước sau:
- Bắt đầu giao dịch lạc quan đọc.
- CHỌN TỐI ĐA (address_id) TỪ LAST_IDS
- lưu trữ tối đa trong một biến java, tức là:$ OldID.
- $ NewID =$ OldID + 1 (+100 trong khóa bi quan)
- CẬP NHẬT LAST_IDS SET address_id =
$newIDWHERE address_id =$oldID? - cam kết giao dịch lạc quan đọc.
- nếu cam kết thành công, hãy lưu trữ
$newIDthànhsetID()trong HibernateBean mà bạn muốn lưu. - Cuối cùng, hãy để Hibernate gọi chèn.
Đây là cách duy nhất tôi biết.
BTW:Hibernate-Entitys sẽ chỉ sử dụng kế thừa nếu Cơ sở dữ liệu hỗ trợ kế thừa giữa các bảng như PostgreSQL hoặc Oracle .