拦截器

你已经学到,在 Hibernate 中,一个对象将被创建和保持。一旦对象已经被修改,它必须被保存到数据库里。这个过程持续直到下一次对象被需要,它将被从持久的存储中加载。

因此一个对象通过它生命周期中的不同阶段,并且 Interceptor 接口提供了在不同阶段能被调用来进行一些所需要的任务的方法。这些方法是从会话到应用程序的回调函数,允许应用程序检查或操作一个持续对象的属性,在它被保存,更新,删除或上传之前。以下是在 Interceptor 接口中可用的所有方法的列表。

S.N. 方法和描述
1 findDirty()这个方法在当 flush() 方法在一个 Session 对象上被调用时被调用。
2 instantiate()这个方法在一个持续的类被实例化时被调用。
3 isUnsaved()这个方法在当一个对象被传到 saveOrUpdate() 方法时被调用。
4 onDelete()这个方法在一个对象被删除前被调用。
5 onFlushDirty()这个方法在当 Hibernate 探测到一个对象在一次 flush(例如,更新操作)中是脏的(例如,被修改)时被调用。
6 onLoad()这个方法在一个对象被初始化之前被调用。
7 onSave()这个方法在一个对象被保存前被调用。
8 postFlush()这个方法在一次 flush 已经发生并且一个对象已经在内存中被更新后被调用。
9 preFlush()这个方法在一次 flush 前被调用。

Hibernate 拦截器给予了我们一个对象如何应用到应用程序和数据库的总控制。

如何使用拦截器?

为了创建一个拦截器你可以直接实现 Interceptor 类或者继承 EmptyInterceptor 类。以下是简单的使用 Hibernate 拦截器功能的步骤。

创建拦截器

我们将在例子中继承 EmptyInterceptor,当 Employee 对象被创建和更新时拦截器的方法将自动被调用。你可以根据你的需求实现更多的方法。

  1. import java.io.Serializable;
  2. import java.util.Date;
  3. import java.util.Iterator;
  4. import org.hibernate.EmptyInterceptor;
  5. import org.hibernate.Transaction;
  6. import org.hibernate.type.Type;
  7. public class MyInterceptor extends EmptyInterceptor {
  8. private int updates;
  9. private int creates;
  10. private int loads;
  11. public void onDelete(Object entity,
  12. Serializable id,
  13. Object[] state,
  14. String[] propertyNames,
  15. Type[] types) {
  16. // do nothing
  17. }
  18. // This method is called when Employee object gets updated.
  19. public boolean onFlushDirty(Object entity,
  20. Serializable id,
  21. Object[] currentState,
  22. Object[] previousState,
  23. String[] propertyNames,
  24. Type[] types) {
  25. if ( entity instanceof Employee ) {
  26. System.out.println("Update Operation");
  27. return true;
  28. }
  29. return false;
  30. }
  31. public boolean onLoad(Object entity,
  32. Serializable id,
  33. Object[] state,
  34. String[] propertyNames,
  35. Type[] types) {
  36. // do nothing
  37. return true;
  38. }
  39. // This method is called when Employee object gets created.
  40. public boolean onSave(Object entity,
  41. Serializable id,
  42. Object[] state,
  43. String[] propertyNames,
  44. Type[] types) {
  45. if ( entity instanceof Employee ) {
  46. System.out.println("Create Operation");
  47. return true;
  48. }
  49. return false;
  50. }
  51. //called before commit into database
  52. public void preFlush(Iterator iterator) {
  53. System.out.println("preFlush");
  54. }
  55. //called after committed into database
  56. public void postFlush(Iterator iterator) {
  57. System.out.println("postFlush");
  58. }
  59. }

创建 POJO 类

