11/08/2018, 18:55

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 ...

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 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

Download Source Code Eclipse

Bài tiếp theo: Native SQL trong Hibernate
Hibernate – Query Language (HQL)
0