Interceptor trong Hibernate
Batch processing trong Hibernate Như bạn đã biết được rằng trong Hibernate, một đối tượng sẽ được tạo ra và tồn tại. Một khi đối tượng đã được thay đổi, nó phải được lưu trở lại cơ sở dữ liệu. Quá trình này tiếp tục cho đến khi đối tượng tiếp theo được yêu cầu, và nó sẽ được tải từ ...
Như bạn đã biết được rằng trong Hibernate, một đối tượng sẽ được tạo ra và tồn tại. Một khi đối tượng đã được thay đổi, nó phải được lưu trở lại cơ sở dữ liệu. Quá trình này tiếp tục cho đến khi đối tượng tiếp theo được yêu cầu, và nó sẽ được tải từ các persistent store.
Do đó, một đối tượng đi qua các giai đoạn khác nhau trong vòng đời của nó. Giao tiếp Interceptor trong Hibernate 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ố nhiệm vụ được yêu cầu. Các phương thức này là gọi lại từ session tới ứng dụng, cho phép ứng dụng kiểm tra và/hoặc thao tác các thuộc tính của một đối tượng persistent trước khi nó được lưu, cập nhật, xóa hoặc nạp. Sau đây là danh sách tất cả các phương thức có sẵn trong Interceptor Interface:
No. | Phương thức và mô tả |
---|---|
1 | findDirty()
Phương thức này được gọi khi phương thức flush() được gọi trên một đối tượng Session. |
2 | instantiate()
Phương thức này được gọi khi một lớp persistent được khởi tạo. |
3 | isUnsaved()
Phương thức này được gọi khi một đối tượng được truyền vào phương thức saveOrUpdate() / |
4 | onDelete()
Phương thức này được gọi trước khi một đối tượng bị xóa. |
5 | onFlushDirty()
Phương thức này được gọi khi Hibernate phát hiện ra rằng một đối tượng là dirty(tức là đã được thay đổi) trong quá trình flush nghĩa là thao tác update. |
6 | onLoad()
Phương thức này được gọi trước khi một đối tượng được khởi tạo. |
7 | onSave()
Phương thức này được gọi trước khi một đối tượng được lưu. |
8 | postFlush()
Phương thức này được gọi sau khi flush và một đối tượng đã được update trong bộ nhớ. |
9 | preFlush()
Phương thức này được gọi trước một flush. |
Hibernate Interceptor cho phép chúng ta kiểm soát toàn diện đối tượng trong cả ứng dụng và cơ sở dữ liệu.
Ví dụ về Interceptor trong Hibernate
Để xây dựng một interceptor bạn có thể impliments lớp Interceptor trực tiếp hoặc extents lớp EmptyInterceptor. Sau đây là các bước đơn giản để sử dụng chức năng Interceptor trong Hibernate.
Tạo các Interceptor
Tạo lớp MyInterceptor kế thừa EmptyInterceptor nơi phương thức của Interceptor sẽ được gọi tự động khi đối tượng Employee được tạo ra và cập nhật. Bạn có thể thực hiện nhiều phương thức hơn theo yêu cầu của bạn.
import java.io.Serializable; import java.util.Iterator; import org.hibernate.EmptyInterceptor; import org.hibernate.type.Type; import hibernate.interceptor.entity.Employee; public class MyInterceptor extends EmptyInterceptor { 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"); } }
Tạo lớp POJO
File: Employee.java
package hibernate.interceptor.entity; 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 cơ sở dữ liệu
Bước thứ hai, tạo các bảng trong cơ sở dữ liệu. Sẽ có một bảng tương ứng với mỗi đối tượng mà bạn sẵn sàng cung cấp persistent. Các đối tượng trên cần phải được lưu trữ và truy xuất vào bảng RDBMS sau:
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
Bước này tạo ra một file ánh xạ hướng dẫn Hibernate làm thế nào để ánh xạ các lớp hoặc các lớp đã định nghĩa vào các bảng cơ sở dữ liệu.
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="hibernate.interceptor.entity.Employee" table="EMPLOYEE"> <meta attribute="class-description"> Lớp này chứa 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 file cấu hình Hibernate
File: hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration SYSTEM "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.dialect"> org.hibernate.dialect.MySQLDialect </property> <property name="hibernate.connection.driver_class"> com.mysql.jdbc.Driver </property> <property name="hibernate.connection.url"> jdbc:mysql://localhost/testdb </property> <property name="hibernate.connection.username"> root </property> <property name="hibernate.connection.password"> 1234567890 </property> <mapping resource="Employee.hbm.xml" /> </session-factory> </hibernate-configuration>
Tạo lớp ứng dụng
Cuối cùng, chúng ta sẽ tạo lớp chứa phương thức main() để chạy ứng dụng. Ở đây cần lưu ý rằng trong khi tạo đối tượng Session, chúng ta đã sử dụng lớp Interceptor như một đối số.
import java.util.Iterator; import java.util.List; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cfg.Configuration; import hibernate.interceptor.entity.Employee; 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(); } } }
Kết quả run trên Eclipse
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 postFlush