Bài viết được sự cho phép của tác giả Giang Phan
Trong bài trước, chúng ta đã cùng tìm hiểu về cách sử dụng Hibernate Query Language (HQL) để truy vấn cơ sở dữ liệu và nhận kết quả. Trong bài này, chúng ta sẽ cùng tìm hiểu về Hibernate Criteria Query Language – một cách khác để lấy dữ liệu dựa vào các tiêu chí (Criteria) cụ thể.
Giới hiệu Hibernate Criteria Query Language (HCQL)
Hibernate Criteria API cung cấp cách tiếp cận hướng đối tượng để truy vấn cơ sở dữ liệu và nhận kết quả. Criteria cho phép chúng ta xây dựng câu lệnh một cách linh động (dynamic) và không bị hardcode trong một chuỗi truy vấn và có thể tái sử dụng.
Một số trường hợp sử dụng phổ biến của Hibernate Criteria Query:
- Sử dụng các hàm tập hợp như sum(), min(), max(), …
- Truy vấn một vài column cụ thể.
- Sử dụng để join nhiều table với nhau.
- Giới hạn dữ liệu được trả về.
- Sắp xếp (Order) kết quả trả về.
- Phân trang (Paging).
Tương tự như HQL, để tạo đối tượng Criteria chúng ta sẽ sử dụng phương thức getCriteriaBuilder() từ đối tượng Session và tạo đối tượng Criteria: CriteriaQuery, createCriteriaUpdate, createCriteriaDelete.
1
2
3
4
5
|
<T> javax.persistence.criteria.CriteriaQuery<T> createQuery(java.lang.Class<T> aClass); <T> javax.persistence.criteria.CriteriaUpdate<T> createCriteriaUpdate(java.lang.Class<T> aClass); <T> javax.persistence.criteria.CriteriaDelete<T> createCriteriaDelete(java.lang.Class<T> aClass); |
Ví dụ sử dụng Hibernate Criteria Query Language (HCQL)
Chúng ta sẽ sử dụng lại cơ sở dữ liệu ở bài viết trước để thực hiện các truy vấn với Criteria.
Lấy 1 đối tượng
Ví dụ lấy user có id là 1.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
try (Session session = HibernateUtils.getSessionFactory().openSession();) { // Begin a unit of work session.beginTransaction(); CriteriaBuilder builder = session.getCriteriaBuilder(); CriteriaQuery<User> query = builder.createQuery(User. class ); Root<User> root = query.from(User. class ); // FROM User u query.select(root); // SELECT query.where(builder.equal(root.get( "id" ), 1 )); // WHERE u.id = 1 User user = session.createQuery(query).uniqueResult(); // Commit the current resource transaction, writing any unflushed changes to the database. session.getTransaction().commit(); } |
Lấy danh sách với paging và ordering
Ví dụ lấy danh sách user có id >= 1 và id <= 1000. Sắp xếp danh sách này theo ngày tạo giảm dần, tên tăng dần. Lấy từ 5 user bắt đầu từ vị trí thứ 10.
1
2
3
4
5
6
7
8
9
10
|
CriteriaBuilder builder = session.getCriteriaBuilder(); CriteriaQuery<User> query = builder.createQuery(User. class ); Root<User> root = query.from(User. class ); // FROM query.select(root); // SELECT query.where(builder.and(builder.ge(root.get( "id" ), 1 ), builder.le(root.get( "id" ), 1000 ))); // WHERE id >= 1 AND id <= 1000 query.orderBy(builder.desc(root.get( "createdAt" )), builder.desc(root.asc( "fullname" ))); // ORDER BY createdAt DESC, fullname ASC List<User> users = session.createQuery(query) .setFirstResult( 10 ) .setMaxResults( 5 ) .getResultList(); |
Lấy một column (Selecting an expression)
Ví dụ lấy tất cả email của user.
1
2
3
4
5
|
CriteriaBuilder builder = session.getCriteriaBuilder(); CriteriaQuery<String> query = builder.createQuery(String. class ); Root<User> root = query.from(User. class ); // FROM query.select(root.get( "fullname" )); // SELECT fullname List<String> fullnames = session.createQuery(query).getResultList(); |
Lấy nhiều column (Selecting multiple values)
1
2
3
4
5
|
CriteriaBuilder builder = session.getCriteriaBuilder(); CriteriaQuery<Object[]> query = builder.createQuery(Object[]. class ); Root<User> root = query.from(User. class ); // FROM query.multiselect(root.get( "fullname" ), root.get( "username" )); // SELECT fullname, username List<Object[]> users = session.createQuery(query).getResultList(); |
Lấy nhiều column sử dụng Wrapper (Selecting a wrapper)
Thay vì trả về list Object[], chúng ta có thể trả về List POJO class như sau:
- Tạo class mới, chứa các cột trả về.
- Sử dụng phương thức construct của CriteriaBuilder để gán giá trị tương ứng cho wrapper class.
Chẳng hạn, cần lấy 2 column là fullname và username
1
2
3
4
5
6
|
@Data @AllArgsConstructor class BaseUser { private String fullname; private String username; } |
1
2
3
4
5
|
CriteriaBuilder builder = session.getCriteriaBuilder(); CriteriaQuery<BaseUser> query = builder.createQuery(BaseUser. class ); Root<User> root = query.from(User. class ); // FROM query.select( builder.construct( BaseUser. class , root.get( "fullname" ), root.get( "username" ) ) ); // SELECT fullname, username List<BaseUser> users = session.createQuery(query).getResultList(); |
Sử dụng hàm tập hợp (Aggregate Functions)
Ví dụ đếm số lượng user được tạo theo tháng.
1
2
3
4
5
6
7
8
9
10
|
CriteriaBuilder builder = session.getCriteriaBuilder(); CriteriaQuery<Object[]> query = builder.createQuery(Object[]. class ); Root<User> root = query.from(User. class ); Expression<Long> groupByExp = builder.function( "month" , Long. class , root.get( "createdAt" )).as(Long. class ); Expression<Long> countExp = builder.count(root.get( "id" )); query.multiselect(groupByExp, countExp); query.groupBy(groupByExp); query.having(builder.gt(builder.count(root), 3 )); //ordering by count in descending order query.orderBy(builder.desc(countExp)); |
Truy vấn nhiều bảng (join)
Ví dụ: lấy thông tin user và user profile.
1
2
3
4
5
|
CriteriaBuilder builder = session.getCriteriaBuilder(); CriteriaQuery<User> query = builder.createQuery(User. class ); Root<User> root = query.from(User. class ); // FROM Join<User, UserProfile> userJoin = root.join( "userProfile" , JoinType.LEFT); List<User> users = session.createQuery(query).getResultList(); |
Một số bất lợi khi sử dụng của Criteria
Như bạn thấy, Query với Criteria khá đơn giản. Tuy nhiên, nó có một số vấn đề sau chúng ta cần xem xét trước khi sử dụng:
- Performance issue: Chúng ta không có cách nào để kiểm soát truy vấn SQL do Hibernate tạo ra, nếu truy vấn được tạo chậm, ta rất khó điều chỉnh truy vấn.
- Maintenace issue: Tất cả các truy vấn SQL được phân tán thông qua mã code Java, khi một truy vấn bị lỗi, có thể dành thời gian để tìm truy vấn gây ra vấn đề trong ứng dụng của mình.
Không có gì là hoàn hảo, hãy xem xét nhu cầu dự án của mình và sử dụng nó một cách phù hợp. Đó cũng là một trong những lý dó mà Hibernate support nhiều loại truy vấn khác nhau.
Tài liệu tham khảo:
Bài viết gốc được đăng tải tại gpcoder.com
Có thể bạn quan tâm:
Xem thêm Việc làm IT hấp dẫn trên TopDev