在Hibernate中,有两种方式可以捕获实体对象的GRUD操作并执行相应的处理

Hibernate回调(org.hibernate.classic.Lifecycle接口):

//Provides callbacks from the Session to the persistent object.
//Persistent classes may implement this interface but they are not
//required to.
//If a CallbackException is thrown, the operation is vetoed and the
//exception is passed back to the application.
public interface Lifecycle { //If onSave(), onUpdate() or onDelete() return VETO,
//the operation is silently vetoed.
public static final boolean VETO = true;
public static final boolean NO_VETO = false; //Called just before the object is saved
public boolean onSave(Session s) throws CallbackException; //Called when an entity is passed to Session.update().
//This method is not called every time the object's
//state is persisted during a flush.
public boolean onUpdate(Session s) throws CallbackException; //Called just before an object is deleted
public boolean onDelete(Session s) throws CallbackException; //Called just after an object is loaded
public void onLoad(Session s, Serializable id);
}

需要注意的地方:

1,如果onSave()、onUpdate()、onDelete()方法返回VOTE(true)或者在以上方法中抛出了CallbackException异常,操作将会停止而不会调用之后的Session.save()、Session.update()、Session.delete()方法

2,并不是每次调用Session.update()方法之前都会调用onUpdate()方法

3,调用Session.get()方法会直接返回实体对象,故在调用该方法后会立即调用onload()方法,而调用Session.load()方法返回的是实体对象的代理,故在调用该方法后不会立即调用onload()方法,对象在第一次使用时才会真正加载,而在对象真正加载完成之后才会调用onload()方法

4,不能直接使用方法中的Session对象,该方法是由当前Session负责调用,如果在这些方法中又调用当前Session进行持久化,将导致Session内部状态混乱

在onSave()方法中调用Session.save()方法将会导致死循环,但是在onSave()方法中执行Session.update()方法却没有报异常,不过通常方法只负责记录日志,数据合法性校验等简单工作,不会在这里再次调用Session对象完成数据持久化,故不需考虑太多

提到Lifecycle接口,通常也要提到Validatable接口(org.hibernate.classic.Validatable):

//Implemented by persistent classes with invariants that must
//be checked before inserting into or updating the database.
public interface Validatable { //Validate the state of the object before persisting it.
//If a violation occurs, throw a ValidationFailure.
//This method must not change the state of the object by
//side-effect.
public void validate() throws ValidationFailure;
}

只有在对象插入和对象更新时才会调用validate()方法对对象数据合法性进行校验

public class User implements Serializable,Lifecycle,Validatable{
private Integer id;
private String name;
private Integer age;
private static final long serialVersionUID = 1L; public User(){} public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Integer getAge() {
return age;
} public void setAge(Integer age) {
this.age = age;
} public boolean onSave(Session s) throws CallbackException {
System.out.println("********on save********");
System.out.println("id :" + id);
System.out.println("name :" + name);
System.out.println("age :" + age);
return Lifecycle.NO_VETO;
} @Override
public boolean onUpdate(Session s) throws CallbackException {
System.out.println("********on update********");
System.out.println("id :" + id);
System.out.println("name :" + name);
System.out.println("age :" + age);
return Lifecycle.VETO;
} @Override
public boolean onDelete(Session s) throws CallbackException {
System.out.println("********on delete********");
throw new CallbackException("Delete operation is not allowed!");
} @Override
public void onLoad(Session s, Serializable id) {
System.out.println("********on load********");
System.out.println("id :" + id);
} @Override
public void validate() throws ValidationFailure {
System.out.println("~~~~~~~~valid~~~~~~~~");
if(id < 0)
throw new ValidationFailure("Illegal id!");
if(name == null || name.equals(""))
throw new ValidationFailure("Illegal name!");
if(age < 0 || age > 150)
throw new ValidationFailure("Illegal age!");
}
}

由于这种方式对POJO带有侵入性,所以不建议使用

