ฟังก์ชันการจัดกลุ่มและการรวม
คุณทราบวิธีการส่งคำขออย่างง่ายไปยัง 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 |
|
API เกณฑ์ |
|
ประการที่สอง บ่อยครั้งที่มีสถานการณ์ที่ต้องสร้างแบบสอบถามแบบไดนามิก ตัวอย่างเช่น คุณมีหน้าเว็บที่กรองข้อมูลพนักงาน อพาร์ทเมนต์ และอื่นๆ และหากพารามิเตอร์บางตัวไม่สำคัญสำหรับผู้ใช้ ผู้ใช้ก็จะไม่ระบุพารามิเตอร์นั้น ดังนั้น 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 สามารถช่วยคุณได้ ดังนั้นมันไป
สามารถดูรายละเอียดเพิ่มเติมได้ในเอกสารอย่างเป็นทางการ