🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
# 10.6\. 修改脱管(Detached)对象 很多程序需要在某个事务中获取对象,然后将对象发送到界面层去操作,最后在一个新的事务保存所做的修改。 在高并发访问的环境中使用这种方式,通常使用附带版本信息的数据来保证这些“长“工作单元之间的隔离。 Hibernate通过提供`Session.update()`或`Session.merge()` 重新关联脱管实例的办法来支持这种模型。 ``` // in the first session Cat cat = (Cat) firstSession.load(Cat.class, catId); Cat potentialMate = new Cat(); firstSession.save(potentialMate); // in a higher layer of the application cat.setMate(potentialMate); // later, in a new session secondSession.update(cat); // update cat secondSession.update(mate); // update mate ``` 如果具有`catId`持久化标识的`Cat`之前已经被`另一Session(secondSession)`装载了, 应用程序进行重关联操作(reattach)的时候会抛出一个异常。 如果你确定当前session没有包含与之具有相同持久化标识的持久实例,使用`update()`。 如果想随时合并你的的改动而不考虑session的状态,使用`merge()`。 换句话说,在一个新session中通常第一个调用的是`update()`方法,以便保证重新关联脱管(detached)对象的操作首先被执行。 如果希望相关联的脱管对象(通过引用“可到达”的脱管对象)的数据也要更新到数据库时(并且也_仅仅_在这种情况), 可以对该相关联的脱管对象单独调用`update()` 当然这些可以自动完成,即通过使用_传播性持久化(transitive persistence)_,请看[第 10.11 节 “传播性持久化(transitive persistence)”](../Text/pr01_split_000.html "10.11\. 传播性持久化(transitive persistence)")。 `lock()`方法也允许程序重新关联某个对象到一个新session上。不过,该脱管(detached)的对象必须是没有修改过的! ``` //just reassociate: sess.lock(fritz, LockMode.NONE); //do a version check, then reassociate: sess.lock(izi, LockMode.READ); //do a version check, using SELECT ... FOR UPDATE, then reassociate: sess.lock(pk, LockMode.UPGRADE); ``` 请注意,`lock()`可以搭配多种`LockMode`, 更多信息请阅读API文档以及关于事务处理(transaction handling)的章节。重新关联不是`lock()`的唯一用途。 其他用于长时间工作单元的模型会在[第 11.3 节 “乐观并发控制(Optimistic concurrency control)”](../Text/pr01_split_000.html "11.3\. 乐观并发控制(Optimistic concurrency control)")中讨论。