hibernate之对象同一性和等同性

来源:互联网 发布:string在java中是什么意思 编辑:程序博客网 时间:2024/04/30 08:42
hibernate之对象同一性和等同性

-------------------------
关于对话
当来自应用程序用户的一个请求需要数据访问时,就启动一个新的工作单元。这个工作单元在处理结束时终止,并为客户准备好了响应。这也被称作每次请求一个会话策略。(这里可以用持久化上下文代替会话)
hibernate可以支持一个可能长期运行的工作单元的实现,称作对话。
例如,在web应用程序中,用户花了很长的时间思考修改,但是由于可伸缩性的原因,必须保持数据库事务的简短,并尽快释放数据库资源。每当需要引导用户通过几个屏幕完成一个工作单元时,可能面对这个问题。可以用最少的代码和最佳的可伸缩性实现这样一个对话。
有两种策略可以在hibernate应用程序中实现对话:1. 利用脱管对象。2.通过扩展一个持久化上下文。
. 利用脱管对象
脱管对象状态和已经提到过的重附或者合并的特性是实现该对话的方法。用户在思考时间期间对象以脱管状态保存,并且这些对象的任何修改都通过重附或者合并被手工变成持久化。这一策略也被称作利用脱管对象每次请求一个会话。持久化上下文只跨一个特定的请求的处理,对话期间应用程序手工重附和合并实体实例。
. 通过扩展一个持久化上下文
这里不需要手工重附或者合并:利用每次对话一个会话模式,把一个持久化上下文扩展到跨整个工作单元。
---------------------------
关于对象同一性的范围
理解java同一性a==b和数据库同一性a.getId().equals(b.getId())之间的关系非常重要。有时候它们是相等的,有时候不等。我们把java同一性等价于数据库同一性的条件称作对象同一性的范围。
范围有:
1. 持久化上下文范围的同一性,保证在单个持久化上下文的范围中,只有一个对象实例表示一个特定的数据库行。还允许在上下文级高速缓存。
2. 过程范围的同一性更进一步保证在整个过程(JVM)中只有一个对象实例表示该行。
对于典型的web或者企业应用程序,持久化上下文范围的同一性是首选。过程范围的同一性的确对跨多个工作单元的实例重用,在高速缓存利用和编程模型方面提供了一些潜在的优势。但是,在一个遍布多线程的应用程序中,始终在全局的同一性映射中同步对持久化对象的共享访问成本太高,难以支付。更简单并且更可伸缩些的办法是,让每个线程在每个持久化上下文中使用一组独特的持久化实例。
hibernate同一性范围是持久化上下文的范围。因此,hibernate天生最适合多用户应用程序中高并发的数据访问。然而,我们已经提到过一些在对象不与持久化上下文关联时会遇到的问题。让我们用一个示例来讨论这个话题:
 
对象引用a和b,不仅有着相同的数据库同一性,而且还有相同的java同一性,因为它们是在相同的Session中获得的。它们引用那个工作单元的持久化上下文中所知道的同一个持久化实例。一旦出了这个范围,hibernate就不保证java同一性了,因此a和c不相等。当然,测试数据库同一性的a.getId().equals(c.getId()),将仍然返回true。
-----------------------------
脱管对象的同一性
如果对象引用离开了受保护的同一性范围,那么就称它为脱管对象引用。在上面代码中,如果只考虑数据库同一性---它们的主键值,则所有三个对象引用a,b和c都相等。然而,它们不是相等的内存对象实例。如果你在脱管状态下把它们作为相等处理,就会产生问题。每当使用脱管状态下的对象时,特别在给同一性进行测试时,就需要为持久化类提供自己的equal()和hashCode()方法的实现。假设你想要使用脱管对象,并且必须用自己的子程序测试它们的等同性。可以通过几种方式实现equal()和hashCode()。记住,在覆盖equal()时,始终也需要覆盖hashCode(),以便这两种方法保持一致。如果两个对象相等,它们就必须有相同的散列码。
虽然可以通过几种方式实现等同性,但我们推荐利用业务键实现。业务键是一种属性,或者一些属性的组合,它对于每个包含相同的数据库同一性的实例来说是唯一的。本质上,它就是你要使用的自然键,如果你没有正在使用代理主键来代替的话。业务键不同于自然键,它的永远不变并非绝对的必备条件---只要它很少改变,就足够了。业务键等同性意味着equals()方法只比较构成业务键的属性,这是个完美的解决方案,唯一的缺点是它需要特别记着先辨别正确的业务键。
对于一些其他的类,业务键可能更加复杂,由一个属性的组合组成,以下是一些提示,帮助你在类中辨别业务键:
1. 考虑当应用程序的用户必须辨别一个对象(在现实世界中)时,他们会引用什么属性。
2. 每个不可变的属性都可能是一个好的备选业务键。
3. 每个包含UNIQUE数据库约束的属性都是好的备选业务键。记住,业务键的精确度必须好到足以避免重叠。
4. 也可以考虑使用被关联对象的数据库标识符。
-----------------------------
扩展持久化上下文
一个特定的对话为所有交互重用相同的持久化上下文。对话期间的所有请求处理都由相同的持久化上下文管理。当来自用户的请求被处理之后,持久化上下文没有关闭。在用户思考时间内,它断开与数据库的连接,并保持这种状态。当用户在对话中继续时,持久化上下文被重新连接到数据库,就可以处理下一个请求了。对话结束时,持久化上下文与数据库同步并关闭。