post-image

Hibernate – Interceptors

JDBC & Hibernate

Như bạn đã biết rằng trong Hibernate, một đối tượng sẽ được tạo ra và tồn tại. Khi đối tượng đã được tay đổi, nó phải được lưu lại tại database. Quá trình này tiếp tục cho đến lần tiếp theo đối tượng là cần thiết và nó sẽ được tải lại kho lưu trữ liên tục.

Do đó, một đối tượng đi qua các giai đoạn khác nhau trong một vòng đời của nó và Interceptor Interface cung cấp các phương thức, có thể được gọi ở các giai đoạn khác nhau để thực hiện một số tác vụ được yêu cầu. Các phượng thức này là các lệnh gọi lại từ phiên đến ứng dụng, cho phép ứng dụng kiểu tra and/or các thuộc tính của đối tượng liên tục trước khi nó lưu, cập nhật, xóa hoặc tải lại. Sau đây là danh sách tất cả các phương thức có sẵn trong Interceptor Interface

STTPhương thức và mô tả
1findDirty()
Phương thức này đưuọc gọi khi phương thức flush() được gọi trên một đối tượng Session.
2instantiate()
Phương thức này được gọi khi một lớp persisted được khởi tạo.
3isUnsaved()
Phương thức này được gọi khi một đối tượng chuyển đến phương thức saveOrUpdate()
4onDelete()
Phương thức này được gọi trước khi một đối tượng bị xóa.
5onFlushDirty()
Phương thức này được gọi khi Hibernate phát hiện thấy một đối tượng bị bẩn (tức là đã bị thay đổi) trong quá trình flush tức là đang cập nhật.
6onLoad()
Phương thức này được gọi trước khi một đối tượng được khởi tạo.
7onSave()
Phương thức này được gọi trước khi một đối tượng được lưu.
8postFlush()
Phương thức này đợc gọi sau khi flush và một đối tựogn được cập nhật bộ nhớ.
9preFlush()
Phương thức này được gọi trước khi flush.

Hibernate Interceptor cho chúng ta toàn quyền kiểm soát cách một đối tượng sẽ trông như thế nào đối với cả ứng dụng và cơ sở dữ liệu.

Làm thế nào để sử dụng Interceptors?

Để xây dựng một interceptor, bạn có thể implement trực tiếp lớp Interceptor hoặc extend lớp EmptyInterceptor. Sau đây sẽ là các bước đơn giản để sử dụng chức năng Hibernate Interceptor.

Tạo Interceptors

Mình sẽ extend EmotyInterceptor trong ví dụ dưới, nơi phương thức của Interceptor sẽ được gọi tự động khi đối tượgng Employee được tạo và cập nhật. Bạn có thể implement nhiều phương thức hơn theo yêu cầu của bạn.

import java.io.Serializable;
import java.util.Date;
import java.util.Iterator;

import org.hibernate.EmptyInterceptor;
import org.hibernate.Transaction;
import org.hibernate.type.Type;

public class MyInterceptor extends EmptyInterceptor {
   private int updates;
   private int creates;
   private int loads;

   public void onDelete(Object entity, Serializable id,
      Object[] state, String[] propertyNames, Type[] types) {
       // do nothing
   }

   // This method is called when Employee object gets updated.
   public boolean onFlushDirty(Object entity, Serializable id,
      Object[] currentState, Object[] previousState, String[] propertyNames,
      Type[] types) {
         if ( entity instanceof Employee ) {
            System.out.println("Update Operation");
            return true; 
         }
         return false;
   }
	
   public boolean onLoad(Object entity, Serializable id,
      Object[] state, String[] propertyNames, Type[] types) {
         // do nothing
         return true;
   }
   
   // This method is called when Employee object gets created.
   public boolean onSave(Object entity, Serializable id,
      Object[] state, String[] propertyNames, Type[] types) {
         if ( entity instanceof Employee ) {
            System.out.println("Create Operation");
            return true; 
         }
         return false;
   }
   
