在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. 应用数据存储到sdcard上一定要规范,android4.4.2有新规范

    如果你的android设备有内部存储空间,即通常所说的机身存储(这就是指主要外部存储),那么你从外部插入SD卡就是一个二级外部存储设备. 最新的Android 4.4系统中,外置存储卡(SD卡)被称为 ...

  2. Java多线程编程之同步器

    同步器 为每种特定的同步问题提供了解决方案 Semaphore Semaphore[信号标:旗语],通过计数器控制对共享资源的访问. 测试类: package concurrent; import c ...

  3. 第二百四十七天 how can I 坚持

    今天去了趟北海公园,看到地铁宣传图片挺好看的,实景也倒是不错,环境好了,哪都好,今天是蓝天白云啊. 回来的路上看了,扎克伯格对质疑的回应.哎.改变世界在硅谷是行动,而不是口号.change the w ...

  4. Red5源代码分析 - 关键类及其初始化过程

    原文地址:http://semi-sleep.javaeye.com/blog/348768 Red5如何响应rmpt的请求,中间涉及哪些关键类? 响应请求的流程如下: 1.Red5在启动时会调用RT ...

  5. 常用的Activex 控件

    1. Flash Player  ActiveX Control 6.0.47.0 与FLASH 6.0配套的浏览器端动画播放插件                  download.pchome.n ...

  6. 对于一个网站,如何禁止直接从浏览器Web browser中访问js文件

    比如有一个网站,https://testsystem.infotest.com 在这个网站的内容文件目录下面,有一个scripts文件夹,该文件夹中有一个js文件,比如lukeTest.js文件 这样 ...

  7. CSS构造列表

    列表图片 背景列表 翻转列表 水平导航 内边距与外边距 Ul { List-style-type:none; Margin: 0; Padding: 0; } 使用图片作为列表图标 Ul { Marg ...

  8. CoreSeek有符号整型

    数据库status字段的值有:-1,0,1 设置过滤字段,发现sql_attr_uint不支持负数,后改用sql_attr_bigint sql_attr_bigint = status sql_at ...

  9. Science上发表的超赞聚类算法(转)

    作者(Alex Rodriguez, Alessandro Laio)提出了一种很简洁优美的聚类算法, 可以识别各种形状的类簇, 并且其超参数很容易确定. 算法思想 该算法的假设是类簇的中心由一些局部 ...

  10. [c++]堆和栈的区别

    堆和栈的区别一.预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构 ...