Hibernate的flush机制深入

来源:互联网 发布:淘宝格子铺登陆网址 编辑:程序博客网 时间:2024/05/21 12:40

Hibernate flush 机制:(执行save,update操作时,只是登记行为,flush时真正执行将登记行为插入数据库根据insert,update,……,delete的顺序提交所有登记的操作)

//异常:unsafe use of the session

Transaction tran = s.beginTransaction(); (1)

s.save(cat); (2)(此处同样可以为update delete)

s.flush();// 提前flush,将缓存登记行为提交到数据库

s.evict(cat); (3) //s会从entityEntries中将cat这个对象移出

tran.commit(); (4) //将entityEntries中cat的existsInDatabase标志置为true,由于cat并不存在于entityEntries中,会报异常

s.close();(5)

(1)生成一个事务的对象,并标记当前的Session处于事务状态(注:此时并未启动数据库级事务)。

(2)应用使用s.save保存cat对象,这个时候Sessioncat这个对象放入entityEntries,用来标记cat已经和当前的会话建立了关联,由于应用对cat做了保存的操作,Session还要在insertions中登记应用的这个插入行为(行为包括:对象引用、对象idSession、持久化处理类)。

(3)s.evict(cat)cat对象从s会话中拆离,这时s会从entityEntries中将cat这个对象移出。

(4)事务提交,需要将所有缓存flush入数据库,Session启动一个事务,并按照insert,update,……,delete的顺序提交所有之前登记的操作(注意:所有insert执行完毕后才会执行update,这里的特殊处理也可能会将你的程序搞得一团糟,如需要控制操作的执行顺序,要善于使用flush),现在cat不在entityEntries中,但在执行insert的行为时只需要访问insertions就足够了,所以此时不会有任何的异常。异常出现在插入后通知Session该对象已经插入完毕这个步骤上,这个步骤中需要将entityEntriescatexistsInDatabase标志置为true,由于cat并不存在于entityEntries中,此时Hibernate就认为insertionsentityEntries可能因为线程安全的问题产生了不同步(也不知道Hibernate的开发者是否考虑到例子中的处理方式,如果没有的话,这也许算是一个bug吧),于是一个net.sf.hibernate.AssertionFailure就被抛出,程序终止。

commit() 和flush() 的区别:

commit() 调用之前会调用flush提交数据库,然后提交事务,告诉该事务已经提交。数据已经持久化

flush()后只是将Hibernate缓存中的数据提交到数据库,将登记行为中数据提交到数据库

缓存flush顺序:

Hibernate按照insert,update,……,delete的顺序提交所有登记的操作

OpenSessionInViewFilter

 Spring+Hibernate中,  集合映射如果使用lazy="true" PO传到View层时, 出现未初始化session已关闭的错误,只能在dao先初始化

OpenSessionInView模式后造成了内存和数据库连接问题 :

Session的生命周期变得非常长。虽然解决了Lazy Load的问题,但是带来的问题就是Hibernate的一级缓存,也就是Session级别的缓存的生命周期会变得非常长,那么如果你在你的Service层做大批量的数据操作时,其实这些数据会在缓存中保留一份,这是非常耗费内存的。还有一个数据库连接的问题,存在的原因在于由于数据库的Connection是和Session绑在一起的,所以,Connection也会得不到及时的释放。因而当系统出现业务非常繁忙,而计算量又非常大的时候,往往数据连接池的连接数会不够

SessionFactory负责创建Session,SessionFactory是线程安全的,多个并发线程可以同时访问一个SessionFactory 并从中获取Session 实例。而
Session并非线程安全,也就是说,如果多个线程同时使用一个Session实例进行数据存取,则将会导致Session 数据存取逻辑混乱

SessionFactory:线程安全

Session:线程不安全,它代表与数据库之间的一次操作

主键策略:

native:主键生成工作交由数据库控制

assigned:赋值主键

sequence:sequence序列器

foregin:关联对象作为标识 one-to-one

<class name="com.whl.entity.Person" table="tbl_person">

   <id name="id">

    <generator class="foreign">

    <param name="property">idCard</param>

</generator>

     //声明该表主键作为外键参照idCard.id,constrained="true"关键起作用

   </id>

 <property name="name" column="user_name"/>

 <one-to-one name="idCard" constrained="true"></one-to-one>

 </class>

hibernate关联映射:

  1. one-to-one:
  2. one-to-many:
  3. many-to-one:

0 0