📄 objectstate.html
字号:
对象发生了一些改动 </p></li><li><p> 该对象被返回到业务逻辑层 </p></li><li><p> 程序调用第二个session的<tt class="literal">update()</tt>方法持久这些改动 </p></li></ul></div><p> <tt class="literal">saveOrUpdate()</tt>做下面的事: </p><div class="itemizedlist"><ul type="disc" compact><li><p> 如果对象已经在本session中持久化了,不做任何事 </p></li><li><p> 如果另一个与本session关联的对象拥有相同的持久化标识(identifier),抛出一个异常 </p></li><li><p> 如果对象没有持久化标识(identifier)属性,对其调用<tt class="literal">save()</tt> </p></li><li><p> 如果对象的持久标识(identifier)表明其是一个新实例化的对象,对其调用<tt class="literal">save()</tt> </p></li><li><p> 如果对象是附带版本信息的(通过<tt class="literal"><version></tt>或<tt class="literal"><timestamp></tt>) 并且版本属性的值表明其是一个新实例化的对象,<tt class="literal">save()</tt>它。 </p></li><li><p> 否则<tt class="literal">update()</tt> 这个对象 </p></li></ul></div><p> <tt class="literal">merge()</tt>可非常不同: </p><div class="itemizedlist"><ul type="disc" compact><li><p> 如果session中存在相同持久化标识(identifier)的实例,用用户给出的对象的状态覆盖旧有的持久实例 </p></li><li><p> 如果session没有相应的持久实例,则尝试从数据库中加载,或创建新的持久化实例 </p></li><li><p> 最后返回该持久实例 </p></li><li><p> 用户给出的这个对象没有被关联到session上,它依旧是脱管的 </p></li></ul></div></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="objectstate-deleting"></a>11.8. 删除持久对象</h2></div></div><div></div></div><p> 使用<tt class="literal">Session.delete()</tt>会把对象的状态从数据库中移除。 当然,你的应用程序可能仍然持有一个指向已删除对象的引用。所以,最好这样理解:<tt class="literal">delete()</tt>的用途是把一个持久实例变成瞬时(transient)实例。 </p><pre class="programlisting">sess.delete(cat);</pre><p> 你可以用你喜欢的任何顺序删除对象,不用担心外键约束冲突。当然,如果你搞错了顺序,还是有可能引发在外键字段定义的<tt class="literal">NOT NULL</tt>约束冲突。 例如你删除了父对象,但是忘记删除孩子们。 </p></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="objectstate-replicating"></a>11.9. 在两个不同数据库间复制对象</h2></div></div><div></div></div><p> 偶尔会用到不重新生成持久化标识(identifier),将持久实例以及其关联的实例持久到不同的数据库中的操作。 </p><pre class="programlisting">//retrieve a cat from one databaseSession session1 = factory1.openSession();Transaction tx1 = session1.beginTransaction();Cat cat = session1.get(Cat.class, catId);tx1.commit();session1.close();//reconcile with a second databaseSession session2 = factory2.openSession();Transaction tx2 = session2.beginTransaction();session2.replicate(cat, ReplicationMode.LATEST_VERSION);tx2.commit();session2.close();</pre><p> <tt class="literal">ReplicationMode</tt>决定数据库中已存在相同行时,<tt class="literal">replicate()</tt>如何处理。 </p><div class="itemizedlist"><ul type="disc" compact><li><p> <tt class="literal">ReplicationMode.IGNORE</tt> - 忽略它 </p></li><li><p> <tt class="literal">ReplicationMode.OVERWRITE</tt> - 覆盖相同的行 </p></li><li><p> <tt class="literal">ReplicationMode.EXCEPTION</tt> - 抛出异常 </p></li><li><p> <tt class="literal">ReplicationMode.LATEST_VERSION</tt> - 如果当前的版本较新,则覆盖,否则忽略 </p></li></ul></div><p> 这个功能的用途包括使录入的数据在不同数据库中一致,产品升级时升级系统配置信息,回滚non-ACID事务中的修改等等。 (译注,non-ACID,非ACID;ACID,Atomic,Consistent,Isolated and Durable的缩写) </p></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="objectstate-flushing"></a>11.10. Session刷出(flush)</h2></div></div><div></div></div><p> 每间隔一段时间,<tt class="literal">Session</tt>会执行一些必需的SQL语句来把内存中的对象的状态同步到JDBC连接中。这个过程被称为<span class="emphasis"><em>刷出(flush)</em></span>,默认会在下面的时间点执行: </p><div class="itemizedlist"><ul type="disc" compact><li><p> 在某些查询执行之前 </p></li><li><p> 在调用<tt class="literal">org.hibernate.Transaction.commit()</tt>的时候 </p></li><li><p> 在调用<tt class="literal">Session.flush()</tt>的时候 </p></li></ul></div><p> 涉及的SQL语句会按照下面的顺序发出执行: </p><div class="orderedlist"><ol type="1" compact><li><p> 所有对实体进行插入的语句,其顺序按照对象执行<tt class="literal">Session.save()</tt>的时间顺序 </p></li><li><p> 所有对实体进行更新的语句 </p></li><li><p> 所有进行集合删除的语句 </p></li><li><p> 所有对集合元素进行删除,更新或者插入的语句 </p></li><li><p> 所有进行集合插入的语句 </p></li><li><p> 所有对实体进行删除的语句,其顺序按照对象执行<tt class="literal">Session.delete()</tt>的时间顺序 </p></li></ol></div><p> (有一个例外是,如果对象使用<tt class="literal">native</tt>方式来生成ID(持久化标识)的话,它们一执行save就会被插入。) </p><p> 除非你明确地发出了<tt class="literal">flush()</tt>指令,关于Session<span class="emphasis"><em>何时</em></span>会执行这些JDBC调用是完全无法保证的,只能保证它们执行的前后顺序。 当然,Hibernate保证,<tt class="literal">Query.list(..)</tt>绝对不会返回已经失效
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -