ฟังก์ชันการจัดกลุ่มและการรวม

คุณทราบวิธีการส่งคำขออย่างง่ายไปยัง Criteria API แล้ว มาดูวิธีการสร้างแบบสอบถามที่ซับซ้อนมากขึ้น

ตัวอย่างเช่น เราต้องการเขียนแบบสอบถามเพื่อกำหนดจำนวนพนักงานในบริษัท นี่คือลักษณะของ HQL:

select count(*) from Employee

และเช่นนี้ใน Criteria API:

CriteriaQuery<Long> critQuery = builder.createQuery(Long.class);
critQuery.select(builder.count(critQuery.from(Employee.class)));

โค้ด Java ที่สมบูรณ์จะมีลักษณะดังนี้:

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();

และมันก็เหมือนกันโดยใช้ HQL:

String hqlQuery = "select count(*) from Employee";

Query<Long> query = session.createQuery(hqlQuery);
Long count = query.getSingleResult();

ทีนี้มาลองคำนวณเงินเดือนเฉลี่ยในบริษัทกัน แบบสอบถาม HQL จะมีลักษณะดังนี้:

select avg(salary) from Employee

และเช่นนี้ใน Criteria API:

CriteriaQuery<Double> critQuery = builder.createQuery(Double.class);
critQuery.select(builder.avg( critQuery.from(Employee.class).get("salary")));

โค้ด Java ที่สมบูรณ์จะมีลักษณะดังนี้:

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();

การปรับปรุงเกณฑ์

การแก้ไขตารางนั้นง่ายพอๆ กับการรับข้อมูลจากตาราง ในการทำเช่นนี้ CriteriaBuilder มีวิธีการพิเศษ - createCriteriaUpdate()ซึ่งสร้างวัตถุCriteriaUpdate<T>ที่ปรับปรุงเอนทิตีในฐานข้อมูล

ขอขึ้นเงินเดือนพนักงานที่รับต่ำกว่าหมื่น นี่คือลักษณะการสืบค้น HQL นี้:

update Employee set salary = salary+20000 where salary<=10000

และนี่คือลักษณะที่ปรากฏบน Criteria API:

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();

เกณฑ์การลบ

และการลบบันทึกนั้นง่ายยิ่งกว่าการเปลี่ยนแปลง ในการทำเช่นนี้ มีเมธอดพิเศษcreateCriteriaDelete()ซึ่งสร้างวัตถุCriteriaDelete<T>.

มาตัดพนักงานทุกคนที่ไม่มีค่า: เงินเดือนน้อยกว่า 10,000 นี่คือลักษณะการสืบค้น HQL นี้:

delete from Employee where salary<=10000

และนี่คือลักษณะที่ปรากฏบน Criteria API:

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();

ประโยชน์ของ Criteria API

แล้ว Criteria API มีประโยชน์อย่างไร? ข้อความค้นหามีความยุ่งยาก HQL จะกระชับมากขึ้นอย่างแน่นอน

ประการแรก การสืบค้น HQL นั้นไม่สั้นนักหากคุณต้องการส่งพารามิเตอร์ไปยังพวกเขา เปรียบเทียบ:

เราพิจารณาจำนวนพนักงานที่มีเงินเดือนน้อยกว่า 10,000 คน
HQL
String hqlQuery = "from Employee where salary < :sal";
Query<Employee> query = session.createQuery(hqlQuery);
query.setParametr("sal", 10000);
List<Employee> results = query.getResultList();
API เกณฑ์
CriteriaBuilder builder = session.getCriteriaBuilder();
critQuery.select(critQuery.from(Employee.class)).where(builder.lt(root.get("salary"), 10000));
Query<Employee> query = session.createQuery(critQuery);
List<Employee> results = query.getResultList();

ประการที่สอง บ่อยครั้งที่มีสถานการณ์ที่ต้องสร้างแบบสอบถามแบบไดนามิก ตัวอย่างเช่น คุณมีหน้าเว็บที่กรองข้อมูลพนักงาน อพาร์ทเมนต์ และอื่นๆ และหากพารามิเตอร์บางตัวไม่สำคัญสำหรับผู้ใช้ ผู้ใช้ก็จะไม่ระบุพารามิเตอร์นั้น ดังนั้น null จะถูกส่งผ่านไปยังเซิร์ฟเวอร์แทน

นี่คืองานของคุณ: เพื่อเลือกพนักงานที่มีอาชีพเฉพาะ (อาชีพ) เงินเดือน (เงินเดือน) และปีที่จ้าง (ปี (join_date)) แต่ถ้าค่าพารามิเตอร์ใดๆ เป็น null อย่าใช้ในตัวกรอง

จากนั้นแบบสอบถาม HQL จะมีลักษณะดังนี้:

from Employee
where (occupation = :ocp)
   	and (salary = :sal)
   	and ( YEAR(join_date) = :jny)

แต่มันจะทำงานไม่ถูกต้อง เนื่องจากเราต้องการให้พารามิเตอร์ "jny" เป็นโมฆะ คำขอจะมีลักษณะดังนี้:

from Employee
where (occupation = :ocp)
   	and (salary = :sal)

เราสามารถลองเขียนคำขอใหม่โดยตรวจสอบพารามิเตอร์เป็น null จากนั้นเราจะได้สิ่งนี้:

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)

ดูว่าความเป็นจริงซับซ้อนมากขึ้นอย่างไร? ความจริงมักเป็นเช่นนี้ :)

แต่ตัวกรองอาจมีความซับซ้อนมากยิ่งขึ้น ลองค้นหาผู้ใช้ที่มีงานที่มีคำว่า "ซื้อ" อยู่ในนั้นไหม หรือผู้ใช้ที่มีงานค้างชำระ?

from Employee
where (occupation = :ocp)
   	and (salary = :sal)
   	and (YEAR(join_date) = :jny)
   	and (tasks.name like '%buy%')
   	and (tasks.deadline < curdate())

หากคุณเขียน หรือเป็นโมฆะที่ใดที่หนึ่งในแบบสอบถามสิ่งนี้จะไม่ยกเลิกการรวมระหว่างตาราง

ดังนั้น ในทางปฏิบัติ เมื่อคุณทำตัวกรองที่ซับซ้อนในฟิลด์ของตารางหลายตาราง Criteria API สามารถช่วยคุณได้ ดังนั้นมันไป

สามารถดูรายละเอียดเพิ่มเติมได้ในเอกสารอย่างเป็นทางการ