Hibernate的回调与拦截
在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的回调与拦截的更多相关文章
- Ps回调函数.拦截驱动模块原理+实现.
目录 一丶简介 二丶原理 1.原理 2.代码实现 3.效果 一丶简介 主要是讲解.内核中如何拦截模块加载的. 需要熟悉.内核回调的设置 PE知识. ShellCode 二丶原理 1.原理 原理是通过回 ...
- 再谈Delphi关机消息拦截 -- 之控制台程序 SetConsoleCtrlHandler(控制台使用回调函数拦截,比较有意思)
这里补充一下第一篇文章中提到的拦截关机消息 Delphi消息拦截:http://blog.csdn.net/cwpoint/archive/2011/04/05/6302314.aspx 下面我再介绍 ...
- 笔记:Hibernate 拦截器和事件
Hibernate 在执行持久化的过程中,应用程序通常无法参与其中,通过事件框架,Hibernate 允许应用程序能响应特定的内部事件,从而允许实现某些通用的功能,或者对 Hibernate 进行扩展 ...
- Hibernate学习---第十三节:hibernate过滤器和拦截器的实现
一.hibernate 过滤器 1.在持久化映射文件中配置过滤器,代码如下: <?xml version="1.0"?> <!DOCTYPE hibernate- ...
- Atitit.hibernate体系结构大总结
Atitit.hibernate体系结构大总结 1. 4.1 hibernate基础语义 80 4.1.1 configuration 80 4.1.2 sessionfactory 81 4. ...
- hibernate详解
Hibernate原理与应用 主要内容 1.引入 2.安装配置 3.基本概念和CURD 4.HQL和Criteria 5.关联映射 6.继承映射 7.集合映射 8.懒加载 9.缓存 10.事务 11. ...
- 拦截器(Interceptor)与过滤器(Filter)的区别
转自:https://www.jianshu.com/p/cf088baa9b04 过滤器,是在java web中将你传入的request.response提前过滤掉一些信息,或者提前设置一些参数.然 ...
- Struts2之过滤器和拦截器的区别
刚学习Struts2这个框架不久,心中依然有一个疑惑未解那就是过滤器和拦截器的区别,相信也有不少人跟我一样对于这个问题没有太多的深入了解 那么下面我们就一起来探讨探讨 过滤器,是在java web中, ...
- 过滤器(servlet.filter)和拦截器(springmvc.interceptor)区别
①拦截器是基于java的反射机制的,而过滤器是基于函数回调. ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器. ③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求 ...
随机推荐
- 应用数据存储到sdcard上一定要规范,android4.4.2有新规范
如果你的android设备有内部存储空间,即通常所说的机身存储(这就是指主要外部存储),那么你从外部插入SD卡就是一个二级外部存储设备. 最新的Android 4.4系统中,外置存储卡(SD卡)被称为 ...
- Java多线程编程之同步器
同步器 为每种特定的同步问题提供了解决方案 Semaphore Semaphore[信号标:旗语],通过计数器控制对共享资源的访问. 测试类: package concurrent; import c ...
- 第二百四十七天 how can I 坚持
今天去了趟北海公园,看到地铁宣传图片挺好看的,实景也倒是不错,环境好了,哪都好,今天是蓝天白云啊. 回来的路上看了,扎克伯格对质疑的回应.哎.改变世界在硅谷是行动,而不是口号.change the w ...
- Red5源代码分析 - 关键类及其初始化过程
原文地址:http://semi-sleep.javaeye.com/blog/348768 Red5如何响应rmpt的请求,中间涉及哪些关键类? 响应请求的流程如下: 1.Red5在启动时会调用RT ...
- 常用的Activex 控件
1. Flash Player ActiveX Control 6.0.47.0 与FLASH 6.0配套的浏览器端动画播放插件 download.pchome.n ...
- 对于一个网站,如何禁止直接从浏览器Web browser中访问js文件
比如有一个网站,https://testsystem.infotest.com 在这个网站的内容文件目录下面,有一个scripts文件夹,该文件夹中有一个js文件,比如lukeTest.js文件 这样 ...
- CSS构造列表
列表图片 背景列表 翻转列表 水平导航 内边距与外边距 Ul { List-style-type:none; Margin: 0; Padding: 0; } 使用图片作为列表图标 Ul { Marg ...
- CoreSeek有符号整型
数据库status字段的值有:-1,0,1 设置过滤字段,发现sql_attr_uint不支持负数,后改用sql_attr_bigint sql_attr_bigint = status sql_at ...
- Science上发表的超赞聚类算法(转)
作者(Alex Rodriguez, Alessandro Laio)提出了一种很简洁优美的聚类算法, 可以识别各种形状的类簇, 并且其超参数很容易确定. 算法思想 该算法的假设是类簇的中心由一些局部 ...
- [c++]堆和栈的区别
堆和栈的区别一.预备知识—程序的内存分配一个由c/C++编译的程序占用的内存分为以下几个部分1.栈区(stack)— 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等.其操作方式类似于数据结构 ...