   //called before commit into database
   public void preFlush(Iterator iterator) {
      System.out.println("preFlush");
   }
   
   //called after committed into database
   public void postFlush(Iterator iterator) {
      System.out.println("postFlush");
   }
}Code language: JavaScript (javascript)

Tạo POJO Classes

POJO hay POJOs là từ viết tắt của của cụm từ “Plain Old Java 0bject” trong tiếng Anh hay nó có ý nghĩa là “Các đối tượng Java thuần túy”.

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;
   }
}Code language: JavaScript (javascript)

Tạo Database Tables

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)
);Code language: PHP (php)

Tạo Mapping Configuration File

<?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 = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </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>Code language: HTML, XML (xml)

Tạo Application Class

import java.util.List; 
import java.util.Date;
import java.util.Iterator; 
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

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", 1000);
      Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
      Integer empID3 = ME.addEmployee("John", "Paul", 10000);

      /* List down all the employees */
      ME.listEmployees();

      /* Update employee's records */
      ME.updateEmployee(empID1, 5000);

      /* Delete an employee from the database */
      ME.deleteEmployee(empID2);

      /* List down new list of the employees */
      ME.listEmployees();
   }
   
   /* Method to CREATE an employee in the database */
   public Integer addEmployee(String fname, String lname, int salary){
      Session session = factory.openSession( new MyInterceptor() );
      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 */
   public void listEmployees( ){
      Session session = factory.openSession( new MyInterceptor() );
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         List employees = session.createQuery("FROM Employee").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 UPDATE salary for an employee */
   public void updateEmployee(Integer EmployeeID, int salary ){
      Session session = factory.openSession( new MyInterceptor() );
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         employee.setSalary( salary );
		 session.update(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to DELETE an employee from the records */
   public void deleteEmployee(Integer EmployeeID){
      Session session = factory.openSession( new MyInterceptor() );
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         session.delete(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
}Code language: JavaScript (javascript)

Compilation and Execution

Dưới đây là các bước để biên dịch và chạy ứng dụng được đề cập ở trên. Đảm bảo rằng bạn đã đặt PATH và CLASSPATH thích hợp trước khi tiến hành biên dịch và thực thi.

  • Tạo file cấu hình hibernate.cfg.xml như được giải thích trong phần cấu hình
  • Tạo tệp mapping Employee.hbm.xml như hình trên.
  • Tạo tệp nguồn Employee.java như hình trên và biên dịch nó.
  • Tạo tệp nguồn MyInterceptor.java như được hiển thị ở trên và biên dịch nó.
  • Tạo tệp nguồn ManageEaffee.java như được hiển thị ở trên và biên dịch nó.
  • Thực thi lệnh nhị phân ManageE Jobee để chạy chương trình.

Bạn sẽ nhận được kết quả sau và các bản ghi sẽ được tạo trong bảng EMPLOYEE .

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........

Create Operation
preFlush
postFlush
Create Operation
preFlush
postFlush
Create Operation
preFlush
postFlush
First Name: Zara  Last Name: Ali  Salary: 1000
First Name: Daisy  Last Name: Das  Salary: 5000
First Name: John  Last Name: Paul  Salary: 10000
preFlush
postFlush
preFlush
Update Operation
postFlush
preFlush
postFlush
First Name: Zara  Last Name: Ali  Salary: 5000
First Name: John  Last Name: Paul  Salary: 10000
preFlush
postFlushCode language: PHP (php)

Nếu bạn kiểm tra bảng EMPLOYEE  của mình, bảng này sẽ có các bản ghi sau:

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 29 | Zara       | Ali       |   5000 |
| 31 | John       | Paul      |  10000 |
+----+------------+-----------+--------+
2 rows in set (0.00 sec
mysql>Code language: JavaScript (javascript)

Nguồn:

https://www.tutorialspoint.com/hibernate/hibernate_interceptors.htm

Bài viết liên quan:

https://hocspringboot.net/2021/05/10/tai_sao_nen_dung_hibernate_thay_vi_jdbc/

Leave a Reply

Your email address will not be published. Required fields are marked *