现在让我们稍微修改我们的第一个例子,我们使用 EMPLOYEE 表单和 Employee 类:

  1. public class Employee {
  2. private int id;
  3. private String firstName;
  4. private String lastName;
  5. private int salary;
  6. public Employee() {}
  7. public Employee(String fname, String lname, int salary) {
  8. this.firstName = fname;
  9. this.lastName = lname;
  10. this.salary = salary;
  11. }
  12. public int getId() {
  13. return id;
  14. }
  15. public void setId( int id ) {
  16. this.id = id;
  17. }
  18. public String getFirstName() {
  19. return firstName;
  20. }
  21. public void setFirstName( String first_name ) {
  22. this.firstName = first_name;
  23. }
  24. public String getLastName() {
  25. return lastName;
  26. }
  27. public void setLastName( String last_name ) {
  28. this.lastName = last_name;
  29. }
  30. public int getSalary() {
  31. return salary;
  32. }
  33. public void setSalary( int salary ) {
  34. this.salary = salary;
  35. }
  36. }

创建数据库表

第二步将是在你的数据库中创建表。一张表对应每个你提供持久性的对象。考虑以上的对象需要被存储和检索到以下的 RDBM 表中:

  1. create table EMPLOYEE (
  2. id INT NOT NULL auto_increment,
  3. first_name VARCHAR(20) default NULL,
  4. last_name VARCHAR(20) default NULL,
  5. salary INT default NULL,
  6. PRIMARY KEY (id)
  7. );

创建 Mapping 配置文件

这个步骤是来创建一个指导 Hibernate 如何将定义的类或者多个类映射到数据库表单中的映射文件。

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <!DOCTYPE hibernate-mapping PUBLIC
  3. "-//Hibernate/Hibernate Mapping DTD//EN"
  4. "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
  5. <hibernate-mapping>
  6. <class name="Employee" table="EMPLOYEE">
  7. <meta attribute="class-description">
  8. This class contains the employee detail.
  9. </meta>
  10. <id name="id" type="int" column="id">
  11. <generator class="native"/>
  12. </id>
  13. <property name="firstName" column="first_name" type="string"/>
  14. <property name="lastName" column="last_name" type="string"/>
  15. <property name="salary" column="salary" type="int"/>
  16. </class>
  17. </hibernate-mapping>

创建 Application 类

