首页 > 代码库 > 攻城狮在路上(壹) Hibernate(七)--- 通过Hibernate操纵对象(下)
攻城狮在路上(壹) Hibernate(七)--- 通过Hibernate操纵对象(下)
一、与触发器协同工作:
当Hibernate与数据库的触发器协同工作时,会出现以下两类问题:
1、触发器使Session缓存中的数据和数据库中的不一致:
出现此问题的原因是触发器运行在数据库内,它执行的操作对Session是透明的。
解决方案:在执行完包含有触发器的操作之后,立刻调用Session的flush()和refresh()方法,迫使Session的缓存与数据库同步。
2、Session的update()方法盲目的激发触发器:
这种情况主要发生在Session调用update()或saveOrUpdate()方法时,能够使一个游离对象和Session关联,此时由于缓存中不存在该对象的快照,因此肯定会执行一次update语句,进而激发触发器。如果该对象的属性和数据库中的数据一致,那么该update语句就是多余的。要避免此种情况,在<class>元素中设置select-before-update="true"即可。
二、利用拦截器生成审计日志:暂不关注。
三、Hibernate事件处理机制:
Hibernate3的核心处理模块采用了“事件\监听器”设计模式。
Session的大部分方法都会触发特定事件,该事件由相应的监听器来处理。
在org.hibernate.event包中提供了与Session的各个方法对应的事件类及监听器接口。
创建及注册客户化监听器方法的一般步骤:
1、创建客户化监听器:
A、直接实现特定的监听器接口。
B、继承Hibernate提供的监听器接口的基础实现类,比如org.hibernate.enent.def.AbstractSaveEventListner.
C、继承Hibernate提供的监听器接口的默认实现类。比如org.hibernate.event.def.DefaultSaveEventListner.
2、注册客户化监听器:2种方式
A、在Hibernate的配置文件hibernate.cfg.xml中静态注册。
1 2 3 | <event type= "load" > <listener class = "mypack.MyLoadListener" /> </event> |
B、在程序中动态注册:可以注册多个。
1 2 3 | Configuration cfg = new Configuration(); LoadEventListener[] listeners = { new MyLoadListener(),...}; cfg.getEventListeners().setLoadEventListeners(listeners); |
四、批量处理数据:
批量操作带来的问题:
A、占用大量内存,比如批量更新,需要把大量的对象先加载到内存中,然后一一更新。
B、执行的更新语句的数目太多。
因此,应该尽量避免在应用层进行批量操作,而应该在数据库层直接进行批量操作。若要在应用层执行批量操作,有以下四种方式:
1、通过Session来进行批量操作:
此种做法是在处理完一个对象或一小批对象之后,立刻调用flush()方法清理缓存,然后调用clear()方法清空缓存。
需要注意:
合理设置hibernate.jdbc.batch_size属性。
如果对象采用identity标识符生成器,则Hibernate无法再JDBC层进行批量插入操作。
进行批量操作时,建议关闭二级缓存。
2、通过StatelessSession来进行批量操作:用法和Session类似。
3、通过HQL来进行批量操作:Query.executeUpdate()
4、直接通过JDBC API来进行批量操作:
五、使用元数据:
通过SessionFactory.getClassMetadata()和getCollectionMetadate()可以获取相应的对象来操纵元数据。
六、执行存储过程:参见JDBC的方式。