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