JPA và Hibernate - Tiêu chí so với JPQL hoặc HQL


295

Những ưu và nhược điểm của việc sử dụng Tiêu chí hoặc HQL là gì? API Tiêu chí là một cách hướng đối tượng đẹp để thể hiện các truy vấn trong Hibernate, nhưng đôi khi Truy vấn Tiêu chí khó hiểu / xây dựng hơn HQL.

Khi nào bạn sử dụng Tiêu chí và khi HQL? Bạn thích gì trong trường hợp sử dụng? Hay đó chỉ là vấn đề của hương vị?


Câu trả lời đúng sẽ là 'phụ thuộc vào trường hợp sử dụng'.
Hace

Còn công cụ này thì sao? Nó cho phép xây dựng các truy vấn phổ biến theo cách đối tượng: được bảo vệ khoản select () {return em.select ("DISTINCT i") .from (this.getName (), "i") .joinFetch ("i.locale lf") } công khai T findBySlug (Chuỗi sên) {return (T) this.select () .join ("i.locale l"); .where ("l.slug =?", sên) .fetchSingle (); }
Vojtěch

1
Định nghĩa một câu hỏi dựa trên ý kiến, nhưng mọi người vẫn chưa có cơ hội để đóng nó ... theo trang web Câu hỏi thường gặp

Câu trả lời:


212

Tôi chủ yếu thích Truy vấn tiêu chí cho các truy vấn động. Ví dụ, dễ dàng hơn nhiều để thêm một số thứ tự động hoặc bỏ một số phần (ví dụ: hạn chế) tùy thuộc vào một số tham số.

Mặt khác, tôi đang sử dụng HQL cho các truy vấn tĩnh và phức tạp, vì việc hiểu / đọc HQL dễ dàng hơn nhiều. Ngoài ra, HQL mạnh hơn một chút, tôi nghĩ, ví dụ cho các loại tham gia khác nhau.


13
Ngoài ra, mặc dù Tiêu chí có vẻ an toàn hơn một chút, nhưng điều duy nhất có thể khiến bạn cảm thấy an toàn là thử nghiệm.

Có ví dụ nào cho thấy tại sao HQL tốt hơn tiêu chí api trong một số trường hợp nhất định không? Tôi đọc phần cuối của một blog, nhưng không hiểu gì cả. Sẽ đánh giá cao nếu bạn có thể giúp đỡ. Cảm ơn. Liên kết - javalulk.org/articles/hibernatequery102
Erran Morad

Tất cả các lý do ở trên - Tôi cũng thích Tiêu chí hơn cho HQL vì nó an toàn hơn cho lập trình viên, giảm các lỗi mã hóa - việc biên dịch trên chuỗi HQL không được xác thực.
nuno

Tuy nhiên, có vấn đề truy xuất các thực thể riêng biệt trong khi phân trang. Khi làm điều này, tôi chọn HQL để tránh các vấn đề ...
Anthony Webster

sử dụng truy vấn tiêu chí với một siêu mô hình cho các tên cột giúp trong quá trình tái cấu trúc để không phá vỡ bất cứ điều gì và với một lệnh đơn giản từ một IDE hiện đại để đổi tên tất cả các lần xuất hiện trong mã.
Massimo

92

Có một sự khác biệt về hiệu năng giữa HQL và tiêu chíQuery, mỗi khi bạn truy vấn truy vấn bằng tiêu chí, nó sẽ tạo một bí danh mới cho tên bảng không phản ánh trong bộ đệm được truy vấn cuối cùng cho bất kỳ DB nào. Điều này dẫn đến việc tổng hợp SQL được tạo, mất nhiều thời gian hơn để thực thi.

Về chiến lược tìm nạp [http://www.hibernate.org/315.html]

  • Tiêu chí tôn trọng các cài đặt lười biếng trong ánh xạ của bạn và đảm bảo rằng những gì bạn muốn được tải đã được tải. Điều này có nghĩa là một truy vấn Tiêu chí có thể dẫn đến một số câu lệnh CHỌN SQL ngay lập tức để tìm nạp sơ đồ con với tất cả các liên kết và bộ sưu tập ánh xạ không lười biếng. Nếu bạn muốn thay đổi "cách" và thậm chí là "cái gì", hãy sử dụng setFetchMode () để bật hoặc tắt tìm nạp kết nối bên ngoài cho một bộ sưu tập hoặc liên kết cụ thể. Các truy vấn tiêu chí cũng hoàn toàn tôn trọng chiến lược tìm nạp (tham gia vs select vs subselect).
  • HQL tôn trọng các cài đặt lười biếng trong ánh xạ của bạn và đảm bảo rằng những gì bạn muốn được tải đã được tải. Điều này có nghĩa là một truy vấn HQL có thể dẫn đến một số câu lệnh CHỌN SQL ngay lập tức để tìm nạp sơ đồ con với tất cả các liên kết và bộ sưu tập ánh xạ không lười biếng. Nếu bạn muốn thay đổi "cách" và thậm chí là "cái gì", hãy sử dụng LEFT THAM GIA FETCH để cho phép tìm nạp ngoài tham gia cho một bộ sưu tập cụ thể hoặc liên kết nhiều-một hoặc một hoặc không thể tham gia hoặc THAM GIA FETCH để bật tham gia nội bộ tìm nạp cho một hiệp hội nhiều-một hoặc một-một không thể vô hiệu. Các truy vấn HQL không tôn trọng bất kỳ fetch = "tham gia" nào được xác định trong tài liệu ánh xạ.

1
Chỉ cần chỉ ra cho bất cứ ai duyệt. rằng câu trả lời này là từ năm 2008, điều này có thể không còn xảy ra nữa. dimigsev.blogspot.com/2015/02/ trên
Amalgovinus

41

Tiêu chí là một API hướng đối tượng, trong khi HQL có nghĩa là nối chuỗi. Điều đó có nghĩa là tất cả các lợi ích của hướng đối tượng được áp dụng:

  1. Tất cả những thứ khác đều bằng nhau, phiên bản OO có phần ít bị lỗi hơn. Bất kỳ chuỗi cũ nào cũng có thể được thêm vào truy vấn HQL, trong khi chỉ các đối tượng Tiêu chí hợp lệ mới có thể biến nó thành cây Tiêu chí. Có hiệu quả, các lớp Tiêu chí bị ràng buộc nhiều hơn.
  2. Với tính năng tự động hoàn thành, OO dễ khám phá hơn (và do đó, dễ sử dụng hơn, đối với tôi ít nhất). Bạn không nhất thiết phải nhớ phần nào của truy vấn đi đâu; IDE có thể giúp bạn
  3. Bạn cũng không cần phải nhớ các chi tiết của cú pháp (giống như biểu tượng đi đâu). Tất cả những gì bạn cần biết là làm thế nào để gọi các phương thức và tạo các đối tượng.

Vì HQL rất giống SQL (mà hầu hết các nhà phát triển đã biết rất rõ), nên các đối số "không cần phải nhớ" này không mang nhiều trọng lượng. Nếu HQL khác hơn, thì điều này sẽ quan trọng hơn.


12
Các đối số này không giữ nước (đối với HQL). Nó không phải liên quan đến nối chuỗi. Phiên bản OO ít bị lỗi hơn là không có căn cứ. Nó cũng dễ bị lỗi nhưng thuộc loại khác. Nỗ lực của việc biết nên gọi phương thức nào không khác nhiều so với việc biết nên gọi biểu tượng nào trong HQL (ý tôi là, nghiêm túc, chúng tôi không giải quyết PDE ở đây.)
luis.espinal

Có ví dụ nào cho thấy tại sao HQL tốt hơn tiêu chí api trong một số trường hợp nhất định không? Tôi đọc phần cuối của một blog, nhưng không hiểu gì cả. Sẽ đánh giá cao nếu bạn có thể giúp đỡ. Cảm ơn. Liên kết - javalulk.org/articles/hibernatequery102
Erran Morad

1
Các truy vấn có tên HQL được biên dịch theo thời gian triển khai và tại thời điểm này, các trường bị thiếu (có thể cho các bộ tái cấu trúc xấu?) Được phát hiện. Tôi nghĩ rằng điều này làm cho mã trở nên linh hoạt hơn và trên thực tế ít bị lỗi hơn các tiêu chí.
narduk

Tự động hoàn thành trong Tiêu chí khá nhiều vô dụng vì các thuộc tính chỉ là chuỗi.
Lluis Martinez

35

Tôi thường sử dụng Tiêu chí khi tôi không biết đầu vào nào sẽ được sử dụng trên phần dữ liệu nào. Giống như trên một hình thức tìm kiếm nơi người dùng có thể nhập bất kỳ từ 1 đến 50 mục và tôi không biết họ sẽ tìm kiếm gì. Rất dễ dàng để chỉ thêm vào các tiêu chí khi tôi kiểm tra xem người dùng đang tìm kiếm cái gì. Tôi nghĩ sẽ khó khăn hơn một chút khi đặt truy vấn HQL trong tình huống đó. HQL là tuyệt vời mặc dù khi tôi biết chính xác những gì tôi muốn.


1
Đây là một nhận xét tốt. Chúng tôi hiện đang xây dựng các chuỗi HQL rất lớn cho một hình thức tìm kiếm có chứa nhiều đối tượng khác nhau thông qua các phép nối. Trông xấu xí. Đi để xem nếu một Tiêu chí có thể làm sạch điều đó. Thú vị ...
cbmeek

Cảm ơn. Đây là một ví dụ tuyệt vời. Bạn có thể vui lòng cho tôi thêm một số?
Erran Morad

31

HQL dễ đọc hơn nhiều, dễ gỡ lỗi hơn bằng cách sử dụng các công cụ như plugin Hibernate của Eclipse và dễ dàng đăng nhập hơn. Các truy vấn tiêu chí tốt hơn để xây dựng các truy vấn động trong đó nhiều hành vi được xác định khi chạy. Nếu bạn không biết SQL, tôi có thể hiểu bằng cách sử dụng các truy vấn Tiêu chí, nhưng nói chung tôi thích HQL hơn nếu tôi biết những gì tôi muốn trả trước.



21

Tiêu chí Api là một trong những khái niệm hay về Hibernate. theo quan điểm của tôi đây là một vài điểm mà chúng ta có thể tạo ra sự khác biệt giữa HQLTiêu chí Api

  1. HQL là để thực hiện cả thao tác chọn và không chọn trên dữ liệu, nhưng Tiêu chí chỉ để chọn dữ liệu, chúng tôi không thể thực hiện các thao tác không chọn bằng tiêu chí.
  2. HQL phù hợp để thực hiện Truy vấn tĩnh, trong đó Tiêu chí phù hợp để thực hiện Truy vấn động
  3. HQL không hỗ trợ khái niệm phân trang , nhưng chúng ta có thể đạt được phân trang với Tiêu chí.
  4. Các tiêu chí được sử dụng để mất nhiều thời gian hơn để thực hiện hơn HQL.
  5. Với Tiêu chí, chúng tôi an toàn với SQL Injection vì tạo ra truy vấn động nhưng trong HQL vì các truy vấn của bạn là cố định hoặc được tham số hóa, không có sự an toàn nào từ SQL Injection

11
Một vài điểm Phân trang có trong HQL: bạn có thể sử dụng limit offset:rows Trong hql, bạn có thể tránh tiêm sql bằng cách sử dụngsetParameter
Viswanath Lekshmanan

13

Để sử dụng tốt nhất cả hai thế giới, tính biểu cảm và tính đồng nhất của HQL và bản chất động của Tiêu chí xem xét sử dụng Querydsl .

Querydsl hỗ trợ JPA / Hibernate, JDO, SQL và Bộ sưu tập.

Tôi là người duy trì Querydsl, vì vậy câu trả lời này là sai lệch.


13

Đối với tôi Tiêu chí là một điều khá dễ hiểu và thực hiện các truy vấn động. Nhưng lỗ hổng tôi nói cho đến nay là Nó tải tất cả các mối quan hệ nhiều người vì chúng tôi chỉ có ba loại FetchModes tức là Chọn, Proxy và Mặc định và trong tất cả các trường hợp này, nó tải nhiều người (có thể tôi sai nếu có trợ giúp tôi ra rồi :))

