Hibernate – Criteria Queries
Hibernate – Query Language (HQL) Hibenate cung cấp Criteria API chứa các phương thức cho phép bạn xây dựng một đối tượng truy vấn tiêu chuẩn theo yêu cầu của chương trình, nơi bạn có thể áp dụng các quy tắc lọc và điều kiện hợp lý. Giao tiếp Session trong Hibernate cung cấp ...
Hibenate cung cấp Criteria API chứa các phương thức cho phép bạn xây dựng một đối tượng truy vấn tiêu chuẩn theo yêu cầu của chương trình, nơi bạn có thể áp dụng các quy tắc lọc và điều kiện hợp lý.
Giao tiếp Session trong Hibernate cung cấp phương thức createCriteria() có thể được sử dụng để tạo một đối tượng Criteria mà trả về các thể hiện của lớp đối tượng persistence khi ứng dụng của bạn thi hành một truy vấn tiêu chuẩn.
Sau đây là ví dụ đơn giản nhất của một truy vấn tiêu chuẩn, chỉ đơn giản là trả về mọi đối tượng tương ứng với lớp Employee.
Criteria cr = session.createCriteria(Employee.class); List results = cr.list();
Restrictions với Criteria
Bạn có thể sử dụng phương thức add() có sẵn cho đối tượng Criteria để thêm các điều kiện lọc cho truy vấn tiêu chuẩn. Sau đây là ví dụ để bổ sung điều kiện để trả các record có salary là 2000:
Criteria cr = session.createCriteria(Employee.class); cr.add(Restrictions.eq("salary", 2000)); List results = cr.list();
Sau đây là một vài ví dụ khác bao gồm các kịch bản khác nhau và có thể được sử dụng theo từng yêu cầu:
Criteria cr = session.createCriteria(Employee.class); // Lấy các record có salary lớn hơn 2000 cr.add(Restrictions.gt("salary", 2000)); // Lấy các record có salary nhỏ hơn 2000 cr.add(Restrictions.lt("salary", 2000)); // Lấy các record có fistName bắt đầu là zara cr.add(Restrictions.like("firstName", "zara%")); // Dạng không phân biệt chữ hoa và chữ thường cho điều kiện trên. cr.add(Restrictions.ilike("firstName", "zara%")); // Lấy các record có salary trong khoảng 1000 và 2000 cr.add(Restrictions.between("salary", 1000, 2000)); // Check thuộc tính đã cho là null cr.add(Restrictions.isNull("salary")); // Check thuộc tính đã cho là khác null cr.add(Restrictions.isNotNull("salary")); // Check thuộc tính đã cho là empty cr.add(Restrictions.isEmpty("salary")); // Check thuộc tính đã cho là khác empty cr.add(Restrictions.isNotEmpty("salary"));
Bạn có thể tạo các điều kiện AND và OR sử dụng các hạn chế LogicExpression như sau:
Criteria cr = session.createCriteria(Employee.class); Criterion salary = Restrictions.gt("salary", 2000); Criterion name = Restrictions.ilike("firstNname","zara%"); // Lấy các record phù hợp với điều kiện OR LogicalExpression orExp = Restrictions.or(salary, name); cr.add(orExp); // Lấy các record phù hợp với điều kiện AND LogicalExpression andExp = Restrictions.and(salary, name); cr.add(andExp); List results = cr.list();
Tuy nhiên tất cả các điều kiện trên có thể được sử dụng trực tiếp với HQL như đã giải thích trong hướng dẫn trước.
Phân trang bằng việc sử dụng Criteria
Có hai phương thức của giao tiếp Criteria để phân trang.
No. | Phương thức & Mô tả |
---|---|
1 | public Criteria setFirstResult(int firstResult)
Phương thức này lấy một số nguyên đại diện cho hàng đầu tiên trong tập kết quả của bạn, bắt đầu với hàng 0. |
2 | public Criteria setMaxResults(int maxResults)
Phương thức này cho Hibernate tìm kiếm một số maxResults của các đối tượng. |
Sử dụng hai phương thức trên, chúng ta có thể xây dựng một thành phần phân trang trong ứng dụng Web hoặc Swing. Sau đây là ví dụ mà bạn có thể mở rộng để lấy 10 hàng một lúc:
Criteria cr = session.createCriteria(Employee.class); cr.setFirstResult(1); cr.setMaxResults(10); List results = cr.list();
Sắp xếp kết quả
Criteria API cung cấp lớp org.hibernate.criterion.Order để sắp xếp kết quả trả về theo thứ tự tăng dần hoặc giảm dần, theo một trong các thuộc tính của đối tượng. Ví dụ này thể hiện cách sử dụng lớp Order để sắp xếp tập kết quả:
Criteria cr = session.createCriteria(Employee.class); // Lấy các record có salary lớn hơn 2000 cr.add(Restrictions.gt("salary", 2000)); // Sắp xếp các record theo thứ tự giảm dần cr.addOrder(Order.desc("salary")); // Sắp xếp các record theo thứ tự tăng dần cr.addOrder(Order.asc("salary")); List results = cr.list();
Projections & Aggregations
Criteria API cung cấp lớp org.hibernate.criterion.Projections có thể được sử dụng để có được giá trị trung bình, maximum và minimum của các giá trị thuộc tính. Lớp Projections cũng tương tự như lớp Restrictions vì nó cung cấp một số phương thức static để lấy các thể hiện của lớp Projections.
Dưới đây là một số ví dụ về các trường hợp khác nhau và có thể được sử dụng theo từng yêu cầu:
Criteria cr = session.createCriteria(Employee.class); // Lấy tổng số hàng. cr.setProjection(Projections.rowCount()); // Lấy giá trị trung bình của một thuộc tính. cr.setProjection(Projections.avg("salary")); // Để có số lần xuất hiện duy nhât của một thuộc tính. cr.setProjection(Projections.countDistinct("firstName")); // Lấy giá trị maximum của một thuộc tính. cr.setProjection(Projections.max("salary")); // Lấy giá trị minimum của một thuộc tính. cr.setProjection(Projections.min("salary")); // Lấy tổng các giá trị của một thuộc tính cr.setProjection(Projections.sum("salary"));
Ví dụ về câu truy vấn Criteria
Tạo lớp Java POJO Employee.java
public class Employee { private int id; private String firstName; private String lastName; private int salary; public Employee() {} public Employee(String fname, String lname, int salary) { this.firstName = fname; this.lastName = lname; this.salary = salary; } public int getId() { return id; } public void setId( int id ) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName( String first_name ) { this.firstName = first_name; } public String getLastName() { return lastName; } public void setLastName( String last_name ) { this.lastName = last_name; } public int getSalary() { return salary; } public void setSalary( int salary ) { this.salary = salary; } }
Tạo bảng EMPLOYEE sau để lưu trữ các đối tượng Employee
create table EMPLOYEE ( id INT NOT NULL auto_increment, first_name VARCHAR(20) default NULL, last_name VARCHAR(20) default NULL, salary INT default NULL, PRIMARY KEY (id) );
Tạo file mapping XML
File: Employee.hbm.xml
<?xml version="1.0" encoding="utf-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <hibernate-mapping> <class name="vn.viettuts.hibernate.entity.Employee" table="EMPLOYEE"> <meta attribute="class-description"> Lớp này chưa thông tin chi tiết về employee. </meta> <id name="id" type="int" column="id"> <generator class="native" /> </id> <property name="firstName" column="first_name" type="string" /> <property name="lastName" column="last_name" type="string" /> <property name="salary" column="salary" type="int" /> </class> </hibernate-mapping>
Tạo lớp ứng dụng chứa phương thức main() để chạy ứng dụng nơi mà truy vấn Criteria được sử dụng
public class ManageEmployee { private static SessionFactory factory; public static void main(String[] args) { try{ factory = new Configuration().configure().buildSessionFactory(); }catch (Throwable ex) { System.err.println("Failed to create sessionFactory object." + ex); throw new ExceptionInInitializerError(ex); } ManageEmployee ME = new ManageEmployee(); // Add few employee records in database Integer empID1 = ME.addEmployee("Zara", "Ali", 2000); Integer empID2 = ME.addEmployee("Daisy", "Das", 5000); Integer empID3 = ME.addEmployee("John", "Paul", 5000); Integer empID4 = ME.addEmployee("Mohd", "Yasee", 3000); // List down all the employees ME.listEmployees(); // Print Total employee's count ME.countEmployee(); // Print Toatl salary ME.totalSalary(); } // Method to CREATE an employee in the database public Integer addEmployee(String fname, String lname, int salary){ Session session = factory.openSession(); Transaction tx = null; Integer employeeID = null; try{ tx = session.beginTransaction(); Employee employee = new Employee(fname, lname, salary); employeeID = (Integer) session.save(employee); tx.commit(); }catch (HibernateException e) { if (tx!=null) tx.rollback(); e.printStackTrace(); }finally { session.close(); } return employeeID; } // Method to READ all the employees having salary more than 2000 public void listEmployees( ){ Session session = factory.openSession(); Transaction tx = null; try{ tx = session.beginTransaction(); Criteria cr = session.createCriteria(Employee.class); // Add restriction. cr.add(Restrictions.gt("salary", 2000)); List employees = cr.list(); for (Iterator iterator = employees.iterator(); iterator.hasNext();){ Employee employee = (Employee) iterator.next(); System.out.print("First Name: " + employee.getFirstName()); System.out.print(" Last Name: " + employee.getLastName()); System.out.println(" Salary: " + employee.getSalary()); } tx.commit(); }catch (HibernateException e) { if (tx!=null) tx.rollback(); e.printStackTrace(); }finally { session.close(); } } // Method to print total number of records public void countEmployee(){ Session session = factory.openSession(); Transaction tx = null; try{ tx = session.beginTransaction(); Criteria cr = session.createCriteria(Employee.class); // To get total row count. cr.setProjection(Projections.rowCount()); List rowCount = cr.list(); System.out.println("Total Coint: " + rowCount.get(0) ); tx.commit(); }catch (HibernateException e) { if (tx!=null) tx.rollback(); e.printStackTrace(); }finally { session.close(); } } // Method to print sum of salaries public void totalSalary(){ Session session = factory.openSession(); Transaction tx = null; try{ tx = session.beginTransaction(); Criteria cr = session.createCriteria(Employee.class); // To get total salary. cr.setProjection(Projections.sum("salary")); List totalSalary = cr.list(); System.out.println("Total Salary: " + totalSalary.get(0) ); tx.commit(); }catch (HibernateException e) { if (tx!=null) tx.rollback(); e.printStackTrace(); }finally { session.close(); } } }
Kết quả chạy ứng dụng trên eclipse
First Name: Daisy Last Name: Das Salary: 5000 First Name: John Last Name: Paul Salary: 5000 First Name: Mohd Last Name: Yasee Salary: 3000 Total Coint: 4 Total Salary: 15000