第十二节:Hibernate 事务隔离,对象状态
- 瞬时态:当new一个实体对象后,这个对象处于瞬时态,即这个对象只是一个保存临时数据的内存区域,如果没有变量引用这个对象,则会被JVM的垃圾回收机制回收。这个对象所保存的数据与数据库没有任何关系,除非通过Session的save()、saveOrUpdate()、persist()、merge()方法把瞬时态对象与数据库关联,并把数据插入或者更新到数据库,这个对象才转换为持久态对象。
- 持久态:持久态对象的实例在数据库中有对应的记录,并拥有一个持久化标识(ID)。对持久态对象进行delete操作后,数据库中对应的记录将被删除,那么持久态对象与数据库记录不再存在对应关系,持久态对象变成移除态(可以视为瞬时态)。持久态对象被修改变更后,不会马上同步到数据库,直到数据库事务提交。
- 游离态:当Session进行了close()、clear()、evict()或flush()后,实体对象从持久态变成游离态,对象虽然拥有持久和与数据库对应记录一致的标识值,但是因为对象已经从会话中清除掉,对象不在持久化管理之内,所以处于游离态(也叫脱管态)。游离态的对象与临时状态对象是十分相似的,只是它还含有持久化标识。
Hibernate事务隔离级别:
隔离级别 | 脏读 (Dirty Read) | 不可重复读(NonRepeatable Read) | 幻读 (Phantom Read) |
读操作未提交 (Read uncommitted) | 可能 | 可能 | 可能 |
读操作已提交 (Read commited) | 不可能 | 可能 | 可能 |
可重复读 (Repeatable read) | 不可能 | 不可能 | 可能 |
可串行化 (Serializable) | 不可能 | 不可能 | 不可能 |
设置隔离级别:
<property name=”hibernate.connection.isolation”>4</property> //可填1,2,4(不可重复读),8
在以下的情况下,Hibernate会调用flush():
(1) 事务提交时,如果flush模式不为FlushMode.NEVER, commit()将调用flush().
(2) 在某些查询语句之前(此查询语句已经改变了数据库状态,所以需要调用flush()以同步数据,使查出来的数据是经过更改的)
(3) 当程序强制调用session.flush时。
在一个事务中调用一个select 查询,如果此查询之前已经有某个update语句做了数据修改(注意此update语句并没有真正执行),则首先会调用flush(),使update对数据库操作成功,接着才返回查询数据。
FlushMode有以下几种:
(1) FlushMode.AUTO: 数据有更改,则在查询前更新此改动,以保证数据同步.
(2) FlushMode.COMMIT: 在事务结束之前刷新session
(3) FlushMode.NEVER: 仅在明确调用flush()时才对数据库进行同步.
在Hibernate中使用JDBC事务:
Hibernate.transaction.factory_class=net.sf.hibernate.transaction.JDBCTransactionFactory
使用JTA 事务:
在一个具有多个数据库的系统中,可能一个程序将会调用几个数据库中的数据,需要一种分布式事务,或者准备用JTA来管理跨Session的长事务,那么就需要使用JTATransaction.
Hibernate中对数据的锁定:
如果要在事务中使用悲观锁,则可以像下面这样写:
Transaction tx=session.beginTransaction();
//取得持久化User对象,并使用LockMode.UPGRADE模式锁定对象
User user=(User)session.get(User.class,LockMode.UPGRADE);
user.setName(“newName”); //更改对象属性,注意并不需要使用session.save(user)
tx.commit();
这样的话,Hibernate会使用select …… for update 语句载入User类,并且锁住了这个对象在数据库中的列,直到事务完成(commit()以后)。
Hibernate 可以利用Query或者Criteria的setLockMode()方法来设定要锁定的表或列(Row)及其锁定模式。可设定的模式有两个:
(1) LockMod.UPGRADE
(2) LockMode.UPDGRADE_NOWAIT: