hibernate的三种持久化生命周期

即瞬时、持久和分离

把实例从瞬时状态转换为持久状态有两种方式:调用持久管理器的save()方法或者从已经存在的持久实例中创建引用。第二种方式中,不必在事务结束时把内存中的每个持久对象的状态更新到数据库中对应的行上。ORM软件有一种机制来检测哪个持久对象已经被应用程序在事务中修改了,我们称其为自动脏数据检查。Hibernate在SQLUPDATE 语句中默认包含所有的列。如果仅仅希望更新修改过的列,你可以在类映射中通过把dynamic-update 设为true。

分离:当关闭Session 时这些实例就失去了同持久管理器的关联,我们把这些对象称为分离的。Hibernate也提供了一个显式的分离操作:Session的evict()方法。

应用程序可能(通常)含有事务(及持久管理器)之外的分离对象的引用。Hibernate 可以让你同新的持久管理器重新关联这些实例以便在新事务中重用这些实例,是hibernate的主要卖点。

来看看Java标识a=b 与数据库标识a.getId().equals( b.getId() )之间的关系。有时它们是相等的,有时却不相等。我们把Java 标识等于数据库标识的情况称为对象标识范围(scope of object identity)。
在这个范围内,通常有三种选择:
1.没有标识范围(no identity scope)的简单持久层不能保证如果某一行被访问两次,应用程序能够返回相同的Java 对象实例。如果应用程序在一个单独的事务中修改了代表相同行的两个不同的实例将会出问题(你怎样决定哪一个状态将会同数据库同步?)。
2.使用事务范围标识(transaction-scoped identity)的持久层保证在单独的事务上下文中,仅仅有一个对象实例代表数据库中的某一行。这就避免了前面那个问题,并且允许做一些事务级的缓存。
3.过程范围标识(process-scoped identity)更进一步,它能保证在整个过程(JVM)中只有一个对象实例代表某一行。                                                                                                                                                                                对于典型的网络或企业应用程序,事务范围标识是首选的。 过程范围标识在利用缓存和多个事务重用实例的编程模型方面有一些潜在的优点;然而在普遍的多线程应用程序中,同步共享访问全局标识图中的持久对象要花费很大代价。在每个事务范围内每个线程只同完全不同的一组持久实例工作将会更加简单                        Session session1 = sessions.openSession();
Transaction tx1 = session1.beginTransaction();
// Load Category with identifier value "1234"
Object a = session1.load(Category.class, new Long(1234) );
Object b = session1.load(Category.class, new Long(1234) );
if ( a==b ) {
System.out.println("a and b are identical.");
}
tx1.commit();
session1.close();
Session session2 = sessions.openSession();
Transaction tx2 = session2.beginTransaction();
Object b2 = session2.load(Category.class, new Long(1234) );
if ( a!=b2 ) {
System.out.println("a and b2 are not identical.");
}
tx2.commit();
session2.close();
由于对象引用a和b 在相同的Session中装载,它们不仅有相同的数据库标识,而且有相同的Java标识。然而,一旦超出了这种界限,Hibernate 就不能保证Java 标识是相等的,因此,a 和b2 是不相等的,信息打印在控制台上。当然,测试数据库标识--a.getId().equals( b2.getId() )—将仍然返回true。

你可能感兴趣的:(hibernate的三种持久化生命周期)