Hibernate拦截(org.hibernate.Interceptor接口):

接口定义了非常多的方法,基本上通过命名就可以看出其功能,就不一一介绍了

不建议直接继承Interceptor接口,更好的方式是继承EmptyInterceptor类,并重写需要的方法,EmptyInterceptor接口如下:

public class EmptyInterceptor implements Interceptor,
Serializable { public static final Interceptor INSTANCE =
new EmptyInterceptor(); protected EmptyInterceptor() {} public void onDelete(
Object entity,
Serializable id,
Object[] state,
String[] propertyNames,
Type[] types) {} public boolean onFlushDirty(
Object entity,
Serializable id,
Object[] currentState,
Object[] previousState,
String[] propertyNames,
Type[] types) {
return false;
} public boolean onLoad(
Object entity,
Serializable id,
Object[] state,
String[] propertyNames,
Type[] types) {
return false;
} public boolean onSave(
Object entity,
Serializable id,
Object[] state,
String[] propertyNames,
Type[] types) {
return false;
} public void postFlush(Iterator entities) {} public void preFlush(Iterator entities) {} public Boolean isTransient(Object entity) {
return null;
} public Object instantiate(String entityName, EntityMode entityMode,
Serializable id) {
return null;
} public int[] findDirty(Object entity,
Serializable id,
Object[] currentState,
Object[] previousState,
String[] propertyNames,
Type[] types) {
return null;
} public String getEntityName(Object object) {
return null;
} public Object getEntity(String entityName, Serializable id) {
return null;
} public void afterTransactionBegin(Transaction tx) {} public void afterTransactionCompletion(Transaction tx) {} public void beforeTransactionCompletion(Transaction tx) {} public String onPrepareStatement(String sql) {
return sql;
} public void onCollectionRemove(Object collection, Serializable key)
throws CallbackException {} public void onCollectionRecreate(Object collection, Serializable key)
throws CallbackException {} public void onCollectionUpdate(Object collection, Serializable key)
throws CallbackException {}
}

示例如下:

public class LogInterceptor extends EmptyInterceptor {

	private static final long serialVersionUID = 1L;

	@Override
public boolean onLoad(Object entity, Serializable id, Object[] state,
String[] propertyNames, Type[] types) {
System.out.println(entity.getClass().getName() + " loaded.");
return false;
}
}

值得注意的是可以配置2种范围的拦截器

SessionFactory范围的拦截器:

由于多个Session可能并发的使用SessionFactoruy范围的拦截器,故该拦截器必须是线程安全的

LogInterceptor li = new LogInterceptor();
Configuration conf = new Configuration().setInterceptor(li);
SessionFactory sessionFactory = conf.configure().buildSessionFactory(); Session sess = sessionFactory.openSession();

Session范围的拦截器:

LogInterceptor li = new LogInterceptor();
Configuration conf = new Configuration();
SessionFactory sessionFactory = conf.configure().buildSessionFactory(); Session sess = sessionFactory.openSession(li);

