在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. https://github.com/mlzboy/spider-impl.git

    Installation - pygit2 0.24.0 documentation Python 2.7, 3.2+ or PyPy 2.6+ (including the development ...

  2. Apache Spark Streaming的适用场景

    使用场景: Spark Streaming 适合需要历史数据和实时数据结合进行分析的应用场景,对于实时性要求不是特别高的场景也能够胜任.

  3. Apache Spark Streaming的优点

    Apache Spark Streaming的优点: (1)优势及特点 1)多范式数据分析管道:能和 Spark 生态系统其他组件融合,实现交互查询和机器学习等多范式组合处理. 2)扩展性:可以运行在 ...

  4. build.gradle 使用tips

    7.查看依赖 gradlew [你想查看的module]:dependencies >dependencies.txt 6.buildToolsVersion build tools版本号 co ...

  5. poj 3026 Borg Maze (BFS + Prim)

    http://poj.org/problem?id=3026 Borg Maze Time Limit:1000MS     Memory Limit:65536KB     64bit IO For ...

  6. 转载github上最全的资源教程--前端涉及的所有知识体系

    以下地址为园子里一个哥们总结的前端所涉及的所有知识体系 http://www.cnblogs.com/bymax/p/5878113.html 很值得学习参考

  7. 对.NET的认识

    .NET其实就是一个软件平台,这个平台和Java平台有许多的相似之处,主要表现在 1.二者编写的程序都是可以跨平台执行的   2.二者编写的程序编译后生成的都是一种中间码(IL),需要经过第二次编译才 ...

  8. 解决Java版CKFinder无法显示缩略图问题

    这些天在写我的Java EE项目的时候用到了CKEditor和CKFinder,但是在用CKFinder的时候无法显示图片的缩略图,但是官网上的demo上却有缩略图,我一直以为是自己配置错误了,我把官 ...

  9. 项目经验之:MVVM初学者图形化笔记整理。。。

    这个模式,一下子把我的思路给打开..让我眼前一亮..居然可以这样将界面分离得如此彻底........... 大家一起学习... 说说我的感受吧,一个小实例讲述了 MVVM实现原理: 一个简单的例,将两 ...

  10. 通过克隆MAC地址 破解网通电信封路由

    通过克隆MAC地址 破解网通电信封路由 电信封路由方法一:先确定申请上网的电脑单机状态下已经能够上网.就说明该电脑网卡的MAC地址是合法的MAC地址.进入系统的MSDOS方式,发布ipconfig/a ...