2015-04-13 16 views
5

Tôi gặp sự cố sau. Trong ứng dụng, mà tôi đang phát triển, chúng tôi sử dụng Hibernate và mọi truy vấn được viết bằng API tiêu chí. Bây giờ, ở một số nơi, chúng tôi muốn thêm khả năng cho người dùng viết một số mã SQL sẽ được sử dụng như một phần của mệnh đề where trong truy vấn. Vì vậy, về cơ bản, người dùng có thể lọc dữ liệu được hiển thị cho anh ta từ cơ sở dữ liệu theo cách riêng của mình.Làm thế nào để sử dụng SQL gốc dưới dạng một đoạn (trong đó khoản) của truy vấn lớn hơn được tạo bằng API Tiêu chí trong Hibernate?

Trong vài ngày tới, tôi đang cố gắng tìm cách sửa đổi các truy vấn trước đó của chúng tôi để thu được kết quả được mô tả ở trên. Dưới đây là những gì tôi biết:

  1. Có vẻ như bạn không thể kết hợp API tiêu chí với SQL gốc. Bạn có thể viết toàn bộ truy vấn trong SQL hoặc chỉ sử dụng API tiêu chí. Có đúng không? Tôi hỏi câu hỏi này bởi vì nó sẽ là giải pháp đơn giản nhất, chỉ để sử dụng mã SQL này như một vị từ khác trong mệnh đề where trong truy vấn của chúng tôi. Nhưng tôi không nghĩ nó có thể ở đẳng cấp này.

  2. Tôi biết người dùng bảng nào muốn lọc dữ liệu. Vì vậy, tôi chỉ có thể thực thi truy vấn SQL nguyên gốc và sử dụng danh sách kết quả như một tham số cho mệnh đề IN trong truy vấn tiêu chí. Nhưng tôi không biết liệu nó có hiệu quả với nhiều bản ghi trong danh sách kết quả không. Vì vậy, nếu tôi không thể làm điều đó trên cấp API tiêu chuẩn, tôi nghĩ rằng có lẽ tôi bằng cách nào đó có thể ảnh hưởng đến quá trình biến đổi SQL và đặt SQL của tôi ở một nơi thích hợp nhưng dường như là không thể. Vì vậy, câu hỏi thực sự của tôi là: là nó bằng cách nào đó có thể có quyền truy cập vào mã SQL của truy vấn, sau giai đoạn phát sinh SQL nhưng trước khi thực hiện truy vấn thực tế hay chưa? Chỉ cần thao tác với thủ công? Nó có thể được thực hiện một cách an toàn và đơn giản nhất có thể không?

  3. Hoặc có thể chỉ cần phân tích cú pháp SQL này do người dùng viết và sử dụng nó trong truy vấn tiêu chí?

Thay đổi truy vấn tiêu chí hiện có thành truy vấn SQL nguyên gốc là không được thảo luận.

+0

Không, bạn không thể sử dụng SQL với Tiêu chuẩn JPA - Tiêu chuẩn JPA là để viết JPQL. Nếu một số thực hiện "cung cấp" nó như là một phần mở rộng sau đó bạn mất tính di động. Theo thông số JPA –

Trả lời

2

Có, bạn có thể lấy SQL từ tiêu chí Hibernate bằng cách sử dụng lớp org.hibernate.loader.criteria.CriteriaQueryTranslator.

này sẽ cho phép bạn thêm mệnh đề SQL bổ sung (s) đến cùng và thực hiện nó như là một SQL mẹ đẻ:

CriteriaQueryTranslator translator = new CriteriaQueryTranslator(factory, criteria, "myEntityName", CriteriaQueryTranslator.ROOT_SQL_ALIAS); 
String select = translator.getSelect();  
String whereClause = translator.getWhereCondition(); 

Cá nhân tuy nhiên, nếu phải đối mặt với yêu cầu này tôi sẽ né tránh việc chấp nhận SQL từ người dùng cuối và cung cấp cho họ giao diện người dùng để điền một số loại đối tượng bộ lọc. Điều này sau đó có thể được chuyển đổi thành tiêu chí HQL, an toàn hơn nhiều và không ràng buộc mã của bạn chặt chẽ với việc thực hiện cơ sở dữ liệu.

Chỉnh sửa dựa trên ý kiến ​​

Ví dụ về giải nén SQL từ một truy vấn JPA thực hiện với Hibernate:

CriteriaBuilder builder = entityManager.getCriteriaBuilder(); 
CriteriaQuery<MyEntity> q = builder.createQuery(MyEntity.class); 
Root<MyEntity> entity = q.from(MyEntity.class); 
q.select(entity).orderBy(builder.desc(entity.get("lastModified"))); 
TypedQuery<MyEntity> query = entityManager.createQuery(q); 

String sql = query.unwrap(org.hibernate.Query.class).getQueryString(); 
+0

Cảm ơn bạn đã trả lời, tôi sẽ cố gắng thực hiện những gì bạn đã đề xuất trong giây lát.Tôi đồng ý với ý kiến ​​của bạn về việc chấp nhận SQL từ người dùng cuối và tôi đã xem xét giải pháp này nhưng những gì chúng tôi đang cố gắng làm là phát triển một ứng dụng mới, tốt hơn có chức năng tương tự như ứng dụng hiện tại và nó cần tương thích ngược. Nói cách khác, các bộ lọc đã được viết bằng SQL cũng sẽ hoạt động trong ứng dụng của chúng ta. – MichalD

+0

Hmm, xin lỗi vì đã không chính xác hoặc thậm chí là sai, nhưng nó hoàn toàn mới đối với tôi. Chúng tôi tạo truy vấn bằng cách sử dụng triển khai hibernate cho JPA và không phải với API tiêu chí Hibernate. Và mẫu mã bạn đã viết ở trên dường như chỉ hoạt động đối với API tiêu chuẩn Hibernate, tôi có đúng không? Hoặc có lẽ tôi chỉ pha trộn các khái niệm? – MichalD

+0

Xin lỗi, tôi đã giải thích sai câu hỏi của bạn. Dường như không có yêu cầu trong đặc tả JPA cho một truy vấn để lộ ra SQL bên dưới (có ý nghĩa). Bạn có thể phải bỏ qua để thực hiện, tôi sẽ cập nhật câu trả lời của tôi với một ví dụ. – StuPointerException

Các vấn đề liên quan