Vấn đề thứ hai với Tiêu chí là nó tải đối tượng hoàn chỉnh, tức là nếu tôi chỉ muốn tải EmpName của một nhân viên, thì nó sẽ không xuất hiện với đối tượng Nhân viên hoàn chỉnh và tôi có thể lấy EmpName từ nó vì nó thực sự hoạt động kém báo cáo . khi HQL chỉ tải (không tải liên kết / quan hệ) những gì bạn muốn để tăng hiệu suất nhiều lần.

Một tính năng của Tiêu chí là nó sẽ bảo vệ bạn khỏi SQL Injection do việc tạo truy vấn động của nó trong đó như trong HQL khi các truy vấn của bạn được cố định hoặc được tham số hóa nên không an toàn với SQL Injection.

Ngoài ra nếu bạn viết HQL trong các tệp ur aspx.cs, thì bạn được kết hợp chặt chẽ với DAL của bạn.

Nhìn chung, kết luận của tôi là có những nơi bạn không thể sống mà không có HQL như báo cáo nên sử dụng chúng khác Tiêu chí dễ quản lý hơn.


13
HQL KHÔNG phải là SQL tiêm an toàn
Varun Mehta

Tôi nghĩ rằng Tiêu chí không phải là tiêm an toàn. Xem bài đăng của tôi ở đây: stackoverflow.com/questions/6746486/ từ
Mister Smith

