Hibernate的session中的flush

什么是Hibernate Session刷出(flush)?也许大家对此不够了解,但相信你看完本文一定有很大的收益。

每间隔一段时间,Session会执行一些必需的SQL语句来把内存中的对象的状态同步到JDBC连接中。这个过程被称为Hibernate Session刷出(flush)。

<wbr></wbr>

默认会在下面的时间点执行:

<wbr></wbr>

◆在某些查询执行之前

◆在调用org.hibernate.Transaction.commit()的时候

◆在调用Session.flush()的时候

◆涉及的SQL语句会按照下面的顺序发出执行:

◆所有对实体进行插入的语句,其顺序按照对象执行Session.save()的时间顺序

◆所有对实体进行更新的语句

◆所有进行集合删除的语句

◆所有对集合元素进行删除,更新或者插入的语句

◆所有进行集合插入的语句

◆所有对实体进行删除的语句,其顺序按照对象执行Session.delete()的时间顺序

(有一个例外是,如果对象使用native方式来生成ID(持久化标识)的话,它们一执行save就会被插入。)

<wbr></wbr>

除非你明确地发出了flush()指令,关于Session何时会执行这些JDBC调用是完全无法保证的,只能保证它们执行的前后顺序。 当然,Hibernate保证,Query.list(..)绝对不会返回已经失效的数据,也不会返回错误数据。

<wbr></wbr>

也可以改变默认的设置,来让Hibernate Session刷出(flush)操作发生的不那么频繁。 FlushMode类定义了三种不同的方式。仅在提交时刷出(仅当Hibernate的Transaction API被使用时有效), 按照刚才说的方式刷出,以及除非明确使用flush()否则从不刷出。最后一种模式对于那些需要长时间保持Session为打开或者断线状态的长时间运行的工作单元很有用。

<wbr></wbr>

sess = sf.openSession();<wbr><br> Transaction tx = sess.beginTransaction();</wbr>

<wbr></wbr>

// allow queries to return stale state<wbr><wbr><br> sess.setFlushMode(FlushMode.COMMIT);<wbr><wbr><br> Cat izi = (Cat) sess.load(Cat.class, id);<wbr><br> izi.setName(iznizi);<wbr><br><wbr><br> // might return stale data<wbr><br> sess.find("from Cat as cat left outer join cat.kittens kitten");<wbr><br><wbr><br> // change to izi is not flushed!</wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr></wbr>

tx.commit(); // flush occurs<wbr></wbr>

sess.close();

<wbr></wbr>

Hibernate Session刷出(flush)期间,可能会抛出异常。(例如一个DML操作违反了约束)异常处理涉及到对Hibernate事务性行为的理解,这里在事务和并发中有具体的介绍,这里我们就不加以介绍了。

<wbr></wbr>

还有一种情况很值得我们注意——插入大量数据的时候

例如,我现在要插入10000个User,咋办?

很多人会想这样:

Transaction tx = session.beginTransaction();

for(int i=0;i<10000;i++)

{

<wbr><wbr><wbr> User u = new User(......);</wbr></wbr></wbr>

<wbr><wbr><wbr> session.save(u);</wbr></wbr></wbr>

}

tx.commit();

session.close();

<wbr></wbr>

但随着程序的运行,总会在某一个时间点失败。并且抛出OutOfMemoryException(内存溢出)异常!

这是因为Hibernate的session持有一个必选的一级缓存,所有的User实例都将在session级别的缓存区进行缓存。但缓存区“装不下了”。

<wbr></wbr>

那么如何解决?

解决方案:定时将session的缓存刷入数据库!

for(int i=0;i<10000;i++)

{

<wbr><wbr><wbr> User u = new User(......);</wbr></wbr></wbr>

<wbr><wbr><wbr> session.save(u);</wbr></wbr></wbr>

<wbr><wbr><wbr> for(i ==0)</wbr></wbr></wbr>

<wbr><wbr><wbr> {</wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr> session.flush();</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr><wbr><wbr><wbr><wbr> session.close();</wbr></wbr></wbr></wbr></wbr></wbr></wbr>

<wbr><wbr><wbr> }</wbr></wbr></wbr>

}

tx.commit();

session.close();

<wbr></wbr>

参考地址:http://developer.51cto.com/art/200909/153860.htm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值