Chức năng nhóm và tổng hợp
Bạn đã tìm ra cách thực hiện các yêu cầu đơn giản đối với API Tiêu chí. Hãy xem cách thực hiện các truy vấn phức tạp hơn.
Ví dụ, chúng ta muốn viết một truy vấn để xác định số lượng nhân viên trong một công ty. Đây là giao diện của nó trong HQL:
select count(*) from Employee
Và như thế này trên API tiêu chí:
CriteriaQuery<Long> critQuery = builder.createQuery(Long.class);
critQuery.select(builder.count(critQuery.from(Employee.class)));
Mã Java hoàn chỉnh sẽ trông như thế này:
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Long> critQuery = builder.createQuery(Long.class);
critQuery.select(builder.count(critQuery.from(Employee.class)));
Query<Long> query = session.createQuery(critQuery);
Long count = query.getSingleResult();
Và nó giống nhau khi sử dụng HQL:
String hqlQuery = "select count(*) from Employee";
Query<Long> query = session.createQuery(hqlQuery);
Long count = query.getSingleResult();
Bây giờ hãy thử tính mức lương trung bình trong công ty. Truy vấn HQL sẽ như thế này:
select avg(salary) from Employee
Và như thế này trên API tiêu chí:
CriteriaQuery<Double> critQuery = builder.createQuery(Double.class);
critQuery.select(builder.avg( critQuery.from(Employee.class).get("salary")));
Mã Java hoàn chỉnh sẽ trông như thế này:
CriteriaBuilder builder = session.getCriteriaBuilder();
CriteriaQuery<Double> critQuery = builder.createQuery(Double.class);
critQuery.select(builder.avg( critQuery.from(Employee.class).get("salary")));
Query<Double> query = session.createQuery(critQuery);
Double avgSalary = query.getSingleResult();
Tiêu chíCập nhật
Sửa đổi một bảng dễ dàng như lấy dữ liệu từ nó. Để làm điều này, CriteriaBuilder có một phương thức đặc biệt - createCriteriaUpdate() , tạo một đối tượngTiêu chíCập nhật<T>Cái cập nhật các thực thể trong cơ sở dữ liệu.
Hãy tăng lương cho những nhân viên nhận lương dưới 10 nghìn. Đây là giao diện của truy vấn HQL này:
update Employee set salary = salary+20000 where salary<=10000
Và đây là giao diện của API tiêu chí:
CriteriaUpdate<Employee> criteriaUpdate = builder.createCriteriaUpdate(Employee.class);
Root<Employee> root = criteriaUpdate.from(Employee.class);
criteriaUpdate.set("salary", "salary+20000");
criteriaUpdate.where(builder.lt(root.get("salary"), 10000));
Transaction transaction = session.beginTransaction();
session.createQuery(criteriaUpdate).executeUpdate();
transaction.commit();
Tiêu chíXóa
Và việc xóa các bản ghi thậm chí còn dễ dàng hơn việc thay đổi chúng. Để làm điều này, có một phương thức đặc biệt createCriteriaDelete() , tạo một đối tượngTiêu chíXóa<T>.
Hãy cắt giảm tất cả những nhân viên không có giá trị: lương của họ dưới 10 nghìn. Đây là giao diện của truy vấn HQL này:
delete from Employee where salary<=10000
Và đây là giao diện của API tiêu chí:
CriteriaDelete<Employee> criteriaDelete = builder.createCriteriaDelete(Employee.class);
Root<Employee> root = criteriaDelete.from(Employee.class);
criteriaDelete.where(builder.lt(root.get("salary"), 10000));
Transaction transaction = session.beginTransaction();
session.createQuery(criteriaDelete).executeUpdate();
transaction.commit();
Lợi ích của API tiêu chí
Vậy lợi ích của API tiêu chí là gì? Các truy vấn rất cồng kềnh, HQL chắc chắn sẽ gọn nhẹ hơn.
Thứ nhất, các truy vấn HQL không quá ngắn nếu bạn cần truyền tham số cho chúng. So sánh:
Chúng tôi xem xét số lượng nhân viên có mức lương dưới 10 nghìn |
---|
HQL |
|
API tiêu chí |
|
Thứ hai, rất thường xảy ra tình huống khi một truy vấn cần được xây dựng động. Ví dụ: bạn có một trang web lọc nhân viên, căn hộ và mọi thứ. Và nếu một số tham số không quan trọng đối với người dùng, thì anh ta chỉ đơn giản là không chỉ ra nó. Theo đó, thay vào đó, null được chuyển đến máy chủ.
Đây là nhiệm vụ của bạn: chọn nhân viên có một nghề nhất định (nghề nghiệp), tiền lương (tiền lương) và năm làm việc (NĂM (join_date)). Nhưng nếu bất kỳ giá trị tham số nào là null, thì đừng sử dụng nó trong bộ lọc.
Sau đó, truy vấn HQL sẽ giống như thế này:
from Employee
where (occupation = :ocp)
and (salary = :sal)
and ( YEAR(join_date) = :jny)
Nhưng nó sẽ không hoạt động chính xác, vì chúng tôi muốn rằng nếu tham số "jny" là null, thì yêu cầu sẽ như sau:
from Employee
where (occupation = :ocp)
and (salary = :sal)
Chúng ta có thể thử viết lại yêu cầu bằng cách kiểm tra tham số null, sau đó chúng ta sẽ nhận được kết quả như sau:
from Employee
where (occupation = :ocp or :ocp is null)
and (salary = :sal or :sal is null)
and ( YEAR(join_date)= :jny or :jny is null)
Xem làm thế nào thực tế trở nên phức tạp hơn? Thực tế thường là như vậy :)
Nhưng bộ lọc có thể phức tạp hơn nữa. Làm thế nào về việc tìm kiếm những người dùng có nhiệm vụ với từ "mua" trong đó? Hoặc người dùng có nhiệm vụ quá hạn?
from Employee
where (occupation = :ocp)
and (salary = :sal)
and (YEAR(join_date) = :jny)
and (tasks.name like '%buy%')
and (tasks.deadline < curdate())
Nếu bạn viết hoặc là null ở đâu đó trong một truy vấn như vậy , thì điều này sẽ không hủy phép nối giữa các bảng.
Vì vậy, trong thực tế, khi bạn thực hiện bất kỳ bộ lọc phức tạp nào trên các trường của một số bảng, API Tiêu chí có thể giúp bạn giải quyết. Vì vậy, nó đi.
Thông tin chi tiết có thể được tìm thấy trong tài liệu chính thức .