JPA SERIES - QUAN HỆ
IDENTITY: Cần ID Sau SQL, Nên Không Gom Được Insert
ID TIMING - XANH = TẦNG PHÓNG TOBatching cần trì hoãn statement. IDENTITY cần chạy insert để database trả generated key.
IDENTITY
ID được sinh on execution; trong transaction, identity insert thường là early insert và chạy ngay từng entity.
Xung đột về thời điểmMuốn JDBC batch phải xếp nhiều statement lại; muốn lấy identity key phải execute statement trước.
SEQUENCE / before execution
Hibernate lấy ID trước, đặt entity vào persistence context và giữ insert action tới flush để batch.
Mức 1 - chọn nhánh sinh ID
AbstractSaveEventListener.saveWithGeneratedId()
Generator quyết định ID có trước hay sau statement
persister.getGenerator()Lấy generator đã resolve từ mapping.generator.generatedOnExecution(...)IDENTITY trả true: database sinh ID khi insert chạy.generatedId = nullChưa thể set identifier trước SQL.- Before-execution generatorSequence/pooled strategy lấy ID rồi
persister.setIdentifier()trước insert. performSave(...)Đưa lựa chọn timing xuống action creation.
Mức 2 - identity early insert
EntityIdentityInsertAction
Trong transaction, action phải execute để nhận generated key
delayIdentityInserts == falseKhi transaction đang chạy hoặc caller cần ID ngay, identity insert không được trì hoãn.isEarlyInsert()Trả!isDelayedcho identity action.ActionQueue.addInsertAction()Nhìn thấy early insert và flush các insert đang chờ trước nó.execute(insert)Chạy identity insert ngay thay vì thêm vào executable insertions list.getGeneratedId()Đọc key database trả về, set ID và hoàn tất entity key.
Mức 3 - đường có thể batch
EntityInsertAction Trong Queue
ID đã có cho phép trì hoãn tới flush
- Sequence cấp ID trước
allocationSizehoặc pooled optimizer giảm số lần hỏi sequence. - Entity key có sẵnPersistence context có thể quản lý entity trước khi row được insert.
- Insert action vào
ActionQueueNhiều action cùng SQL shape được giữ tới flush. hibernate.jdbc.batch_sizeBatch coordinator chỉ có việc để gom khi statement được trì hoãn.order_insertskhi cầnSắp action theo entity type có thể tăng cơ hội lấp đầy batch.
Phép kiểm: cùng một transaction và dataset, bật statistics rồi so IDENTITY với SEQUENCE: prepared statements, executed JDBC batches, sequence calls và thời gian. Giữ nguyên batch size, driver rewrite option và flush/clear cadence.
Chọn ID theo workload
- Dùng sequence/pooled strategy nếu DB hỗ trợID có trước giúp queue và batch insert.
- Import theo chunkFlush và clear định kỳ để giới hạn persistence context.
- Test trên đúng driver và databaseJDBC batch còn phụ thuộc driver rewrite và SQL shape.
Khi KHÔNG được kết luận
- Bật
batch_sizelà đủIDENTITY không để statement tích lũy; association và SQL shape cũng có thể phá batch. - Sequence phải cho ID liên tụcAllocation, rollback và concurrency tạo gap; identity là danh tính, không phải số thứ tự nghiệp vụ.
- Mọi generated-on-execution đều tuyệt đối không delaySource có nhánh delayed identity ngoài transaction khi caller không cần ID ngay; workload chuẩn trong transaction không đi nhánh đó.