企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# 11.1.3\. 关注对象标识(Considering object identity) 应用程序可能在两个不同的`Session`中并发访问同一持久化状态,但是, 一个持久化类的实例无法在两个 `Session`中共享。因此有两种不同的标识语义: 数据库标识 `foo.getId().equals( bar.getId() )` JVM 标识 `foo==bar` 对于那些关联到 _特定_`Session` (也就是在单个`Session`的范围内)上的对象来说,这 两种标识的语义是等价的,与数据库标识对应的JVM标识是由Hibernate来保 证的。不过,当应用程序在两个不同的session中并发访问具有同一持久化标 识的业务对象实例的时候,这个业务对象的两个实例事实上是不相同的(从 JVM识别来看)。这种冲突可以通过在同步和提交的时候使用自动版本化和乐 观锁定方法来解决。 这种方式把关于并发的头疼问题留给了Hibernate和数据库;由于在单个线程内,操作单元中的对象识别不 需要代价昂贵的锁定或其他意义上的同步,因此它同时可以提供最好的可伸缩性。只要在单个线程只持有一个 `Session`,应用程序就不需要同步任何业务对象。在`Session` 的范围内,应用程序可以放心的使用`==`进行对象比较。 不过,应用程序在`Session`的外面使用`==`进行对象比较可能会 导致无法预期的结果。在一些无法预料的场合,例如,如果你把两个脱管对象实例放进同一个 `Set`的时候,就可能发生。这两个对象实例可能有同一个数据库标识(也就是说, 他们代表了表的同一行数据),从JVM标识的定义上来说,对脱管的对象而言,Hibernate无法保证他们 的的JVM标识一致。开发人员必须覆盖持久化类的`equals()`方法和 `hashCode()` 方法,从而实现自定义的对象相等语义。警告:不要使用数据库标识 来实现对象相等,应该使用业务键值,由唯一的,通常不变的属性组成。当一个瞬时对象被持久化的时 候,它的数据库标识会发生改变。如果一个瞬时对象(通常也包括脱管对象实例)被放入一 个`Set`,改变它的hashcode会导致与这个`Set`的关系中断。虽 然业务键值的属性不象数据库主键那样稳定不变,但是你只需要保证在同一个`Set` 中的对象属性的稳定性就足够了。请到Hibernate网站去寻求这个问题更多的详细的讨论。请注意,这不是一 个有关Hibernate的问题,而仅仅是一个关于Java对象标识和判等行为如何实现的问题。