4
HQL IS sql tiêm an toàn bằng cách thêm 'setParameter'
Javatar

2
@Zafar: bạn chỉ có thể chọn một số thuộc tính nhất định của một thực thể bằng các phép chiếu
Răzvan Flavius ​​Panda

@Zafar bạn có thể đặt phép chiếu trong truy vấn tiêu chí để chọn các cột cụ thể. Bạn có thể tìm nạp EmpName, không cần tìm nạp đối tượng hoàn chỉnh.
Khatri

12

API tiêu chí

API tiêu chí phù hợp hơn cho các truy vấn được tạo động. Vì vậy, nếu bạn muốn thêm các bộ lọc mệnh đề WHERE, các mệnh đề THAM GIA hoặc thay đổi mệnh đề ORDER BY hoặc các cột chiếu, thì API Tiêu chí có thể giúp bạn tạo ra truy vấn một cách linh hoạt theo cách cũng ngăn chặn các cuộc tấn công SQL Injection .

Mặt khác, các truy vấn Tiêu chí ít biểu cảm hơn và thậm chí có thể dẫn đến các truy vấn SQL rất phức tạp và không hiệu quả, như được giải thích trong bài viết này .

JPQL và HQL

JPQL là ngôn ngữ truy vấn thực thể tiêu chuẩn JPA trong khi HQL mở rộng JPQL và thêm một số tính năng dành riêng cho Hibernate.

JPQL và HQL rất biểu cảm và giống với SQL. Không giống như API Tiêu chí, JPQL và HQL giúp dễ dàng dự đoán truy vấn SQL cơ bản do nhà cung cấp JPA tạo ra. Việc xem xét các truy vấn HQL của một người cũng dễ dàng hơn nhiều so với các truy vấn Tiêu chí.

Cần lưu ý rằng việc chọn các thực thể với JPQL hoặc API Tiêu chí có ý nghĩa nếu bạn cần sửa đổi chúng. Nếu không, một phép chiếu DTO là một lựa chọn tốt hơn nhiều.

Phần kết luận

Nếu bạn không cần thay đổi cấu trúc truy vấn thực thể, thì hãy sử dụng JPQL hoặc HQL. Nếu bạn cần thay đổi tiêu chí lọc hoặc sắp xếp hoặc thay đổi phép chiếu, thì hãy sử dụng API Tiêu chí.

Tuy nhiên, chỉ vì bạn đang sử dụng JPA hoặc Hibernate, điều đó không có nghĩa là bạn không nên sử dụng SQL gốc. Các truy vấn SQL rất hữu ích và JPQL và API Tiêu chí không phải là sự thay thế cho SQL. Kiểm tra bài viết này để biết thêm chi tiết về chủ đề này.



