Đây là câu hỏi cũ, nhưng tôi gặp sự cố tương tự và tôi đã hình dung được chủ đề này. Tôi cần thêm một bản ghi vào một bộ ghi nhật ký kiểm tra StatelessSession hiện có. Việc triển khai hiện tại đã sử dụng StatelessSession vì hành vi lưu trữ bộ đệm của phiên triển khai phiên chuẩn là không cần thiết trên không và chúng tôi không muốn người nghe ngủ đông của chúng tôi kích hoạt tính năng ghi nhật ký kiểm tra. Triển khai này là về việc đạt được hiệu suất ghi càng cao càng tốt mà không có tương tác.
Tuy nhiên, loại nhật ký mới cần sử dụng loại hành vi chèn khác, nơi chúng tôi dự định cập nhật các mục nhật ký hiện có với thời gian giao dịch là loại hành vi "gắn cờ". Trong một StatelessSession, saveOrUpdate() không được cung cấp vì vậy chúng tôi cần thiết để thực hiện chèn-else-update theo cách thủ công.
Trong ánh sáng của những yêu cầu:
Bạn thể sử dụng mysql "chèn ... vào cập nhật bản sao chìa khóa" hành vi thông qua một tùy chỉnh sql-chèn cho đối tượng dai dẳng hibernate. Bạn có thể xác định các khoản tùy chỉnh sql-chèn hoặc thông qua chú thích (như trong câu trả lời ở trên) hoặc thông qua một tổ chức sql-chèn một ánh xạ xml ngủ đông, ví dụ .:
<class name="SearchAuditLog" table="search_audit_log" persister="com.marin.msdb.vo.SearchAuditLog$UpsertEntityPersister">
<composite-id name="LogKey" class="SearchAuditLog$LogKey">
<key-property
name="clientId"
column="client_id"
type="long"
/>
<key-property
name="objectType"
column="object_type"
type="int"
/>
<key-property
name="objectId"
column="object_id"
/>
</composite-id>
<property
name="transactionTime"
column="transaction_time"
type="timestamp"
not-null="true"
/>
<!-- the ordering of the properties is intentional and explicit in the upsert sql below -->
<sql-insert><![CDATA[
insert into search_audit_log (transaction_time, client_id, object_type, object_id)
values (?,?,?,?) ON DUPLICATE KEY UPDATE transaction_time=now()
]]>
</sql-insert>
Những poster ban đầu hỏi về MySQL đặc biệt. Khi tôi thực hiện hành vi chèn-else-update với mysql, tôi đã nhận được ngoại lệ khi 'đường dẫn cập nhật' của sql được triển khai.Cụ thể, mysql đã báo cáo 2 hàng đã được thay đổi khi chỉ có 1 hàng được cập nhật (bề ngoài vì hàng hiện tại bị xóa và hàng mới được chèn vào). Xem this issue để biết thêm chi tiết về tính năng cụ thể đó.
Vì vậy, khi cập nhật trả về 2x số hàng bị ảnh hưởng đến ngủ đông, hibernate đã ném một BatchedTooManyRowsAffectedException, sẽ quay trở lại giao dịch và đẩy lùi ngoại lệ. Ngay cả khi bạn đã nắm bắt được ngoại lệ và xử lý nó, giao dịch đã được khôi phục vào thời điểm đó.
Sau một số lần đào, tôi thấy rằng đây là vấn đề với thực thể mà hibernate đang sử dụng. Trong trường hợp của tôi hibernate đã được sử dụng SingleTableEntityPersister, trong đó xác định một kỳ vọng rằng số lượng hàng cập nhật phải phù hợp với số hàng được xác định trong hoạt động hàng loạt.
Tinh chỉnh cuối cùng cần thiết để hành vi này hoạt động là xác định persister tùy chỉnh (như được hiển thị trong bản đồ xml ở trên). Trong trường hợp này, tất cả những gì chúng ta phải làm là mở rộng SingleTableEntityPersister và 'override' chèn Expectation. Ví dụ. Tôi chỉ tacked lớp tĩnh này vào đối tượng kiên trì và xác định nó như là persister tùy chỉnh trong các bản đồ ngủ đông:
public static class UpsertEntityPersister extends SingleTableEntityPersister {
public UpsertEntityPersister(PersistentClass arg0, EntityRegionAccessStrategy arg1, SessionFactoryImplementor arg2, Mapping arg3) throws HibernateException {
super(arg0, arg1, arg2, arg3);
this.insertResultCheckStyles[0] = ExecuteUpdateResultCheckStyle.NONE;
}
}
Phải mất nhiều thời gian đào qua mã hibernate để tìm thấy điều này - tôi đã không thể tìm thấy bất kỳ các chủ đề trên mạng với giải pháp cho điều này.
Điều gì sẽ xảy ra nếu bạn muốn sử dụng trường id tăng tự động (nói trong mysql)? Tôi đang nhận được lỗi lạ về cơ sở dữ liệu không trả lại một ID –