Hibernate攔截器
正如前麵已經了解到,在Hibernate中,對象將被創建並保存。一旦對象已經改變,它必須被保存到數據庫中。這個過程一直持續的對象是需要的,直到下一次,並且它將被從持久存儲加載。
因此,一個對象通過不同階段的生命周期和攔截器接口提供了可以在不同的階段被調用來執行一些任務所需的方法。這些方法是從session到應用程序的回調,允許它被保存在申請前檢查和/或操縱持久化對象的屬性,更新,刪除或加載。以下是攔截器界麵中所有可用的方法列表:
S.N. | Method and 描述 |
---|---|
1 |
findDirty() This method is be called when the flush() method is called on a Session object. |
2 |
instantiate() This method is called when a persisted class is instantiated. |
3 |
isUnsaved() This method is called when an object is passed to the saveOrUpdate() method/ |
4 |
onDelete() This method is called before an object is deleted. |
5 |
onFlushDirty() This method is called when Hibernate detects that an object is dirty (ie. have been changed) during a flush i.e. update operation. |
6 |
onLoad() This method is called before an object is initialized. |
7 |
onSave() This method is called before an object is saved. |
8 |
postFlush() This method is called after a flush has occurred and an object has been updated in memory. |
9 |
preFlush() This method is called before a flush. |
Hibernate攔截器為我們提供了完全控製對象如何將目光轉向應用程序和數據庫。
如何使用攔截器?
為了建立一個攔截器可以直接實現Interceptor接口的類或繼承自EmptyInterceptor類。以下將簡單的步驟來使用Hibernate攔截功能。
創建攔截器:
我們將在例子在創建和更新Employee對象時,攔截器的方法將被自動調用繼承自EmptyInterceptor。可以實現更多的方法按您的要求。
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"); } }
創建POJO類:
現在,讓我們修改一點點,我們使用的EMPLOYEE表和Employee類一起看一個例子:
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; } }
創建數據庫表:
第二步是在數據庫中創建表。會有一個表對應於每一個對象,願意提供持久性。考慮上述目的需要存儲和檢索到下麵的RDBMS表:
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) );
創建映射配置文件:
這一步是創建一個指示Hibernate如何定義的一個或多個類映射到數據庫表的映射文件。
<?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>
創建應用程序類:
最後,我們將創建應用程序類的main()方法來運行應用程序。這裡應該指出的是,在創建會話對象,我們使用了攔截器類作為參數。
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(); } } }
編譯和執行:
下麵是步驟來編譯並運行上述應用程序。請確保已在進行的編譯和執行之前,適當地設置PATH和CLASSPATH。
-
創建hibernate.cfg.xml配置文件中配置章節解釋。
-
創建Employee.hbm.xml映射文件,如上圖所示。
-
創建Employee.java源文件,如上圖所示,並編譯它。
-
創建MyInterceptor.java源文件,如上圖所示,並編譯它。
-
創建ManageEmployee.java源文件,如上圖所示,並編譯它。
-
執行ManageEmployee二進製文件來運行程序。
會得到以下結果,並記錄將在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 postFlush
如果檢查EMPLOYEE表,它應該記錄信息下:
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>