最后,我们将用 main() 创建 application 类来运行应用程序。这里应该注意当创建 session 对象时我们使用 Interceptor 类作为参数。

  1. import java.util.List;
  2. import java.util.Date;
  3. import java.util.Iterator;
  4. import org.hibernate.HibernateException;
  5. import org.hibernate.Session;
  6. import org.hibernate.Transaction;
  7. import org.hibernate.SessionFactory;
  8. import org.hibernate.cfg.Configuration;
  9. public class ManageEmployee {
  10. private static SessionFactory factory;
  11. public static void main(String[] args) {
  12. try{
  13. factory = new Configuration().configure().buildSessionFactory();
  14. }catch (Throwable ex) {
  15. System.err.println("Failed to create sessionFactory object." + ex);
  16. throw new ExceptionInInitializerError(ex);
  17. }
  18. ManageEmployee ME = new ManageEmployee();
  19. /* Add few employee records in database */
  20. Integer empID1 = ME.addEmployee("Zara", "Ali", 1000);
  21. Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
  22. Integer empID3 = ME.addEmployee("John", "Paul", 10000);
  23. /* List down all the employees */
  24. ME.listEmployees();
  25. /* Update employee's records */
  26. ME.updateEmployee(empID1, 5000);
  27. /* Delete an employee from the database */
  28. ME.deleteEmployee(empID2);
  29. /* List down new list of the employees */
  30. ME.listEmployees();
  31. }
  32. /* Method to CREATE an employee in the database */
  33. public Integer addEmployee(String fname, String lname, int salary){
  34. Session session = factory.openSession( new MyInterceptor() );
  35. Transaction tx = null;
  36. Integer employeeID = null;
  37. try{
  38. tx = session.beginTransaction();
  39. Employee employee = new Employee(fname, lname, salary);
  40. employeeID = (Integer) session.save(employee);
  41. tx.commit();
  42. }catch (HibernateException e) {
  43. if (tx!=null) tx.rollback();
  44. e.printStackTrace();
  45. }finally {
  46. session.close();
  47. }
  48. return employeeID;
  49. }
  50. /* Method to READ all the employees */
  51. public void listEmployees( ){
  52. Session session = factory.openSession( new MyInterceptor() );
  53. Transaction tx = null;
  54. try{
  55. tx = session.beginTransaction();
  56. List employees = session.createQuery("FROM Employee").list();
  57. for (Iterator iterator =
  58. employees.iterator(); iterator.hasNext();){
  59. Employee employee = (Employee) iterator.next();
  60. System.out.print("First Name: " + employee.getFirstName());
  61. System.out.print(" Last Name: " + employee.getLastName());
  62. System.out.println(" Salary: " + employee.getSalary());
  63. }
  64. tx.commit();
  65. }catch (HibernateException e) {
  66. if (tx!=null) tx.rollback();
  67. e.printStackTrace();
  68. }finally {
  69. session.close();
  70. }
  71. }
  72. /* Method to UPDATE salary for an employee */
  73. public void updateEmployee(Integer EmployeeID, int salary ){
  74. Session session = factory.openSession( new MyInterceptor() );
  75. Transaction tx = null;
  76. try{
  77. tx = session.beginTransaction();
  78. Employee employee =
  79. (Employee)session.get(Employee.class, EmployeeID);
  80. employee.setSalary( salary );
  81. session.update(employee);
  82. tx.commit();
  83. }catch (HibernateException e) {
  84. if (tx!=null) tx.rollback();
  85. e.printStackTrace();
  86. }finally {
  87. session.close();
  88. }
  89. }
  90. /* Method to DELETE an employee from the records */
  91. public void deleteEmployee(Integer EmployeeID){
  92. Session session = factory.openSession( new MyInterceptor() );
  93. Transaction tx = null;
  94. try{
  95. tx = session.beginTransaction();
  96. Employee employee =
  97. (Employee)session.get(Employee.class, EmployeeID);
  98. session.delete(employee);
  99. tx.commit();
  100. }catch (HibernateException e) {
  101. if (tx!=null) tx.rollback();
  102. e.printStackTrace();
  103. }finally {
  104. session.close();
  105. }
  106. }
  107. }

 编译和执行

这里是编译和运行上面提及的应用程序的步骤。确保你已经在处理编译和执行前正确设置了 PATH 和 CLASSPATH。

  • 创建在 configuration 章节中解释的 hibernate.cfg.xml 配置文件。
  • 创建如上所示的 Employee.hbm.xml 映射文件。
  • 创建如上所示的 Employee.java 源文件并编译。
  • 创建如上所示的 MyInterceptor.java 源文件并编译。
  • 创建如上所示的 ManageEmployee.java 源文件并编译。
  • 执行 ManageEmployee 来运行程序。

你将得到以下结果,而且记录将在 EMPLOYEE 表单中被创建。

  1. $java ManageEmployee
  2. .......VARIOUS LOG MESSAGES WILL DISPLAY HERE........
  3. Create Operation
  4. preFlush
  5. postFlush
  6. Create Operation
  7. preFlush
  8. postFlush
  9. Create Operation
  10. preFlush
  11. postFlush
  12. First Name: Zara Last Name: Ali Salary: 1000
  13. First Name: Daisy Last Name: Das Salary: 5000
  14. First Name: John Last Name: Paul Salary: 10000
  15. preFlush
  16. postFlush
  17. preFlush
  18. Update Operation
  19. postFlush
  20. preFlush
  21. postFlush
  22. First Name: Zara Last Name: Ali Salary: 5000
  23. First Name: John Last Name: Paul Salary: 10000
  24. preFlush
  25. postFlush

如果你检查你的 EMPLOYEE 表单,它应该有如下结果:

  1. mysql> select * from EMPLOYEE;
  2. +----+------------+-----------+--------+
  3. | id | first_name | last_name | salary |
  4. +----+------------+-----------+--------+
  5. | 29 | Zara | Ali | 5000 |
  6. | 31 | John | Paul | 10000 |
  7. +----+------------+-----------+--------+
  8. 2 rows in set (0.00 sec
  9. mysql>