La Kiến Vinh Criteria cho phép lập trình viên xây dựng câu truy vấn vào cơ sở dữ liệu nhanh chóng mà không mất nhiều thời gian. Kết hợp với Restriction và Projection, các câu truy vấn trong Hibernate sẽ gắn gọn và tối ưu hơn.
Nội dung bài viết

Giới thiệu

Trong các ứng dụng kết nối cơ sở dữ liệu, việc xây dựng câu truy vấn hay query, là điều cực kỳ quan trọng vì chúng sẽ giúp tăng tốc độ tải dữ liệu của ứng dụng. Framework Hibernate cho phép chúng ta viết câu truy vấn bằng "code" thay vì phải gõ các mệnh đề như Select, From,.. bằng API mang tên Criteria. Điều này sẽ giúp lập trình viên tiết kiệm thời gian khi thao tác với cơ sở dữ liệu và tránh được các lỗi cú pháp.

Câu truy vấn cơ bản

Thông thường, để viết một câu truy vấn "Lấy tất cả đối tượng trong lớp Articles", chúng ta có thể làm như sau.

String hql = "FROM Articles";
Query query = session.createQuery(hql);
List results = query.list();

Đoạn code trên sẽ lấy tất cả đối tượng (dòng) trong lớp Articles và trả về cho results. Với Criteria, chúng ta có thể "code" câu truy vấn mà không cần đến FROM như sau.

Criteria ctr = session.createCriteria(Articles.class);
List results = ctr.list();

Đoạn code với Criteria sẽ cho cùng kết quả là tất cả đối tượng có trong lớp Articles, nhưng tiết kiệm thời gian và lập trình viên sẽ không cần ghi đầy đủ câu truy vấn.

Restrictions - Điều kiện

Để lấy các đối tượng trong lớp Articles có số views lớn hơn 10.000, ta có thể làm như sau.

String hql = "FROM Articles WHERE Articles.views > 10000";
Query query = session.createQuery(hql);
List results = query.list();

Nếu sử dụng Criteria, điều kiện WHERE có thể được viết lại dễ hiểu hơn cho lập trình viên.

Criteria ctr = session.createCriteria(Articles.class);
ctr.add(Restrictions.gt("views", 10000));
List results = ctr.list();

Hàm add(Criterion ctn) sẽ thêm một điều kiện vào query của chúng ta, với Restrictions là lớp con chứa các phép so sánh cần thiết. Ở đoạn code trên, query sử dụng Restrictions.gtGreater Than, sẽ lấy các đối tượng thuộc lớp Articles có thuộc tính được khai báo là views có giá trị lớn hơn 10000.

Với cách làm này, câu truy vấn tuy không thể hiện rõ như SQL hay cách viết SELECT - FROM, nhưng sẽ giúp lập trình viên dễ kiểm soát và bảo trì khi có sự cố xảy ra.

Dưới đây là bảng các Restrictions.

Restriction Description Example
Restrictions.gt Greater Than - giá trị so sánh phải lớn hơn số X ctr.add(Restrictions.gt("views", 10000));
Restrictions.lt Less Than - giá trị so sánh phải nhỏ hơn số X ctr.add(Restrictions.lt("views", 10000));
Restrictions.like Tìm đối tượng có giá trị tương đương, giống nhau, không phân biệt hoa thường ctr.add(Restrictions.like("title", "HQL", MatchMode.ANYWHERE));
Restrictions.ilike Tương tự like, nhưng có phân biệt hoa thường ctr.add(Restrictions.ilike("title", "HqL", MatchMode.ANYWHERE));
Restrictions.between Giá trị phải trong khoảng X và Y ctr.add(Restrictions.between("views", 5000, 10000));
Restrictions.isNull Kiểm tra thuộc tính NULL hay không ctr.add(Restrictions.isNull("date_created"));
Restrictions.isNotNull Kiểm tra thuộc tính có khác NULL hay không ctr.add(Restrictions.isNotNull("date_created"));
Restrictions.isEmpty Kiểm tra thuộc tính có rỗng hay không ctr.add(Restrictions.isEmpty("title"));
Restrictions.isNotEmpty Kiểm tra thuộc tính có khác rỗng hay không ctr.add(Restrictions.isNotEmpty("title"));
Restrictions.and Kết hợp AND giữa các điều kiện Sẽ giải thích thêm ở mục tiếp theo
Restrictions.or Kết hợp OR giữa các điều kiện Sẽ giải thích thêm ở mục tiếp theo

AND/OR

Để sử dụng And/Or trong câu truy vấn, chúng ta sử dụng LogicalExpression.

Criteria ctr = session.createCriteria(Articles.class);
Criterion views = Restriction.gt("views", 10000);
Criterion comments = Restriction.gt("comments", 10);

LogicalExpression andExp = Restrictions.and(views, comments);
ctr.add(andExp);

LogicalExpression orExp = Restrictions.or(views, comments);
ctr.add(orExp);
List results = ctr.list();

Khác với các ví dụ trước, khi sử dụng LogicalExpression, chúng ta không add trực tiếp điều kiện về viewscomments mà sẽ kết hợp chúng lại bằng Restrictions.and hoặc Restrictions.or, sau đó mới add Restriction này vào ctr.

Paging - Chia trang

Chúng ta sẽ sử dụng hàm setFirstResultsetMaxResults được cung cấp bởi lớp Criteria.

Criteria ctr = session.createCriteria(Articles.class);
ctr.setFirstResult(11);
ctr.setMaxResults(20);
List results = ctr.list();

Câu truy vấn sẽ lấy đối tượng từ vị trí thứ 11 đến 20 (trang 2, mỗi trang 10 kết quả).

Sorting - Sắp xếp

Để sắp xếp các kết quả của truy vấn, chúng ta sử dụng addOrder(), với tham số là Order.desc() hoặc Order.asc().

Criteria ctr = session.createCriteria(Articles.class);
ctr.add(Restrictions.gt("views", 10000));
ctr.addOrder(Order.desc("views"));
List results = ctr.list();

Để thêm nhiều Order, chúng ta chỉ việc ghi như sau.

ctr.addOrder(Order.desc("views"));
ctr.addOrder(Order.desc("comments"));

Hàm tính toán

Tương tự với Restrictions, chúng ta có thể thêm các phép tính với giá trị vào câu truy vấn sử dụng setProjection.

Criteria ctr = session.createCriteria(Articles.class);
ctr.setProjection(Projections.rowCount());
List results = ctr.list();

if (!results.isEmpty()) {
    Integer rowCount = (Integer) results.get(0);
    System.out.println("Number of rows: " + rowCount);
}

Projections.rowCount() sẽ đếm số đối tượng có trong lớp Articles và trả về một object Integer trong list.

Dưới đây là bảng các Projection khác.

Projection Description Example
Projections.rowCount Đếm tổng số đối tượng (dòng) trong lớp ctr.setProjection(Projections.rowCount());
Projections.avg Tính trung bình giá trị của thuộc tính (cột) ctr.setProjection(Projections.avg("views"));
Projections.countDistinct Đếm số đối tượng (không trùng lắp) trong lớp ctr.setProjection(Projections.countDistinct("author"));
Projections.max Lấy giá trị lớn nhất của thuộc tính ctr.setProjection(Projections.max("views"));
Projections.min Lấy giá trị nhỏ nhất của thuộc tính ctr.setProjection(Projections.min("views"));
Projections.sum Tính tổng các giá trị trong thuộc tính ctr.setProjection(Projections.sum("views"));
THẢO LUẬN
Trong một thời gian dài tôi băn khoăn không hiểu cái gì có thể cực đắt, cực hiện đại, có thể cực kì vô dụng. Và rồi tôi phát hiện ra máy tính là một cái máy ngu ngốc có khả năng làm những việc thông minh phi thường, trong khi lập trình viên là những người thông minh có khả năng làm những việc ngu ngốc phi thường. Bill Bryson
ĐÓNG