📄 manipulatingdata.html
字号:
pk.getKittens(), "select this.mate where this.color = eg.Color.BLACK");</pre></div><div class="sect2" lang="zh-cn"><div class="titlepage"><div><div><h3 class="title"><a name="manipulatingdata-criteria"></a>9.3.5. 条件查询</h3></div></div><div></div></div><p> HQL极为强大,但是有些人希望能够动态的使用一种面向对象API创建查询,而非在他们的Java代码中嵌入字符串。对于那部分人来说,Hibernate提供了一种直观的<tt class="literal">Criteria</tt>查询API。 </p><pre class="programlisting">Criteria crit = session.createCriteria(Cat.class);crit.add( Expression.eq("color", eg.Color.BLACK) );crit.setMaxResults(10);List cats = crit.list();</pre><p> 如果你对类似于SQL的语法不是感觉很舒服的话,用这种方法开始使用Hibernate可能更容易。这种API也比HQL更可扩展。程序可以提供它们自己的<tt class="literal">Criterion</tt>接口的实现。 </p></div><div class="sect2" lang="zh-cn"><div class="titlepage"><div><div><h3 class="title"><a name="manipulatingdata-nativesql"></a>9.3.6. 使用本地SQL的查询</h3></div></div><div></div></div><p> 你可以使用<tt class="literal">createSQLQuery()</tt>方法,用SQL来表达查询。你必须把SQL别名用大括号包围起来。 </p><pre class="programlisting">List cats = session.createSQLQuery( "SELECT {cat.*} FROM CAT {cat} WHERE ROWNUM<10", "cat", Cat.class).list();</pre><pre class="programlisting">List cats = session.createSQLQuery( "SELECT {cat}.ID AS {cat.id}, {cat}.SEX AS {cat.sex}, " + "{cat}.MATE AS {cat.mate}, {cat}.SUBCLASS AS {cat.class}, ... " + "FROM CAT {cat} WHERE ROWNUM<10", "cat", Cat.class).list()</pre><p> 和Hibernate查询一样,SQL查询也可以包含命名参数或者顺序参数。 </p></div></div><div class="sect1" lang="zh-cn"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="manipulatingdata-updating"></a>9.4. 更新对象</h2></div></div><div></div></div><div class="sect2" lang="zh-cn"><div class="titlepage"><div><div><h3 class="title"><a name="manipulatingdata-updating-insession"></a>9.4.1. 在同一Session中更新</h3></div></div><div></div></div><p> <span class="emphasis"><em>事务中的持久化实例</em></span>(就是通过<tt class="literal">session</tt>装载、保存、创建或者查询出的对象)可以被程序操作,所做的任何修改都会在<tt class="literal">Session</tt><span class="emphasis"><em>同步(flushed)</em></span>的时候被持久化(本章后面会详细讨论)。所以最直接的更改一个对象的方法就是<tt class="literal">load()</tt>它,保持<tt class="literal">Session</tt>打开,然后直接修改即可: </p><pre class="programlisting">DomesticCat cat = (DomesticCat) sess.load( Cat.class, new Long(69) );cat.setName("PK");sess.flush(); // changes to cat are automatically detected and persisted</pre><p> 有些时候这种编程模式显得效率不高,因为它需要在同一个session中先使用SQL <tt class="literal">SELECT</tt>(来装载对象),又有一个SQL <tt class="literal">UPDATE</tt>(来把修改的状态写回)。因此,Hibernate提供了另一种方式。 </p></div><div class="sect2" lang="zh-cn"><div class="titlepage"><div><div><h3 class="title"><a name="manipulatingdata-updating-detached"></a>9.4.2. 更新从session脱离的对象</h3></div></div><div></div></div><p> 很多程序需要在一个事务中获取对象,然后发送到界面层去操作,用一个新的事务来保存修改。(在高同步访问的环境中使用这种方式,经常使用附带版本的数据来保证事务独立性。)这种方法需要和上一节所描述的略微不同的编程模型。Hibernate支持这种模型,因为它提供了<tt class="literal">Session.update()</tt>方法。 </p><pre class="programlisting">// in the first sessionCat cat = (Cat) firstSession.load(Cat.class, catId);Cat potentialMate = new Cat();firstSession.save(potentialMate);// in a higher tier of the applicationcat.setMate(potentialMate);// later, in a new sessionsecondSession.update(cat); // update catsecondSession.update(mate); // update mate</pre><p> 如果拥有<tt class="literal">catId</tt>标识符的<tt class="literal">Cat</tt>在试图update它之前已经被<tt class="literal">secondSession</tt>装载了,会抛出一个异常。 </p><p> 对于给定的临时实例,<span class="emphasis"><em>当且仅当</em></span> 它们触及的其他临时实例需要保存的时候, 应用程序应该对它们分别各自使用<tt class="literal">update()</tt>。(自动管理生命周期的对象(lifecycle object)除外,后面会讨论到。) </p><p> Hibernate用户曾经要求有一个通用的方法,可以为新建的临时实例生成标识符并保存,或者保存已经存在标识符的临时实例的改动。<tt class="literal">saveOrUpdate()</tt>方法就是用来提供这个功能的。 </p><p> Hibernate通过对象的标识符的值(或version,或timestamp时间戳)来分辨这是一个“新”(未保存过的)实例,还是一个“已存在”(已经保存或者从先前的session中装载的)的实例。<tt class="literal">id</tt>映射中的<tt class="literal">unsaved-value</tt>(或<tt class="literal"><version></tt>,或 <tt class="literal"><timestamp></tt>)用来指定哪个值被用于表示“新”实例。 </p><pre class="programlisting"><id name="id" type="long" column="uid" unsaved-value="null"> <generator class="hilo"/></id></pre><p> <tt class="literal">unsaved-value</tt>允许的取值包括: </p><div class="itemizedlist"><ul type="disc" compact><li><p> <tt class="literal">any</tt> - always save 永远保存 </p></li><li><p> <tt class="literal">none</tt> - always update 永远更新 </p></li><li><p> <tt class="literal">null</tt> - 当标识符是空的时候保存(默认情况) </p></li><li><p> valid identifier value (合法的标识符值)- 当标识符是null或者这个给定的值时保存 </p></li><li><p> <tt class="literal">undefined</tt> - 对于<tt class="literal">version</tt> 或 <tt class="literal">timestamp</tt>来说的默认值。此时使用标识符检查。(原文: the default for <tt class="literal">version</tt> or <tt class="literal">timestamp</tt>, then identifier check is used.参见下文有进一步描述.) </p></li></ul></div><pre class="programlisting">// in the first sessionCat cat = (Cat) firstSession.load(Cat.class, catID);// in a higher tier of the applicationCat mate = new Cat();cat.setMate(mate);// later, in a new sessionsecondSession.saveOrUpdate(cat); // update existing state (cat has a non-null id)secondSession.saveOrUpdate(mate); // save the new instance (mate has a null id)</pre><p> <tt class="literal">saveOrUpdate()</tt>的用法和语义看来对初学者来说容易造成困惑。首先,如果你还没有试图在另一个新session中使用来自原session的实例,你根本就不需要使用<tt class="literal">update()</tt>或者<tt class="literal">saveOrUpdate()</tt>方法。有一些程序完全不需要使用这些方法。 </p><p> 通常,<tt class="literal">update()</tt>或<tt class="literal">saveorUpdate()</tt>方法在下列情形下使用: </p><div class="itemizedlist"><ul type="disc" compact><li><p> 程序在前面的session中装载了对象 </p></li><li><p> 对象被传递到UI(界面)层 </p></li><li><p> 对该对象进行了一些修改 </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> 如果对象没有标识值,调用<tt class="literal">save()</tt>来保存它 </p></li><li><p> 如果对象的标识值与<tt class="literal">unsaved-value</tt>中的条件匹配,调用<tt class="literal">save()</tt>来保存它 </p></li><li><p> 如果对象使用了版本(<tt class="literal">version</tt>或<tt class="literal">timestamp</tt>),那么除非设置<tt class="literal">unsaved-value="undefined"</tt>,版本检查会发生在标识符检查之前. </p></li><li><p> 如果这个session中有另外一个对象具有同样的标识符,抛出一个异常
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -