Tôi không nhớ rõ liệu Hibernate có thực sự tự lưu trữ các phiên bản PreparedStatement hay dựa vào nhà cung cấp kết nối để sử dụng lại chúng. (Quét nhanh BatcherImpl cho thấy nó sử dụng lại PreparedStatement cuối cùng nếu thực thi cùng một SQL nhiều lần liên tiếp)
Tôi nghĩ rằng điểm mà tài liệu c3p0 đang cố gắng thực hiện là đối với nhiều trình điều khiển JDBC, PreparedStatement không hữu ích:một số trình điều khiển sẽ chỉ đơn giản là nối các tham số ở phía máy khách và sau đó vẫn chuyển câu lệnh SQL đã xây dựng vào cơ sở dữ liệu. . Đối với những trình điều khiển này, PreparedStatements không có lợi gì cả và mọi nỗ lực để sử dụng lại chúng đều bị lãng phí. (Câu hỏi thường gặp về Postgresql JDBC cho biết đây là trường hợp của Postgresql trước giao thức sever phiên bản 3 và có nhiều thông tin chi tiết hơn trong tài liệu).
Đối với các trình điều khiển xử lý hữu ích PreparedStatements, vẫn có khả năng cần thực sự sử dụng lại các phiên bản PreparedStatement để nhận được bất kỳ lợi ích nào. Ví dụ:nếu trình điều khiển thực hiện:
- Connection.prepareStatement (sql) - tạo một câu lệnh phía máy chủ
- PreparedStatement.execute (..), v.v. - thực thi câu lệnh phía máy chủ đó
- PreparedStatement.close () - phân bổ câu lệnh phía máy chủ
Với điều này, nếu ứng dụng luôn mở một câu lệnh đã chuẩn bị, thực thi nó một lần và sau đó đóng nó lại, thì vẫn có vẫn còn không có lợi ích; trên thực tế, nó có thể tồi tệ hơn vì bây giờ có nhiều chuyến đi khứ hồi hơn. Vì vậy, ứng dụng cần phải bám vào các phiên bản PreparedStatement. Tất nhiên, điều này dẫn đến một vấn đề khác:nếu ứng dụng bị treo trên quá nhiều và mỗi câu lệnh phía máy chủ tiêu thụ một số tài nguyên, thì điều này có thể dẫn đến các sự cố phía máy chủ. Trong trường hợp ai đó đang sử dụng JDBC trực tiếp, điều này có thể được quản lý bằng cách thủ công - một số câu lệnh được cho là có thể sử dụng lại và do đó được chuẩn bị; một số không và chỉ sử dụng các phiên bản Statement tạm thời để thay thế. (Điều này đang bỏ qua lợi ích khác của các câu lệnh chuẩn bị:xử lý thoát đối số)
Vì vậy, đây là lý do tại sao c3p0 và các nhóm kết nối khác cũng đã chuẩn bị sẵn các bộ nhớ đệm câu lệnh - nó cho phép mã ứng dụng tránh phải xử lý tất cả những điều này. Các câu lệnh thường được giữ trong một số nhóm LRU hạn chế, vì vậy các câu lệnh phổ biến sử dụng lại một phiên bản PreparedStatement.
Những mảnh ghép cuối cùng của câu đố là các trình điều khiển JDBC có thể tự quyết định thông minh và thực hiện điều này; và bản thân các máy chủ cũng có thể quyết định khôn khéo và phát hiện ra một ứng dụng khách đang gửi một báo cáo có cấu trúc tương tự như trước đó.
Do bản thân Hibernate không giữ bộ nhớ cache của các phiên bản PreparedStatement, bạn cần phải có c3p0 làm điều đó để có được lợi ích của chúng. (Điều này sẽ được giảm chi phí cho các báo cáo thông thường do sử dụng lại các kế hoạch đã lưu trong bộ nhớ cache). Nếu c3p0 không lưu vào bộ nhớ cache các câu lệnh đã chuẩn bị, thì trình điều khiển sẽ chỉ thấy ứng dụng chuẩn bị một câu lệnh, thực thi nó, rồi đóng nó lại. Có vẻ như trình điều khiển JDBC có cài đặt "ngưỡng" để tránh chuẩn bị / thực thi chi phí máy chủ trong trường hợp ứng dụng luôn thực hiện điều này. Vì vậy, có, bạn cần có bộ nhớ đệm câu lệnh c3p0 do.
Hy vọng điều đó sẽ hữu ích, xin lỗi vì nó hơi dài dòng. Câu trả lời là có .