Hibernate的回调与拦截的更多相关文章

  1. Ps回调函数.拦截驱动模块原理+实现.

    目录 一丶简介 二丶原理 1.原理 2.代码实现 3.效果 一丶简介 主要是讲解.内核中如何拦截模块加载的. 需要熟悉.内核回调的设置 PE知识. ShellCode 二丶原理 1.原理 原理是通过回 ...

  2. 再谈Delphi关机消息拦截 -- 之控制台程序 SetConsoleCtrlHandler(控制台使用回调函数拦截,比较有意思)

    这里补充一下第一篇文章中提到的拦截关机消息 Delphi消息拦截:http://blog.csdn.net/cwpoint/archive/2011/04/05/6302314.aspx 下面我再介绍 ...

  3. 笔记:Hibernate 拦截器和事件

    Hibernate 在执行持久化的过程中,应用程序通常无法参与其中,通过事件框架,Hibernate 允许应用程序能响应特定的内部事件,从而允许实现某些通用的功能,或者对 Hibernate 进行扩展 ...

  4. Hibernate学习---第十三节:hibernate过滤器和拦截器的实现

    一.hibernate 过滤器 1.在持久化映射文件中配置过滤器,代码如下: <?xml version="1.0"?> <!DOCTYPE hibernate- ...

  5. Atitit.hibernate体系结构大总结

    Atitit.hibernate体系结构大总结 1. 4.1 hibernate基础语义 80  4.1.1 configuration 80  4.1.2 sessionfactory 81  4. ...

  6. hibernate详解

    Hibernate原理与应用 主要内容 1.引入 2.安装配置 3.基本概念和CURD 4.HQL和Criteria 5.关联映射 6.继承映射 7.集合映射 8.懒加载 9.缓存 10.事务 11. ...

  7. 拦截器(Interceptor)与过滤器(Filter)的区别

    转自:https://www.jianshu.com/p/cf088baa9b04 过滤器,是在java web中将你传入的request.response提前过滤掉一些信息,或者提前设置一些参数.然 ...

  8. Struts2之过滤器和拦截器的区别

    刚学习Struts2这个框架不久,心中依然有一个疑惑未解那就是过滤器和拦截器的区别,相信也有不少人跟我一样对于这个问题没有太多的深入了解 那么下面我们就一起来探讨探讨 过滤器,是在java web中, ...

  9. 过滤器(servlet.filter)和拦截器(springmvc.interceptor)区别

    ①拦截器是基于java的反射机制的,而过滤器是基于函数回调. ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器. ③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求 ...

随机推荐

  1. ubuntu openstack packaages

  2. oracle 10g

    一.安装系统 首先安装Linux系统,根据Oracle官方文档的建议,在机器内存小于1G的情况下,swap分区大小应该设置为内存的2倍大,若内存大于2G则swap分区设置为与内存大小一样. 为防止Or ...

  3. 现代程序设计——homework-10

    设计 对于MVC我的理解是这样的,V是台显示器,注意仅仅是一台比显示器普通显示器多几个按钮,用户按什么,按了什么该干什么都不用操心:M是实体的软件抽象,假设实体可以但不执行,我就可以一步一步走,实体可 ...

  4. JSF 2 checkboxes example

    In JSF, <h:selectBooleanCheckbox /> tag is used to render a single HTML input element of " ...

  5. mysql从一个表中拷贝数据到另一个表中sql语句

    这一段在找新的工作,今天面试时,要做一套题,其中遇到这么一句话,从一个表中拷贝所有的数据到另一个表中的sql是什么? 原来我很少用到,也没注意过这个问题,面试后我上网查查,回来自己亲手写了写,测试了下 ...

  6. 新手指南:详解Linux Top 命令

    Linux top命令简介 top 命令是最流行的性能监视工具之一,我们必需了解.它是一个优秀的交互式工具,用于监视性能.它提供系统整体性能,但报告进程信息才是 top 命令的长处.top 命令交互界 ...

  7. 精通Linux的“kill”命令

    无论你使用哪种操作系统,你一定会遇到某个行为失常的应用,它把自己锁死并拒绝关闭.在Linux(还有Mac),你可以用一个"kill"命令强制终结它.在这个教程中,我们将展示给你多种 ...

  8. python中列表,元组,字符串如何互相转换

    python中有三个内建函数:列表,元组和字符串,他们之间的互相转换使用三个函数,str(),tuple()和list(),具体示例如下所示: >>> s = "xxxxx ...

  9. word2003公式编辑器公式显示不完整问题

    在段落里设置行距为:单倍行距.

  10. UVa 10817 Headmaster's Headache (状压DP+记忆化搜索)

    题意:一共有s(s ≤ 8)门课程,有m个在职教师,n个求职教师.每个教师有各自的工资要求,还有他能教授的课程,可以是一门或者多门. 要求在职教师不能辞退,问如何录用应聘者,才能使得每门课只少有两个老 ...