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对象,这个时候Session将cat这个对象放入entityEntries,用来标记cat已经和当前的会话建立了关联,由于应用对cat做了保存的操作,Session还要在insertions中登记应用的这个插入行为(行为包括:对象引用、对象id、Session、持久化处理类)。
(3)s.evict(cat)将cat对象从s会话中拆离,这时s会从entityEntries中将cat这个对象移出。
(4)事务提交,需要将所有缓存flush入数据库,Session启动一个事务,并按照insert,update,……,delete的顺序提交所有之前登记的操作(注意:所有insert执行完毕后才会执行update,这里的特殊处理也可能会将你的程序搞得一团糟,如需要控制操作的执行顺序,要善于使用flush),现在cat不在entityEntries中,但在执行insert的行为时只需要访问insertions就足够了,所以此时不会有任何的异常。异常出现在插入后通知Session该对象已经插入完毕这个步骤上,这个步骤中需要将entityEntries中cat的existsInDatabase标志置为true,由于cat并不存在于entityEntries中,此时Hibernate就认为insertions和entityEntries可能因为线程安全的问题产生了不同步(也不知道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关联映射:
- one-to-one:
- one-to-many:
- many-to-one: