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() 方法前调用此方法