通过Hibernate操纵对象(下)

来源:互联网 发布:java经典实例 编辑:程序博客网 时间:2024/05/21 08:01

与触发器协同工作

        能激发触发器的事件有插入,更新,删除。Hibernate与触发器协同工作时会造成两类问题。
1.触发器是对session缓存中的数据与数据库中的数据不一样。
         执行了session后,触发器执行了,数据库产生的变化session中不知道。所以在save,update子类的激发触发器的操作后,可以调用flush和refresh方法来同步。当然如果操作后不在使用哪个对象,就不用同步了。
2.Session的update方法盲目激发触发器。
         update把游离对象转为持久化对象,但是不管游离对象有没有变化都会执行update。所以就会激发触发器。在要在class属性中加入select-before-update属性,让它为true,就可以在update之前select,然后检查数据库中的数据与游离对象是否一样,只有不一致的情况下才执行update。

拦截器

        触发器常用来生成审计日志,这种方式简便,并且有良好的性能,但是缺点就是不能跨数据库平台。而拦截器就不依赖与数据库平台。拦截器必须实现org,hibernate.Interceptor接口,这个接口定义了很多方法。
1.findDirty():决定对象是不是脏对象,flush方法调用这个方法。返回null表示按照默认方式检查。
2.instantiate(Class clazz,Serializable id):创建实体类的实例。session构造实体类的实例前调用,返回null,按照默认方式创建。
3.isUnsaved(Object xxx):saveOrUpdate方法调用这个方法,返回true,执行save,返回false执行update,返回null,就按照默认方式决定参数是临时对象或者游离对象。
4.onDelete():session删除对象前调用。
5.onFlushDirty():flush方法检测到脏对象时调用这个方法。
6.onLoad():session初始化一个持久化对象调用,如果方法中修改了持久化对象数据返回true,否则返回null。
7.onSave():session保存一个对象调用,如果方法中修改了持久化对象数据返回true,否则返回null。
8.postFlush(Iterator aaa):flush执行完所有sql语句后调用这个方法。
9.preFlush(Iterator bbb):flush执行之前调用。

hibernate提供了一个实现了Interceptor接口的类EnptyInterceptor,自定义的拦截器可以扩展这个类。
Interceptor有两种存放方式:
1.SessionFactory.openSession(Interceptor aaa):为每个session分配一个实例。这个实例存在session范围内。
2.Configuration.setInterceptor(Interceptor bbb):为sessionFactory分配一个实例,这个实例保存在sessionFactory范围,被所有session共享。

监听器

        继承默认实现类 DefaultSaveEventListener。覆盖方法。
静态注册:在配置文件中注册
<event type="load">     <listener class=""/> <listener class=""/></event>
动态注册:在程序中注册。
Configuration a = new Confihuration();LoadEventListener[] b = {监听器1实例,监听器2实例,。。。。};a.getEventListeners.setLoadEventListeners(b);

批处理数据

       一般来说,应该避免在应用层进行批量操作,而应该在数据库中直接操作。下面是4种应用层的批量操作。
1.使用session来进行批量操纵

1.1批量插入数据
 
hibernate.jdbc.batch_size=20设置批量操作数目。
如果对象采用identity标识符生成器,Hibernate无法在JDBC层进行批量插入操作。
进行批量操作建议关闭二级缓存
for(int i=0;i<10000;i++){new 一个对象session.save(xxx);if(i%20==0){//批量更新的数目session.flush();session.clear();}}
1.2批量更新数据

ScrollableResults a = session.createQuery("from 表").scroll(ScrollMode.Forward_ONLY);//然后批量操作这里面的数据
上面的这个对象,返回的只是游标,只有到达当前游标时,才会从数据库中加载对象。

2使用StatelessSession来
跟session相似
1.它没有缓存,对象处于游离态。
2.不会与第二缓存进行交互。
3.save,update等语句操作时,立即执行而不是计划执行。
4.不会进行脏检查
5.不会进行级联操作。
6.操作可以被拦截器捕获到,但会被Hibernate事件处理系统忽略。
7.加载两次OID相同的对象时,这两个对象不相等。

3.通过hql进行批量操作。
       操纵直接在数据库中完成,不会占用内存空间。
3.1批量更新
String sql="sql语句";int a = session.createQuery(sql).setString(xxx,xxx).executeUpdate()
删除跟上面一样。
4.直接使用JDBC.


通过Hibernate调用存储过程。

Connection con = session.connection();String sql="{call 存储过程名(?)}";Callablestatement c = con.prepareCall(sql);c.setString(xxx,xxx);c.executeUpdate();

0 0