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.TABLE
sẽ đú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(*)+1
cùng một lúc / với cùng một kết quả? Đúng:Lần thử cuối cùng đểinsert
sẽ 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 =
$newID
WHERE 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ữ
$newID
thà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
.