11

Đối với tôi, chiến thắng lớn nhất trên Tiêu chí là API mẫu, nơi bạn có thể vượt qua một đối tượng và ngủ đông sẽ xây dựng một truy vấn dựa trên các thuộc tính đối tượng đó.

Bên cạnh đó, API tiêu chí có những điểm kỳ quặc (tôi tin rằng nhóm ngủ đông đang làm lại api), như:

  • một tiêu chí.createAlias ​​("obj") buộc tham gia bên trong thay vì tham gia bên ngoài có thể
  • bạn không thể tạo cùng một bí danh hai lần
  • một số mệnh đề sql không có đối tác tiêu chí đơn giản (như một phần phụ)
  • Vân vân.

Tôi có xu hướng sử dụng HQL khi tôi muốn các truy vấn tương tự như sql (xóa khỏi Người dùng trong đó status = 'bị chặn') và tôi có xu hướng sử dụng các tiêu chí khi tôi không muốn sử dụng nối thêm chuỗi.

Một ưu điểm khác của HQL là bạn có thể xác định tất cả các truy vấn của mình trước khi sử dụng và thậm chí gửi chúng vào một tệp.


9

Api tiêu chí cung cấp một tính năng riêng biệt mà cả SQL hoặc HQL đều không cung cấp. I E. nó cho phép biên dịch thời gian kiểm tra một truy vấn.


7

Chúng tôi đã sử dụng chủ yếu Tiêu chí trong ứng dụng của mình ngay từ đầu nhưng sau đó nó đã được thay thế bằng HQL do các vấn đề về hiệu suất.
Chủ yếu chúng tôi đang sử dụng các truy vấn rất phức tạp với một số phép nối dẫn đến nhiều truy vấn trong Tiêu chí nhưng được tối ưu hóa rất nhiều trong HQL.
Trường hợp là chúng tôi chỉ sử dụng một số propeties trên các đối tượng cụ thể và không hoàn thành các đối tượng. Với Tiêu chí, vấn đề cũng là nối chuỗi.
Giả sử nếu bạn cần hiển thị tên và họ của người dùng trong HQL thì điều đó khá dễ dàng (name || ' ' || surname)nhưng trong Crteria thì điều này là không thể.
Để khắc phục điều này, chúng tôi đã sử dụng resultTransormers, trong đó có các phương pháp trong đó việc nối như vậy được thực hiện cho kết quả cần thiết.
Ngày nay chúng ta chủ yếu sử dụng HQL như thế này:

String hql = "select " +
            "c.uuid as uuid," +
            "c.name as name," +
            "c.objective as objective," +
            "c.startDate as startDate," +
            "c.endDate as endDate," +
            "c.description as description," +
            "s.status as status," +
            "t.type as type " +
            "from " + Campaign.class.getName() + " c " +
            "left join c.type t " +
            "left join c.status s";

Query query =  hibernateTemplate.getSessionFactory().getCurrentSession().getSession(EntityMode.MAP).createQuery(hql);
query.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
return query.list();

Vì vậy, trong trường hợp của chúng tôi, các bản ghi trả về là bản đồ của các thuộc tính cần thiết.


1
Với Tiêu chí, bạn có thể sử dụng org.hibernate.criterion.CriteriaSpecification.ALIAS_TO_ENTITY_MAP
AA.

Trả lại một danh sách các bản đồ theo kinh nghiệm của tôi có hiệu suất rất tệ. Tôi thích trả về một danh sách các mảng đối tượng hoặc một danh sách các bean (bạn luôn có thể xác định một bean phù hợp với tập kết quả cụ thể của bạn).
Lluis Martinez

7
  • HQL là để thực hiện cả thao tác chọn và không chọn trên dữ liệu, nhưng Tiêu chí chỉ để chọn dữ liệu, chúng tôi không thể thực hiện các thao tác không chọn bằng tiêu chí
  • HQL phù hợp để thực hiện Truy vấn tĩnh, trong đó Tiêu chí phù hợp để thực hiện Truy vấn động
  • HQL không hỗ trợ khái niệm phân trang, nhưng chúng ta có thể đạt được phân trang với Tiêu chí
  • Tiêu chí được sử dụng để mất nhiều thời gian hơn để thực hiện sau đó HQL
  • Với Tiêu chí, chúng tôi an toàn với SQL Injection do tạo ra truy vấn động nhưng trong HQL vì các truy vấn của bạn là cố định hoặc được tham số hóa, không có sự an toàn nào từ SQL Injection.

