7.5 级联操作对象图

       Session 的缓存中存放的是相互关联的对象图,看起来就加载了一个对象,实际上加载了所有的和其直接或间接关联的对象。

       其中 cascade 属性指定如何操作:

属性值

描述

none

默认值,忽略关联

save-update

级联保存新建的临时对象,级联更新关联的游离对象

delete

级联删除关联的对象

all

包括 save-update 、 delete 行为,也会级联进行 evict() 、 lock() 操作

delete-orphan

删除和当前对象解除关联关系的对象

all-delete-orphan

包括 all 、 delete-orphan 行为

7.6 与触发器协同工作

       激发触发器的事件:

       1.insert 语句

       2.update 语句

       3.delete 语句

       协同工作可能出现的问题:

       1. 使 Session 的缓存中的数据与数据库不一致

       例如,有 TIME 字段,它由触发器来写入当前系统时间, save() 操作不能对它进行修改,而触发器是直接修改的数据库中的内容,程序里的对象的 time 字段并没有赋值,这样如果以后需要再调用这一对象的 TIME 值时,就会出错。

       解决办法是在 flush() 后,再调用 refresh() 方法,重新从数据库中加载被保存的对象。

session.save(customer);// 保存语句,这时只是计划执行 insert 语句

session.flush();// 清理缓存,触发器工作,立即进行 insert 语句(此时直接在数据库中插入 time )

session.refresh(customer);// 重新从数据库中加载被保存的对象

tx.commit();

       2.update() 方法盲目激发触发器

       如果更新时,对象关联一个游离对象,而 Session 无法判断此游离对象是否发生了改变,就会为了保险将其同时更新。为了避免这一问题,可以设置 select-before-update 属性,具体见 7.4.2 。

7.7 利用拦截器( Interceptor )生成审计日志

       审计主要是对数据库中重要数据的更新历史进行记录。

       触发器可以用于生成审计日志,但是不支持跨数据库平台,所以一般用拦截器。

       调用拦截器的方法:

       1.save()

       2.update()

       3.saveOrUpdate()

       4.flush()

       用户定义的拦截器必须实现 net.sf.hibernate.Interceptor 接口,此接口定义了以下方法:

方法

描述

findDirth()

决定缓存中那些对象是脏对象, Session 的 flush() 方法调用此方法

instantiate(Class clazz,Serializable id)

创建实体类的实例。

isUnsaved(Object entity)

Session 的 saveOrUpdate () 方法调用此方法

onDelete()

删除对象前调用此方法

onFlushDirty()

Session 的 flush() 方法检查到脏对象时调用此方法

onLoad()

Session 初始化一个持久化对象时调用此方法

onSave()

保存对象前调用此方法

postFlush(Iterator entities)

Session 的 flush() 方法执行完所有的 SQL 语句后调用此方法

preFlush(Iterator entities)

执行 flush() 方法前调用此方法