nguồn


Để làm rõ, các truy vấn tiêu chí sử dụng API Tiêu chí của Hibernate có thể có sẵn để truy vấn, nhưng các truy vấn tiêu chí JPA bao gồm các lựa chọn, cập nhật và xóa. Xem CriteriaUpdate<T>CriteriaDelete<T>để tham khảo.
Naros

5

Truy vấn tiêu chí cho động chúng ta có thể xây dựng truy vấn dựa trên đầu vào của mình..Trong trường hợp truy vấn Hql là truy vấn tĩnh một khi chúng ta xây dựng chúng ta không thể thay đổi cấu trúc của truy vấn.


2
Không phải vậy. Với HQL, bạn có thể đặt các thuộc tính bằng mã định danh ':', sau đó thay thế các thuộc tính đó bằng các giá trị duy nhất. Ví dụ: Truy vấn q = session.createQuery ("CHỌN: aValue TỪ my_table"); và sau đó q.setParameter ("aValue", "some_column_name");
MattC

@MattC Trong ví dụ của bạn, bạn đang thay đổi giá trị của tham số, không phải cấu trúc của truy vấn.
Sa hoàng

4

Tôi không muốn đá một con ngựa chết ở đây, nhưng điều quan trọng là phải đề cập rằng các truy vấn Tiêu chí hiện không được chấp nhận. Sử dụng HQL.


1

Tôi cũng thích Truy vấn tiêu chí cho các truy vấn động. Nhưng tôi thích hql để xóa các truy vấn, ví dụ: nếu xóa tất cả các bản ghi khỏi bảng con cho id cha 'xyz', thì HQL có thể dễ dàng đạt được, nhưng đối với API tiêu chí, trước tiên chúng ta phải thực hiện n số truy vấn xóa trong đó n là số con bảng ghi chép.


0

Hầu hết các câu trả lời ở đây là sai lệch và đề cập đến Criteria Querieschậm hơn HQL, đó thực sự không phải là trường hợp.

Nếu bạn đào sâu và thực hiện một số bài kiểm tra, bạn sẽ thấy Truy vấn tiêu chí thực hiện tốt hơn nhiều so với HQL thông thường .

Và cũng với Truy vấn tiêu chí, bạn có được điều khiển Hướng đối tượng không có ở đó với HQL .

Để biết thêm thông tin đọc câu trả lời này ở đây .


0

Có một cách khác. Tôi đã kết thúc với việc tạo một trình phân tích cú pháp HQL dựa trên cú pháp gốc ngủ đông để trước tiên nó phân tích cú pháp HQL sau đó nó có thể tự động chèn các tham số động hoặc tự động thêm một số bộ lọc phổ biến cho các truy vấn HQL. Nó hoạt động rất tốt!


0

Bài này khá cũ. Hầu hết các câu trả lời nói về tiêu chí Hibernate, không phải tiêu chí JPA. JPA 2.1 đã thêm CriteriaDelete / CriteriaUpdate và EntityGraph để kiểm soát chính xác những gì cần tìm nạp. API tiêu chí tốt hơn vì Java là OO. Đó là lý do tại sao JPA được tạo ra. Khi JPQL được biên dịch, nó sẽ được dịch sang cây AST (mô hình OO) trước khi dịch sang SQL.


-3

HQL có thể gây ra mối lo ngại về bảo mật như SQL tiêm.


11
Những vấn đề này không phải do HQL gây ra, mà do thiếu hiểu biết về thực tiễn phát triển phần mềm cơ bản. Tôi có thể tạo mã dễ bị tấn công sql với tiêu chí api là tốt.
Jens Schauder

1
Giống như nói "truy vấn RDBMS từ Java có thể gây ra mối lo ngại về bảo mật SQL": D
Czar
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.