﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-把永恒在一刹那间收藏-文章分类-hibernate</title><link>http://www.blogjava.net/gm_jing/category/13227.html</link><description>生活之点点滴滴</description><language>zh-cn</language><lastBuildDate>Sun, 16 Jan 2011 00:55:48 GMT</lastBuildDate><pubDate>Sun, 16 Jan 2011 00:55:48 GMT</pubDate><ttl>60</ttl><item><title>【转】Hibernate Session的Flush模式</title><link>http://www.blogjava.net/gm_jing/articles/310009.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Mon, 18 Jan 2010 14:23:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/310009.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/310009.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/310009.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/310009.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/310009.html</trackback:ping><description><![CDATA[<p>首先要知道的是：</p>
<p>Hibernate会尽量将与数据库的操作延迟，直到必须要与数据库进行交互，例如save方法一般会在提交时才真正执行，最终在提交时会以批处理的方式与数据库进行交互，以提高效率。</p>
<p>而将操作延迟，就是利用缓存，将最后要处理的操作放到缓存中。</p>
<p>flush方法的主要作用就是清理缓存，强制数据库与Hibernate缓存同步，以保证数据的一致性。它的主要动作就是向数据库发送一系列的sql语句，并执行这些sql语句，但是不会向数据库提交。而commit方法则会首先调用flush方法，然后提交事务。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 在下面的情况下，Hibernate会调用Session.flush()以清理缓存： <br />
&nbsp;&nbsp;&nbsp;&nbsp; 1)事务提交时，如果flush模式不为FlushMode.NEVER,commit()将调用flush(). <br />
&nbsp;&nbsp;&nbsp;&nbsp; 2)在某些查询语句之前（此查询语句之前的语句已经改变了数据库状态，所以需要调用flush（）以同步数据库是查出来的数据是经过更改的）。<br />
&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp; 除非明确地指定了flush（）命令，否则关于Session何时会执行这些JDBC调用完全是无法保证的，只能保证他们执行的前后顺序。</p>
<p>&nbsp;<br />
&nbsp; 通过设置session.setFlushMode(),可以精确控制Hibernate的FlushMode. <br />
&nbsp; (1)&nbsp; FlushMode.AUTO:Hibernate判断对象属性有没有改变，如果被更改成为脏数据，则在一个查询语句前将更新此改动以保证数据库的同步。这也是Hibernate的默认清理模式。 <br />
&nbsp; (2) FlushMode.COMMIT:在事务结束之前清理session的缓存。这样有可能导致查出脏数据 <br />
&nbsp; (3) FlushMode.NEVER：除非强制调用Session.flush(),否则永远不清理Session。相当于将数据库设置为一个只读的数据库。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 【如果此时进行数据的写入操作，会发生错误】<br />
&nbsp; (4) FlushMode.ALWAYS：在每一个查询数据之前都调用Session.flush()。很显然这种效率很低。 <br />
&nbsp; <br />
&nbsp;在调用Session.flush()时，涉及的SQL语句会按照下面的顺序执行。 <br />
（1）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所有的实体进行插入的语句，其顺序按照对象执行Session.save()的时间顺序。 <br />
（2）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所有对实体进行更新的语句 <br />
（3）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所有对集合元素进行删除，更新或者插入的语句 <br />
（4）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 所有对实体经行删除的语句，其顺序按照对象执行Session.delete()的时间顺序。 <br />
（5）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有一个例外是，如果对象使用native方式生成的ID（持久化标识），则他们一执行save就会被插入。 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 【因为native方式若想得到主键，必须与数据库交互，而hilo方式则不用】）</p>
<p>&nbsp;</p>
<p>本文来自CSDN博客，转载请标明出处：http://blog.csdn.net/MageShuai/archive/2009/09/11/4544202.aspx</p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/310009.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2010-01-18 22:23 <a href="http://www.blogjava.net/gm_jing/articles/310009.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>HIbernate中SQL statements生成策略</title><link>http://www.blogjava.net/gm_jing/articles/299822.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Mon, 26 Oct 2009 10:22:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/299822.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/299822.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/299822.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/299822.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/299822.html</trackback:ping><description><![CDATA[<p>一）default statements generated on startup<br />
By default, Hibernate creates SQL statements for each persistent class on startup.These statements are simple create, read, update, and delete operations for reading a single row, deleting a row, and so on.<br />
the generated SQL statement updates<span style="background-color: yellow;"> all columns</span>, and if the value of a particular column isn&#8217;t modified, the statement sets it to its old value.</p>
<p><br />
</p>
<p>
二）dynamic statements generated at runtime<br />
<font color="#ff0000">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1)&lt;property&gt;元素 dynamic-insert属性:设置为true,表示insert对象的时候,生成动态的insert语句,如果这个字段的值是null就不会加入到insert语句当中.默认false<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2)&lt;property&gt;元素 dynamic-update属性,设置为true,表示update对象的时候,生成动态的update语句,如果这个字段的值是null就不会被加入到update语句中,默认false<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3)&lt;class&gt;元素 dynamic-insert属性:设置为true,表示把所有的&lt;property&gt;元素的dynamic-insert属性设置为true,默认false<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4)&lt;class&gt;元素 dynamic-update属性:设置为true,表示把所有的&lt;property&gt;元素的dynamic-update属性设置为true,默认false</font></p>
<p>&nbsp;</p>
<p>总结：如果表中包含N多字段,建议把dynamic-update属性和insert属性设置为true,这样在插入和修改数据的时候,语句中只包括要插入或者修改的字段.可以节省SQL语句的执行时间,提高程序的运行效率.(In some situations, such as a legacy table with hundreds of columns
where the SQL statements will be large for even the simplest operations
(say, only one column needs updating),<span style="background-color: yellow;"> you have to turn off this startup SQL generation and switch to dynamic statements generated at runtime</span>.)</p>
<p><br />
</p>
<p>其他属性设置对SQL Statement影响<br />
</p>
<p><font color="#ff0000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1)&lt;property&gt;元素 insert属性:设置为false,在insert语句中不包含这个字段,表示永远不会被插入,默认true<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2)&lt;property&gt;元素 update属性:设置为false,在update语句中不包含这个字段,表示永远不会被修改,默认true<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3)&lt;class&gt;元素 mutable属性:设置为false就是把所有的&lt;property&gt;元素的update属性设置为了false,说明这个对象不会被更新,默认true</font></p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/299822.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2009-10-26 18:22 <a href="http://www.blogjava.net/gm_jing/articles/299822.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate3的DetachedCriteria使用 </title><link>http://www.blogjava.net/gm_jing/articles/262179.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Thu, 26 Mar 2009 09:47:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/262179.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/262179.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/262179.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/262179.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/262179.html</trackback:ping><description><![CDATA[<div class="postbody">Criteria對SQL進行封裝，讓開發人員可以用物件的方式來對資料庫進行操作，例如下面的查詢User表格中的所有資料：<br />
<div style="margin-left: 40px"><span style="font-weight: bold; font-family: Courier New,Courier,monospace">Criteria criteria = session.createCriteria(User.class);</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">// 查詢user所有欄位</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">List users = criteria.list();</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">Iterator iterator =&nbsp; users.iterator();</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">System.out.println("id \t name/age");</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">while(iterator.hasNext()) {</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">&nbsp;&nbsp;&nbsp; User user = (User) iterator.next(); </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">&nbsp;&nbsp;&nbsp; System.out.println(user.getId() +</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; " \t " + user.getName() +</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "/" + user.getAge());&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">}</span><br />
</div>
<br />
Hibernate實際上使用以下的SQL來查詢資料庫：<br />
<div style="margin-left: 40px"><span style="font-weight: bold; font-family: Courier New,Courier,monospace">select this_.id as id0_, this_.name as name0_0_, this_.age as age0_0_ from user this_</span><br />
</div>
<br />
Criteria實際上只是個容器，如果想要設定查詢條件，則要使用add()方法加入Restrictions的條件限制，例如查詢age大於20且小於40的資料：<br />
<div style="margin-left: 40px"><span style="font-weight: bold; font-family: Courier New,Courier,monospace">Criteria criteria = session.createCriteria(User.class);</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">criteria.add(Restrictions.gt("age", new Integer(20)));</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">criteria.add(Restrictions.lt("age", new Integer(40)));</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">List users = criteria.list();</span><br />
</div>
<br />
您也可以使用邏輯組合來進行查詢，例如結合age等於（eq）20或（or）age為空（isNull）的條件： <br />
<div style="margin-left: 40px"><span style="font-weight: bold; font-family: Courier New,Courier,monospace">Criteria criteria = session.createCriteria(User.class);</span><br style="font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">criteria.add(Restrictions.or( </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Restrictions.eq("age", new Integer(20)), </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp; Restrictions.isNull("age") </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;)); </span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">List users = criteria.list();</span><br />
</div>
<br />
也可以使用sqlRestriction()方法來提供SQL語法作限定查詢，例如查詢name以cater開頭的資料：<br />
<div style="margin-left: 40px"><span style="font-weight: bold; font-family: Courier New,Courier,monospace">Criteria criteria = session.createCriteria(User.class);</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">criteria.add(Restrictions.sqlRestriction("{alias}.name LIKE (?)", "cater%", Hibernate.STRING));</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">List users = criteria.list();</span><br />
</div>
<br />
其中alias將被替換為與User類別相關的名稱，而?將被替換為cater%，也就是第二個參數所提供的值，在SQL撰寫時，不必再寫WHERE，如果有多個查詢條件，例如BETWEEN子句的查詢，則可以如下：<br />
<div style="margin-left: 40px"><span style="font-weight: bold; font-family: Courier New,Courier,monospace">Criteria criteria = session.createCriteria(User.class);</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">Integer[] ages = {new Integer(20), new Integer(40)};</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">Type[] types = {Hibernate.INTEGER, Hibernate.INTEGER};</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">criteria.add(Restrictions.sqlRestriction("{alias}.age BETWEEN (?) AND (?)", ages, types));</span><br style="font-weight: bold; font-family: Courier New,Courier,monospace" />
<span style="font-weight: bold; font-family: Courier New,Courier,monospace">List users = criteria.list();</span><br />
</div>
<br />
Restrictions的幾個常用限定查詢方法如下表所示：<br />
<table style="width: 100%; text-align: left" cellspacing="2" cellpadding="2" border="1">
    <tbody>
        <tr>
            <td style="background-color: rgb(204,204,204)"><small>方法</small></td>
            <td style="background-color: rgb(204,204,204)"><small>說明</small></td>
        </tr>
        <tr>
            <td><small>Restrictions.eq</small></td>
            <td><small>等於</small></td>
        </tr>
        <tr>
            <td><small>Restrictions.allEq</small></td>
            <td><small>使用Map，使用key/value進行多個等於的比對</small></td>
        </tr>
        <tr>
            <td><small>Restrictions.gt</small></td>
            <td><small>大於 &gt;</small></td>
        </tr>
        <tr>
            <td><small>Restrictions.ge</small></td>
            <td><small>大於等於 &gt;=</small></td>
        </tr>
        <tr>
            <td><small>Restrictions.lt</small></td>
            <td><small>小於 &lt;</small></td>
        </tr>
        <tr>
            <td><small>Restrictions.le</small></td>
            <td><small>小於等於 &lt;=</small></td>
        </tr>
        <tr>
            <td><small>Restrictions.between</small></td>
            <td><small>對應SQL的BETWEEN子句</small></td>
        </tr>
        <tr>
            <td><small>Restrictions.like</small></td>
            <td><small>對應SQL的LIKE子句</small></td>
        </tr>
        <tr>
            <td><small>Restrictions.in</small></td>
            <td><small>對應SQL的in子句</small></td>
        </tr>
        <tr>
            <td><small>Restrictions.and</small></td>
            <td><small>and關係</small></td>
        </tr>
        <tr>
            <td><small>Restrictions.or</small></td>
            <td><small>or關係</small></td>
        </tr>
        <tr>
            <td><small>Restrictions.sqlRestriction</small></td>
            <td><small>SQL限定查詢</small></td>
        </tr>
    </tbody>
</table>
<p><br />
&nbsp;</p>
<p>&nbsp;</p>
<p>==============</p>
<p>&nbsp;</p>
<h2><a id="_ctl0__ctl2_TitleUrl" href="http://java.mblogger.cn/fyun/posts/17316.aspx">Hibernate Criteria 关联查询</a> </h2>
<p>前面讲了Criteria看起来比HQL顺眼多了，接着继续。<br />
<br />
如果每个美女都有自己的客户资源（不要想歪了！），那么需要查询拥有客户Gates的美女怎么办？<br />
<br />
使用Criteria可以有两种方法：<br />
<br />
1：<br />
DetachedCriteria beautyCriteria = DetachedCriteria.forClass(Beauty.class).createCriteria("customers");<br />
beautyCriteria.add(Restrictions.eq("name", "Gates")):<br />
<br />
2：<br />
DetachedCriteria beautyCriteria = DetachedCriteria.forClass(Beauty.class).createAlias("customers", "c");<br />
beautyCriteria.add(Restrictions.eq("c.name", "Gates")):<br />
<br />
接着有了新的要求，年纪太大的美女不要，还是查找拥有客户Gates的，条件如下：<br />
DetachedCriteria beautyCriteria = DetachedCriteria.forClass(Beauty.class, "b").;<br />
DetachedCriteria customerCriteria = beautyCriteria.createAlias("customers", c");<br />
beautyCriteria.add(Restrictions.le("b.age", new Long(20))):<br />
customerCriteria.add(Restrictions.eq("c.name", "Gates")):<br />
<br />
关于Criteria更详细的资料，Hibernate的源代码和测试是最好的文档。<br />
<br />
Criteria的缺点？DBA很生气，后果很严重。</p>
</div>
<img src ="http://www.blogjava.net/gm_jing/aggbug/262179.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2009-03-26 17:47 <a href="http://www.blogjava.net/gm_jing/articles/262179.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>【引】compass入门与指南</title><link>http://www.blogjava.net/gm_jing/articles/251700.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Sat, 17 Jan 2009 08:36:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/251700.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/251700.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/251700.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/251700.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/251700.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;在新架构中打算选择Compass或Hibernate Search作为搜索引擎框架，比较后，感觉Hibernate Search上还是没有Compass成熟，另外考虑到后期对网页的爬取及搜索需求，决定还是基于Compass来作为架构缺省的搜索引擎。网上关于 Compass的文档很多，但说得相对完整其详细的入门文档基本上没有，Compass的官方文档倒是说得很详细，但是例子一塌糊涂，...&nbsp;&nbsp;<a href='http://www.blogjava.net/gm_jing/articles/251700.html'>阅读全文</a><img src ="http://www.blogjava.net/gm_jing/aggbug/251700.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2009-01-17 16:36 <a href="http://www.blogjava.net/gm_jing/articles/251700.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Session方法（续）</title><link>http://www.blogjava.net/gm_jing/articles/251683.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Sat, 17 Jan 2009 05:57:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/251683.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/251683.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/251683.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/251683.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/251683.html</trackback:ping><description><![CDATA[<p><img height="531" alt="" src="http://www.blogjava.net/images/blogjava_net/gm_jing/session.jpg" width="857" border="0" /><br />
【引用】http://davidwei05951983.spaces.live.com/Blog/cns!BED3D557991594B3!812.entry<br />
<br />
session的常用基本操作有： </p>
<p>&nbsp; Transient instances may be made persistent by calling save(),persist() or saveOrUpdate(). Persistent instances may be made transient by calling delete(). Any instance returned by a get() or load() method is persistent. Detached instances may be made persistent by calling update(), saveOrUpdate(), lock() or replicate(). The state of a transient or detached instance may also be made persistent as a new&nbsp; persistent instance by calling merge().save() and persist() result in an SQL INSERT, delete() in an SQL DELETE and update() or merge() in an SQL UPDATE. Changes to persistent instances are detected at flush time and also result in an SQL UPDATE. saveOrUpdate() and replicate() result in either an INSERT or an UPDATE. </p>
<p>persist(): <br />
&nbsp;&nbsp;&nbsp; Make a transient instance persistent. This operation cascades to associated instances if the association is mapped with cascade="persist". The semantics of this method are defined by JSR-220.<br />
&nbsp;&nbsp;&nbsp; 当级联风格为persist时，这个操作会级联操作关联的对象。这个方法的语义是JSR-220定义的。 <br />
</p>
<p><span style="font-size: small">persist() is well defined. It makes a transient instance persistent. However, <br />
it doesn't guarantee that the identifier value will be assigned to the persistent <br />
instance immediately, the assignment might happen at flush time. The spec doesn't say <br />
that, which is the problem I have with persist().</span></p>
<p><span style="font-size: small">persist() also guarantees that it will not execute an INSERT statement if it is <br />
called outside of transaction boundaries. This is useful in long-running conversations <br />
with an extended Session/persistence context.A method like persist() is required.</span></p>
<p><span style="font-size: small">save() does not guarantee the same, it returns an identifier, and if an INSERT <br />
has to be executed to get the identifier (e.g. "identity" generator, not "sequence"), <br />
this INSERT happens immediately, no matter if you are inside or outside of a transaction. This is not good in a long-running conversation with an extended Session/persistence context."</span></p>
<p><br />
save(): <br />
&nbsp;&nbsp;&nbsp; Persist the given transient instance, first assigning a generated identifier. (Or using the current value of the identifier property if the assigned generator is used.)&nbsp; This operation cascades to associated instances if the association is mapped with cascade="save-update".<br />
&nbsp;&nbsp;&nbsp; 首先会赋予一个标志符，然后持久化给定的对象。但是如果使用assigned 标志符产生方法，则会使用当前的标志符值。如果级联风格为save－pdate，则会持久化相应的关联对象. </p>
<p>merge():<br />
&nbsp;&nbsp;&nbsp; Copy the state of the given object onto the persistent object with the same identifier. If there is no persistent instance currently associated with the session, it will be loaded. Return the persistent instance. If the given instance is unsaved, save a copy of and return it as a newly persistent instance. The given instance does not become associated with the session. This operation cascades to associated instances if the association is mapped with cascade="merge". The semantics of this method are defined by JSR-220.<br />
&nbsp;&nbsp;&nbsp; 拷贝当前的对象的状态到相同标志符的持久化对象的状态。如果当前关联的session中没有持久化对象，Hibernate会加载该对象，并返回这个持久化对象。如果给定的对象没有保存，则Hibernate保存该副本，返回这个新持久化的对象，但给定的对象并没有和session关联。如果指定级联风格为merge，则会级联关联对象。该方法的语义是JSR－200定义的。 </p>
<p>saveOrUpdate(): <br />
&nbsp;&nbsp;&nbsp;&nbsp; Either {@link #save(String, Object)} or {@link #update(String, Object)} the given instance, depending upon resolution of the unsaved-value checks (see the manual for discussion of unsaved-value checking). This operation cascades to associated instances if the association is mapped with cascade="save-update".<br />
&nbsp;&nbsp;&nbsp; 保存或更新给定对象，取决于给定对象的持久化状态。默认情况下是保存，在指定标志符元素属性为unsaved-value时则会调整。如果级联风格为"save-update",则会级联相关联的对象 </p>
<p>delete():<br />
&nbsp;&nbsp;&nbsp;&nbsp; Remove a persistent instance from the datastore. The object argument may be an instance associated with the receiving Session or a transient instance with an identifier associated with existing persistent state. This operation cascades to associated instances if the association is mapped with cascade="delete".<br />
&nbsp;&nbsp;&nbsp; 删除对象。 </p>
<p>lock(): <br />
&nbsp;&nbsp;&nbsp; Obtain the specified lock level upon the given object. This may be used to perform a version check (LockMode.READ), to upgrade to a pessimistic lock (LockMode.UPGRADE), or to simply reassociate a transient instance with a session (LockMode.NONE). This operation cascades to associated instances if the association is mapped with cascade="lock".<br />
&nbsp;&nbsp;&nbsp; 用于对指定对象设置参数中给定的锁。如果锁为LockMode.READ，可以用来执行版本检查；如果锁为LockMode.UPGRADE则用来执行悲观锁。如果定为LockMode.NONE，则仅仅时持久化一个未持久化的对象。如果级联风格为lock，会级联相关联的对象。 </p>
<p>refresh(): <br />
&nbsp;&nbsp;&nbsp; Re-read the state of the given instance from the underlying database. It is inadvisable to use this to implement long-running sessions that span many business tasks. This method is, however, useful in certain special circumstances.For example where a database trigger alters the object state upon insert or update after executing direct SQL (eg. a mass update) in the same session after inserting a Blob or Clob.<br />
&nbsp;&nbsp;&nbsp; 从当前数据库中重新读取给定对象的状态。这在执行跨越多个业务任务的长时间session中优势不显著，在少数特定环境下还是有用的，例如： 插入或更新后数据库触发器更改了对象的状态。当前session中执行完原生SQL后（如批量更新）。 插入Blob或Clob对象后。<br />
&nbsp;<br />
evict():<br />
&nbsp;&nbsp;&nbsp; Remove this instance from the session cache. Changes to the instance will not be synchronized with the database. This operation cascades to associated instances if the association is mapped with cascade="evict".<br />
&nbsp;&nbsp;&nbsp; 从session的缓存中去除当前实例。执行后对象的改变将不再和数据库保持同步。当指定级联风格为'evict&#8217;时，会级联操作关联对象。我用的时候主要是用于批量操作的时候，清空缓存，防止内存紧张。 </p>
<p>replicate(): <br />
&nbsp;&nbsp;&nbsp; Persist the state of the given detached instance, reusing the current identifier value. This operation cascades to associated instances if the association is mapped with cascade="replicate" <br />
&nbsp;&nbsp;&nbsp; 重用当前的标志符，持久化当前已经脱离session的对象的状态。具体的操作和要看参数ReplicationMode。如果是ReplicationMode.EXCEPTION,则在复制时如果有重复的行数据，则抛出异常。ReplicationMode.IGNORE则忽略异常。ReplicationMode.OVERWRITE则会覆盖掉已有行数据。ReplicationMode.LATEST_VERSION则是在有重复时使用最新的版本进行控制。 </p>
<p><br />
<br />
<br />
<hr />
自动状态检测
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp; Hibernate的用户曾要求一个既可自动分配新持久化标识(identifier)保存瞬时(transient)对象，又可更新/重新关联脱管(detached)实例的通用方法。 saveOrUpdate()方法实现了这个功能。&nbsp;saveOrUpdate()用途和语义可能会使新用户感到迷惑。 首先，只要你没有尝试在某个session中使用来自另一session的实例，你就应该不需要使用update()， saveOrUpdate()，或merge()。有些程序从来不用些方法。 </p>
<p>通常下面的场景会使用update()或saveOrUpdate()： <br />
程序在第一个session中加载对象 <br />
该对象被传递到表现层 <br />
对象发生了一些改动 <br />
该对象被返回到业务逻辑层 <br />
程序调用第二个session的update()方法持久这些改动 </p>
<p>saveOrUpdate()做下面的事: <br />
如果对象已经在本session中持久化了，不做任何事 <br />
如果另一个与本session关联的对象拥有相同的持久化标识(identifier)，抛出一个异常 <br />
如果对象没有持久化标识(identifier)属性，对其调用save() <br />
如果对象的持久标识(identifier)表明其是一个新实例化的对象，对其调用save() <br />
如果对象是附带版本信息的（通过&lt;version&gt;或&lt;timestamp&gt;） 并且版本属性的值表明其是一个新实例化的对象，save()它。 <br />
否则update() 这个对象 </p>
<p>merge()可非常不同: <br />
如果session中存在相同持久化标识(identifier)的实例，用用户给出的对象的状态覆盖旧有的持久实例 <br />
如果session没有相应的持久实例，则尝试从数据库中加载，或创建新的持久化实例 ,最后返回该持久实例 <br />
<span style="color: red">用户给出的这个对象没有被关联到session上，它依旧是脱管的</span>. </p>
<p><br />
Session刷出(flush) <br />
每间隔一段时间，Session会执行一些必需的SQL语句来把内存中的对象的状态同步到JDBC连接中。这个过程被称为刷出(flush)，默认会在下面的时间点执行： <br />
a.在某些查询执行之前 <br />
b.在调用org.hibernate.Transaction.commit()的时候 <br />
c.在调用Session.flush()的时候 </p>
<p>涉及的SQL语句会按照下面的顺序发出执行： <br />
所有对实体进行插入的语句，其顺序按照对象执行Session.save()的时间顺序 <br />
所有对实体进行更新的语句 <br />
所有进行集合删除的语句 <br />
所有对集合元素进行删除，更新或者插入的语句 <br />
所有进行集合插入的语句 <br />
所有对实体进行删除的语句，其顺序按照对象执行Session.delete()的时间顺序 </p>
<p>（有一个例外是，如果对象使用native方式来生成ID（持久化标识）的话，它们一执行save就会被插入。） <br />
除非你明确地发出了flush()指令，关于Session何时会执行这些JDBC调用是完全无法保证的，只能保证它们执行的前后顺序。 当然，Hibernate保证，Query.list(..)绝对不会返回已经失效的数据，也不会返回错误数据。 </p>
<p>也可以改变默认的设置，来让刷出(flush)操作发生的不那么频繁。 FlushMode类定义了三种不同的方式。 仅在提交时刷出(仅当Hibernate的Transaction API被使用时有效)， 按照刚才说的方式刷出， 以及除非明确使用flush()否则从不刷出。 最后一种模式对于那些需要长时间保持Session为打开或者断线状态的长时间运行的工作单元很有用。 </p>
<p><br />
父子关系的级联(cascading)操作准确语义如下： <br />
如果父对象被persist()，那么所有子对象也会被persist() <br />
如果父对象被merge()，那么所有子对象也会被merge() <br />
如果父对象被save()，update()或 saveOrUpdate()，那么所有子对象则会被saveOrUpdate() <br />
如果某个持久的父对象引用了瞬时(transient)或者脱管(detached)的子对象，那么子对象将会被saveOrUpdate() <br />
如果父对象被删除，那么所有子对象也会被delete() </p>
<p>除非被标记为cascade="delete-orphan"（删除&#8220;孤儿&#8221;模式，此时不被任何一个父对象引用的子对象会被删除）， 否则子对象失掉父对象对其的引用时，什么事也不会发生。 如果有特殊需要，应用程序可通过显式调用delete()删除子对象。 <br />
</p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/251683.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2009-01-17 13:57 <a href="http://www.blogjava.net/gm_jing/articles/251683.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>二级缓存-续</title><link>http://www.blogjava.net/gm_jing/articles/248520.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Fri, 26 Dec 2008 10:07:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/248520.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/248520.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/248520.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/248520.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/248520.html</trackback:ping><description><![CDATA[<div style="position: relative" _madepositioned="true" _eventid="3">众所周知，<span class="hilite1">List</span>仅仅会填充二级缓存，却不能利用二级缓存，而iterator可以读二级缓存，然而无法命中的话，效率却很低。一个最好的办法就是，第一次查询使用<span class="hilite1">List</span>，随后的查询使用iterator，现在的问题是如何做到第一次查询使用<span class="hilite1">List</span>，随后查询使用iterator。 <br />
<br />
先来考察一下缓存的作用：缓存之所以可以命中，前提条件是该数据被使用的非常频繁，同时更新的可能性相当小，如果数据会频繁修改，那么毫无疑问，缓存不会带来任何好处。明确了这一点，我们就明白什么对象应该进行缓存了。显然，对于那些经常会被访问到的小批量的诸如基础信息，用户和权限信息是非常适合进行缓存的，这些数据我们可以在应用启动的时候就执行一次<span class="hilite1">list</span>方法查询，进行缓存填充(例如写一个InitBean类进行数据缓存初始化)，此外在数据被修改的时候，再次执行<span class="hilite1">list</span>方法，进行缓存填充。而在使用这些数据的其他地方，统统使用iterator方法。这样就可以实现所谓的第一次查询使用<span class="hilite1">List</span>，随后的查询使用iterator了。 </div>
<img src ="http://www.blogjava.net/gm_jing/aggbug/248520.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2008-12-26 18:07 <a href="http://www.blogjava.net/gm_jing/articles/248520.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring 整合 Hibernate 的一处简化配置&lt;转载&gt; </title><link>http://www.blogjava.net/gm_jing/articles/246876.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Wed, 17 Dec 2008 07:23:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/246876.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/246876.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/246876.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/246876.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/246876.html</trackback:ping><description><![CDATA[Spring 整合 Hibernate 的一处简化配置<br />
原文：http://www.blogjava.net/steady/archive/2007/08/17/137527.html<br />
<br />
<span style="font-size: 10pt">在过去使用 Spring 整合 Hibernate 的时候，都是用这样的配置方式。<br />
<br />
</span>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">&lt;</span><span style="color: #800000">bean&nbsp;</span><span style="color: #ff0000">id</span><span style="color: #0000ff">="sessionFactory"</span><span style="color: #ff0000">&nbsp;lazy-init</span><span style="color: #0000ff">="true"</span><span style="color: #ff0000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class</span><span style="color: #0000ff">="org.springframework.orm.hibernate3.LocalSessionFactoryBean"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">property&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="mappingResources"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">list</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">resources/icustomer/Contact.hbm.xml</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">resources/icustomer/Customer.hbm.xml</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">list</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">property</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;<img alt="" src="http://www.blogjava.net/Images/dot.gif" />.<br />
</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">bean</span><span style="color: #0000ff">&gt;</span></div>
<br />
<span style="font-size: 10pt">每当需要加入一个新的 VO 时，我需要过来修改配置文件，来引入对新的 VO 的支持。</span><br />
<br />
<span style="font-size: 10pt">现在我使用的时候，是这么配的：<br />
</span>
<div style="border-right: #cccccc 1px solid; padding-right: 5px; border-top: #cccccc 1px solid; padding-left: 4px; font-size: 13px; padding-bottom: 4px; border-left: #cccccc 1px solid; width: 98%; word-break: break-all; padding-top: 4px; border-bottom: #cccccc 1px solid; background-color: #eeeeee"><span style="color: #0000ff">&lt;</span><span style="color: #800000">bean&nbsp;</span><span style="color: #ff0000">id</span><span style="color: #0000ff">="sessionFactory"</span><span style="color: #ff0000">&nbsp;lazy-init</span><span style="color: #0000ff">="true"</span><span style="color: #ff0000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;class</span><span style="color: #0000ff">="org.springframework.orm.hibernate3.LocalSessionFactoryBean"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">property&nbsp;</span><span style="color: #ff0000">name</span><span style="color: #0000ff">="mappingLocations"</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">list</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000">classpath:resources/**/*.hbm.xml</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">value</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">list</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">property</span><span style="color: #0000ff">&gt;</span><span style="color: #000000"><br />
&nbsp;&nbsp;&nbsp;&nbsp;<img alt="" src="http://www.blogjava.net/Images/dot.gif" />.<br />
</span><span style="color: #0000ff">&lt;/</span><span style="color: #800000">bean</span><span style="color: #0000ff">&gt;</span></div>
<br />
<span style="font-size: 10pt">做项目开发的时候，就再也没有改过配置。</span><br />
<img src ="http://www.blogjava.net/gm_jing/aggbug/246876.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2008-12-17 15:23 <a href="http://www.blogjava.net/gm_jing/articles/246876.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate程序性能优化</title><link>http://www.blogjava.net/gm_jing/articles/216319.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Mon, 21 Jul 2008 03:57:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/216319.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/216319.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/216319.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/216319.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/216319.html</trackback:ping><description><![CDATA[<p>　【引用】　http://blog.csdn.net/freeglad/archive/2008/07/04/2610720.aspx<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;初用HIBERNATE的人也许都遇到过性能问题，实现同一功能，用HIBERNATE与用JDBC性能相差十几倍很正常，如果不及早调整，很可能影响整个项目的进度。</p>
<p>　　大体上，对于HIBERNATE性能调优的主要考虑点如下:</p>
<p>　　&#216; 数据库设计调整</p>
<p>　　&#216; HQL优化</p>
<p>　　&#216; API的正确使用(如根据不同的业务类型选用不同的集合及查询API)</p>
<p>　　&#216; 主配置参数(日志，查询缓存，fetch_size, batch_size等)</p>
<p>　　&#216; 映射文件优化(ID生成策略，二级缓存，延迟加载，关联优化)</p>
<p>　　&#216; 一级缓存的管理</p>
<p>　　&#216; 针对二级缓存，还有许多特有的策略</p>
<p>　　&#216; 事务控制策略。</p>
<p><strong>　　1、 数据库设计</strong></p>
<p>　　a) 降低关联的复杂性</p>
<p>　　b) 尽量不使用联合主键</p>
<p>　　c) ID的生成机制，不同的数据库所提供的机制并不完全一样</p>
<p>　　d) 适当的冗余数据，不过分追求高范式</p>
<p><strong>　　2、 HQL优化</strong></p>
<p>　　HQL如果抛开它同HIBERNATE本身一些缓存机制的关联，HQL的优化技巧同普通的SQL优化技巧一样，可以很容易在网上找到一些经验之谈。</p>
<p><strong>　　3、 主配置</strong></p>
<p>　　a) 查询缓存，同下面讲的缓存不太一样，它是针对HQL语句的缓存，即完全一样的语句再次执行时可以利用缓存数据。但是，查询缓存在一个交易系统(数据变更频繁，查询条件相同的机率并不大)中可能会起反作用:它会白白耗费大量的系统资源但却难以派上用场。</p>
<p>　　b) fetch_size，同JDBC的相关参数作用类似，参数并不是越大越好，而应根据业务特征去设置</p>
<p>　　c) batch_size同上。</p>
<p>　　d) 生产系统中，切记要关掉SQL语句打印。</p>
<p><strong>　　4、 缓存</strong></p>
<p>　　a) 数据库级缓存:这级缓存是最高效和安全的，但不同的数据库可管理的层次并不一样，比如，在ORACLE中，可以在建表时指定将整个表置于缓存当中。</p>
<p>　　b) SESSION缓存:在一个HIBERNATE SESSION有效，这级缓存的可干预性不强，大多于HIBERNATE自动管理，但它提供清除缓存的方法，这在大批量增加/更新操作是有效的。比如，同时增加十万条记录，按常规方式进行，很可能会发现OutofMemeroy的异常，这时可能需要手动清除这一级缓存:Session.evict以及 Session.clear</p>
<p>　　c) 应用缓存:在一个SESSIONFACTORY中有效，因此也是优化的重中之重，因此，各类策略也考虑的较多，在将数据放入这一级缓存之前，需要考虑一些前提条件:</p>
<p>　　i. 数据不会被第三方修改(比如，是否有另一个应用也在修改这些数据?)</p>
<p>　　ii. 数据不会太大</p>
<p>　　iii. 数据不会频繁更新(否则使用CACHE可能适得其反)</p>
<p>　　iv. 数据会被频繁查询</p>
<p>　　v. 数据不是关键数据(如涉及钱，安全等方面的问题)。</p>
<p>　　缓存有几种形式，可以在映射文件中配置:read-only(只读，适用于很少变更的静态数据/历史数据)，nonstrict-read- write，read-write(比较普遍的形式，效率一般)，transactional(JTA中，且支持的缓存产品较少)</p>
<p>　　d) 分布式缓存:同c)的配置一样，只是缓存产品的选用不同，在目前的HIBERNATE中可供选择的不多，oscache, jboss cache，目前的大多数项目，对它们的用于集群的使用(特别是关键交易系统)都持保守态度。在集群环境中，只利用数据库级的缓存是最安全的。</p>
<p><strong>　　5、 延迟加载</strong></p>
<p>　　a) 实体延迟加载:通过使用动态代理实现</p>
<p>　　b) 集合延迟加载:通过实现自有的SET/LIST，HIBERNATE提供了这方面的支持</p>
<p>　　c) 属性延迟加载:</p>
<p><strong>　　6、 方法选用</strong></p>
<p>　　a) 完成同样一件事，HIBERNATE提供了可供选择的一些方式，但具体使用什么方式，可能用性能/代码都会有影响。显示，一次返回十万条记录 (List/Set/Bag/Map等)进行处理，很可能导致内存不够的问题，而如果用基于游标(ScrollableResults)或 Iterator的结果集，则不存在这样的问题。</p>
<p>　　b) Session的load/get方法，前者会使用二级缓存，而后者则不使用。</p>
<p>　　c) Query和list/iterator，如果去仔细研究一下它们，你可能会发现很多有意思的情况，二者主要区别(如果使用了Spring，在HibernateTemplate中对应find,iterator方法):</p>
<p>　　i. list只能利用查询缓存(但在交易系统中查询缓存作用不大)，无法利用二级缓存中的单个实体，但list查出的对象会写入二级缓存，但它一般只生成较少的执行SQL语句，很多情况就是一条(无关联)。</p>
<p>　　ii. iterator则可以利用二级缓存，对于一条查询语句，它会先从数据库中找出所有符合条件的记录的ID，再通过ID去缓存找，对于缓存中没有的记录，再构造语句从数据库中查出，因此很容易知道，如果缓存中没有任何符合条件的记录，使用iterator会产生N+1条SQL语句(N为符合条件的记录数)</p>
<p>　　iii. 通过iterator，配合缓存管理API，在海量数据查询中可以很好的解决内存问题，如:</p>
<p>　　while(it.hasNext()){</p>
<p>　　YouObject object = (YouObject)it.next();</p>
<p>　　session.evict(youObject);</p>
<p>　　sessionFactory.evice(YouObject.class, youObject.getId());</p>
<p>　　}</p>
<p>　　如果用list方法，很可能就出OutofMemory错误了。</p>
<p>　　iv. 通过上面的说明，我想你应该知道如何去使用这两个方法了。</p>
<p><strong>　　7、 集合的选用</strong></p>
<p>　　在HIBERNATE 3.1文档的&#8220;19.5. Understanding Collection performance&#8221;中有详细的说明。</p>
<p><strong>　　8、 事务控制</strong></p>
<p>　　事务方面对性能有影响的主要包括:事务方式的选用，事务隔离级别以及锁的选用</p>
<p>　　a) 事务方式选用:如果不涉及多个事务管理器事务的话，不需要使用JTA，只有JDBC的事务控制就可以。</p>
<p>　　b) 事务隔离级别:参见标准的SQL事务隔离级别</p>
<p>　　c) 锁的选用:悲观锁(一般由具体的事务管理器实现)，对于长事务效率低，但安全。乐观锁(一般在应用级别实现)，如在HIBERNATE中可以定义 VERSION字段，显然，如果有多个应用操作数据，且这些应用不是用同一种乐观锁机制，则乐观锁会失效。因此，针对不同的数据应有不同的策略，同前面许多情况一样，很多时候我们是在效率与安全/准确性上找一个平衡点，无论如何，优化都不是一个纯技术的问题，你应该对你的应用和业务特征有足够的了解。</p>
<p><strong>　　9、 批量操作</strong></p>
<p>　　即使是使用JDBC，在进行大批数据更新时，BATCH与不使用BATCH有效率上也有很大的差别。我们可以通过设置batch_size来让其支持批量操作。</p>
<p>　　举个例子，要批量删除某表中的对象，如&#8220;delete Account&#8221;，打出来的语句，会发现HIBERNATE找出了所有ACCOUNT的ID，再进行删除，这主要是为了维护二级缓存，这样效率肯定高不了，在后续的版本中增加了bulk delete/update，但这也无法解决缓存的维护问题。也就是说，由于有了二级缓存的维护问题，HIBERNATE的批量操作效率并不尽如人意!</p>
<p>　　从前面许多要点可以看出，很多时候我们是在效率与安全/准确性上找一个平衡点，无论如何，优化都不是一个纯技术的问题，你应该对你的应用和业务特征有足够的了解，一般的，优化方案应在架构设计期就基本确定，否则可能导致没必要的返工，致使项目延期，而作为架构师和项目经理，还要面对开发人员可能的抱怨，必竟，我们对用户需求更改的控制力不大，但技术/架构风险是应该在初期意识到并制定好相关的对策。</p>
<p>　　还有一点要注意，应用层的缓存只是锦上添花，永远不要把它当救命稻草，应用的根基(数据库设计，算法，高效的操作语句，恰当API的选择等)才是最重要的。</p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/216319.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2008-07-21 11:57 <a href="http://www.blogjava.net/gm_jing/articles/216319.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate二级缓存攻略</title><link>http://www.blogjava.net/gm_jing/articles/142913.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Wed, 05 Sep 2007 07:33:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/142913.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/142913.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/142913.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/142913.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/142913.html</trackback:ping><description><![CDATA[二级缓存
<p>&nbsp;&nbsp;&nbsp; hibernate的session提供了一级缓存，在同一个session中对同一个id的对象load两次，并不会发送两条sql给数据库。但是session关闭的时候，一级缓存就失效了。</p>
<p>&nbsp;&nbsp;&nbsp; 二级缓存是SessionFactory级别的全局缓存，它底下可以使用不同的缓存类库，比如ehcache、oscache等，需要使用缓存实现方案。</p>
<p>&nbsp;&nbsp;&nbsp; 详细请看: <a title="Visit page outside Confluence" href="http://www.javaeye.com/topic/18904">hibernate二级缓存攻略</a></p>
<h3><a name="Hibernate-%26nbsp%3B3.1%E5%9F%BA%E6%9C%AC%E8%AE%BE%E7%BD%AE"></a>&nbsp;3.1 基本设置</h3>
<p>1. 如果需要特别设置ehcache的属性，把一个ehcache.xml 定义文件拷贝到class-path.</p>
<p>2. jdbc.properties加上</p>
<div class="code">
<div class="codeContent">
<pre class="code-java">hibernate.cache.use_query_cache=<span class="code-keyword">true</span>
hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider</pre>
</div>
</div>
<p>3. applicationContext.xml的 &lt;property name="hibernateProperties"&gt;下加上</p>
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;prop key=<span class="code-quote">"hibernate.cache.use_query_cache"</span>&gt;$ {hibernate.cache.use_query_cache}&lt;/prop&gt;
&lt;prop key=<span class="code-quote">"hibernate.cache.provider_class"</span>&gt;$ {hibernate.cache.provider_class}&lt;/prop&gt;</pre>
</div>
</div>
<h3><a name="Hibernate-3.2Entity%E7%BA%A7%E4%BA%8C%E7%BA%A7%E7%BC%93%E5%AD%98"></a>3.2 Entity级二级缓存</h3>
<p>&nbsp;&nbsp; Entity二级缓存是把PO放进cache，缓存的key就是ID，value是POJO，不同于查询的缓存。</p>
<p>&nbsp;&nbsp; Entity二级缓存在BookDao.get(3)，和book.getCategory()的情况下都能用到，把category这样的小表完全cache到内存挺不错的。</p>
<p>在hbm文件中:&nbsp;</p>
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;class name=<span class="code-quote">"Product"</span> table=<span class="code-quote">"PRODUCT"</span> dynamic-insert=<span class="code-quote">"<span class="code-keyword">true</span>"</span> dynamic-update=<span class="code-quote">"<span class="code-keyword">true</span>"</span>&gt;
&lt;cache usage=<span class="code-quote">"nonstrict-read-write"</span>/&gt;
&lt;id name=<span class="code-quote">"id"</span> column=<span class="code-quote">"ID"</span>&gt;
&lt;generator class=<span class="code-quote">"<span class="code-keyword">native</span>"</span>/&gt;
&lt;/id&gt;</pre>
</div>
</div>
<p>&nbsp;&nbsp; 如果你使用的二级缓存实现是ehcache的话，需要配置ehcache.xml ，否则就会使用ehcache默认的配置</p>
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;cache name=<span class="code-quote">"com.xxx.pojo.Foo"</span> maxElementsInMemory=<span class="code-quote">"500"</span> eternal=<span class="code-quote">"<span class="code-keyword">false</span>"</span> timeToLiveSeconds=<span class="code-quote">"7200"</span> timeToIdleSeconds=<span class="code-quote">"3600"</span> overflowToDisk=<span class="code-quote">"<span class="code-keyword">true</span>"</span> /&gt;</pre>
</div>
</div>
<h3><a name="Hibernate-3.3%E6%9F%A5%E8%AF%A2%E7%BC%93%E5%AD%98"></a>3.3 查询缓存</h3>
<p>&nbsp;&nbsp; 上面的二级缓存是针对单个对象的，如果要对查询结果，则是用下面的语句</p>
<div class="code">
<div class="codeContent">
<pre class="code-java">query.setCacheable(<span class="code-keyword">true</span>);<span class="code-comment">//激活查询缓存
</span>query.setCacheRegion(<span class="code-quote">"myCacheRegion"</span>);<span class="code-comment">//指定要使用的cacheRegion，可选</span></pre>
</div>
</div>
<p>&nbsp;&nbsp; cacheRegion是可选的，可以对使用的缓存进行特殊设置， 在ehcahe.xml里要补上下面的一段。</p>
<div class="code">
<div class="codeContent">
<pre class="code-java">&lt;cache name=<span class="code-quote">"myCacheRegion"</span> maxElementsInMemory=<span class="code-quote">"10"</span> eternal=<span class="code-quote">"<span class="code-keyword">false</span>"</span> timeToIdleSeconds=<span class="code-quote">"3600"</span> timeToLiveSeconds=<span class="code-quote">"7200"</span> overflowToDisk=<span class="code-quote">"<span class="code-keyword">true</span>"</span> /&gt;</pre>
</div>
</div>
<h2>&nbsp;</h2>
<img src ="http://www.blogjava.net/gm_jing/aggbug/142913.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2007-09-05 15:33 <a href="http://www.blogjava.net/gm_jing/articles/142913.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>事务管理方式</title><link>http://www.blogjava.net/gm_jing/articles/133545.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Tue, 31 Jul 2007 04:19:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/133545.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/133545.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/133545.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/133545.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/133545.html</trackback:ping><description><![CDATA[<p>1． 依赖特定事务资源的事务处理<br>这是应用开发中最常见的模式，即通过特定资源提供的事务机制进行事务管理。<br>如通过JDBC、JTA 的rollback、commit方法；Hibernate Transaction 的rollback、commit方法等。<br>这种方法大家已经相当熟悉。</p>
<p><br>2． 依赖容器的参数化事务管理<br>通过容器提供的集约式参数化事务机制，实现事务的外部管理，如EJB 中的事务管理模式。<br>&nbsp;容器管理的参数化事务为程序开发提供了相当的灵活性，同时因为将事务委托给容器进行管理，<br>应用逻辑中无需再编写事务代码，大大节省了代码量（特别是针对需要同时操作多个事务资源的应用），从而提高了生产率。<br></p>
<br><br><br><br>
<hr>
<div class=postcontent><font size=2>【引用】</font> <a href="http://www.blogjava.net/georgehill/archive/2005/07/08/7374.html"><font color=#366900>http://www.blogjava.net/georgehill/archive/2005/07/08/7374.html</font></a>&nbsp;<br><br>事务的4个基本特性（ACID）：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. Atomic（原子性）：事务中包含的操作被看作一个逻辑单元，这个逻辑单元中的操作要么全部成功，要么全部失败。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. Consistency（一致性）：只有合法的数据可以被写入数据库，否则事务应该将其回滚到最初状态。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. Isolation（隔离性）：事务允许多个用户对同一个数据的并发访问，而不破坏数据的正确性和完整性。同时，并行事务的修改必须与其他并行事务的修改相互独立。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. Durability（持久性）：事务结束后，事务处理的结果必须能够得到固化。
<hr>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;数据库操作过程中可能出现的3种不确定情况：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. 脏读取（Dirty Reads）：一个事务读取了另一个并行事务未提交的数据。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. 不可重复读取（Non-repeatable Reads）：一个事务再次读取之前的数据时，得到的数据不一致，被另一个已提交的事务修改。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. 虚读（Phantom Reads）：一个事务重新执行一个查询，返回的记录中包含了因为其他最近提交的事务而产生的新记录。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;标准SQL规范中，为了避免上面3种情况的出现，定义了4个事务隔离等级：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. Read Uncommitted：最低等级的事务隔离，仅仅保证了读取过程中不会读取到非法数据。上诉3种不确定情况均有可能发生。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. Read Committed：大多数主流数据库的默认事务等级，保证了一个事务不会读到另一个并行事务已修改但未提交的数据，避免了&#8220;脏读取&#8221;。该级别适用于大多数系统。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. Repeatable Read：保证了一个事务不会修改已经由另一个事务读取但未提交（回滚）的数据。避免了&#8220;脏读取&#8221;和&#8220;不可重复读取&#8221;的情况，但是带来了更多的性能损失。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. Serializable：最高等级的事务隔离，上面3种不确定情况都将被规避。这个级别将模拟事务的串行执行。
<hr>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Hibernate将事务管理委托给底层的JDBC或者JTA，默认是基于JDBC Transaction的。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Hibernate支持&#8220;悲观锁（Pessimistic Locking）&#8221;和&#8220;乐观锁（Optimistic Locking）&#8221;。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;悲观锁对数据被外界修改持保守态度，因此，在整个数据处理过程中，将数据处于锁定状态。悲观锁的实现，往往依靠数据库提供的锁机制。Hibernate通过使用数据库的for update子句实现了悲观锁机制。Hibernate的加锁模式有：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. LockMode.NONE：无锁机制<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. LockMode.WRITE：Hibernate在Insert和Update记录的时候会自动获取<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. LockMode.READ：Hibernate在读取记录的时候会自动获取<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. LockMode.UPGRADE：利用数据库的for update子句加锁<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5. LockMode.UPGRADE_NOWAIT：Oracle的特定实现，利用Oracle的for update nowait子句实现加锁<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;乐观锁大多是基于数据版本（Version）记录机制实现。Hibernate在其数据访问引擎中内置了乐观锁实现，可以通过class描述符的optimistic-lock属性结合version描述符指定。optimistic-lock属性有如下可选取值：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1. none：无乐观锁<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2. version：通过版本机制实现乐观锁<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3. dirty：通过检查发生变动过的属性实现乐观锁<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4. all：通过检查所有属性实现乐观锁 </div>
<img src ="http://www.blogjava.net/gm_jing/aggbug/133545.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2007-07-31 12:19 <a href="http://www.blogjava.net/gm_jing/articles/133545.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> 【转】open session and Hibernate事务处理机制 </title><link>http://www.blogjava.net/gm_jing/articles/120900.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Wed, 30 May 2007 06:05:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/120900.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/120900.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/120900.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/120900.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/120900.html</trackback:ping><description><![CDATA[<p>在没有使用Spring提供的Open Session In View情况下，因需要在service(or Dao)层里把session关闭，所以lazy loading 为true的话，要在应用层内把关系集合都初始化，如 company.getEmployees()，否则Hibernate抛session already closed Exception;&nbsp;&nbsp;&nbsp; Open Session In View提供了一种简便的方法，较好地解决了lazy loading问题.</p>
<p>&nbsp;&nbsp;&nbsp; 它有两种配置方式OpenSessionInViewInterceptor和OpenSessionInViewFilter(具体参看SpringSide)，功能相同，只是一个在web.xml配置，另一个在application.xml配置而已。</p>
<p>&nbsp;&nbsp;&nbsp; Open Session In View在request把session绑定到当前thread期间一直保持hibernate session在open状态，使session在request的整个期间都可以使用，如在View层里PO也可以lazy loading数据，如 ${ company.employees }。当View 层逻辑完成后，才会通过Filter的doFilter方法或Interceptor的postHandle方法自动关闭session。</p>
<p>&nbsp;</p>
<p><br>OpenSessionInViewInterceptor配置</p>
<p>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &lt;beans&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean name="openSessionInViewInterceptor" <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; class="org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor"&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="sessionFactory"&gt;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="sessionFactory"/&gt;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bean&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean id="urlMapping" <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="interceptors"&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;list&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;ref bean="openSessionInViewInterceptor"/&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/list&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="mappings"&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ... <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bean&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ... <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &lt;/beans&gt; <br>&nbsp;&nbsp;&nbsp; </p>
<p><br>OpenSessionInViewFilter配置</p>
<p>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &lt;web-app&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ... <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;filter&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;hibernateFilter&lt;/filter-name&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;filter-class&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; org.springframework.orm.hibernate3.support.OpenSessionInViewFilter <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/filter-class&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;!-- singleSession默认为true,若设为false则等于没用OpenSessionInView --&gt;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;init-param&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-name&gt;singleSession&lt;/param-name&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;param-value&gt;true&lt;/param-value&gt;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/init-param&gt;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/filter&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ... <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;filter-mapping&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;filter-name&gt;hibernateFilter&lt;/filter-name&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;url-pattern&gt;*.do&lt;/url-pattern&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/filter-mapping&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; ... <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &lt;/web-app&gt; <br>&nbsp;&nbsp;&nbsp; </p>
<p><br>很多人在使用OpenSessionInView过程中提及一个错误：</p>
<p><br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; org.springframework.dao.InvalidDataAccessApiUsageException: Write operations <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; are not allowed in read-only mode (FlushMode.NEVER) - turn your Session into <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; FlushMode.AUTO or remove 'readOnly' marker from transaction definition <br>&nbsp;&nbsp;&nbsp; </p>
<p><br>看看OpenSessionInViewFilter里的几个方法</p>
<p><br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,FilterChain filterChain) throws ServletException, IOException {　SessionFactory sessionFactory = lookupSessionFactory();　logger.debug("Opening Hibernate Session in OpenSessionInViewFilter");　Session session = getSession(sessionFactory);　TransactionSynchronizationManager.bindResource(　　sessionFactory, new SessionHolder(session));　try {　　filterChain.doFilter(request, response);　}　finally {　TransactionSynchronizationManager.unbindResource(sessionFactory);　logger.debug("Closing Hibernate Session in OpenSessionInViewFilter");　closeSession(session, sessionFactory);　}} <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; protected Session getSession(SessionFactory sessionFactory)throws DataAccessResourceFailureException {　Session session = SessionFactoryUtils.getSession(sessionFactory, true);　session.setFlushMode(FlushMode.NEVER);　return session;}<br>&nbsp;&nbsp;&nbsp; protected void closeSession(Session session, SessionFactory sessionFactory)throws CleanupFailureDataAccessException {　SessionFactoryUtils.closeSessionIfNecessary(session, sessionFactory);} </p>
<p><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 关于绑定session的方式，通过看spring里TransactionSynchronizationManager的实现，发现：它维护一个java.lang.ThreadLocal类型的resources，resources负责持有线程局部变量，这里resources持有的是一个HashMap，通过TransactionSynchronizationManager.bindResource()方法在map里绑定和线程相关的所有变量到他们的标识上，包括如上所述的绑定在sessionFactory上的线程局部session。sessionHolder只不过是存放可以hold一个session并可以和transtaction同步的容器。可以看到OpenSessionInViewFilter在getSession的时候,会把获取回来的session的flush mode 设为FlushMode.NEVER。然后把该sessionFactory绑定到TransactionSynchronizationManager，使request的整个过程都使用同一个session，在请求过后再接除该sessionFactory的绑定，最后closeSessionIfNecessary根据该session是否已和transaction绑定来决定是否关闭session。绑定以后，就可以防止每次不会新开一个Session呢？看看HibernateDaoSupport的情况：</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 1.&nbsp; public final void setSessionFactory(SessionFactory sessionFactory) {&nbsp;&nbsp;&nbsp; 2.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; this.hibernateTemplate = new HibernateTemplate(sessionFactory);&nbsp;&nbsp;&nbsp; 3.&nbsp; }&nbsp;&nbsp;&nbsp; 4.&nbsp; protected final HibernateTemplate getHibernateTemplate() {&nbsp;&nbsp;&nbsp; 5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return hibernateTemplate;&nbsp;&nbsp;&nbsp; 6.&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们的DAO将使用这个template进行操作.</p>
<p>public abstract class BaseHibernateObjectDao extends HibernateDaoSupport<br>implements BaseObjectDao {<br>&nbsp;&nbsp;&nbsp;&nbsp; protected BaseEntityObject getByClassId(final long id) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BaseEntityObject obj =(BaseEntityObject) getHibernateTemplate().execute(new HibernateCallback() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Object doInHibernate(Session session) throws HibernateException {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return session.get(getPersistentClass(),new Long(id));<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return obj;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; public void save(BaseEntityObject entity) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getHibernateTemplate().saveOrUpdate(entity);<br>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; public void remove(BaseEntityObject entity) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getHibernateTemplate().delete(entity);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } catch (Exception e) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new FlexEnterpriseDataAccessException(e);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void refresh(final BaseEntityObject entity) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getHibernateTemplate().execute(new HibernateCallback() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Object doInHibernate(Session session) throws HibernateException {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.refresh(entity);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; public void replicate(final Object entity) {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getHibernateTemplate().execute(new HibernateCallback() {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public Object doInHibernate(Session session)throws HibernateException {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.replicate(entity,ReplicationMode.OVERWRITE);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return null;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; });<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>}</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 而HibernateTemplate试图每次在execute之前去获得Session，执行完就力争关闭Session </p>
<p>&nbsp; 1. public Object execute(HibernateCallback action) throws DataAccessException {&nbsp; 2.&nbsp;&nbsp;&nbsp; Session session = (!this.allowCreate ?&nbsp; 3.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SessionFactoryUtils.getSession(getSessionFactory(),&nbsp;&nbsp; 4.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; false) :&nbsp; 5.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SessionFactoryUtils.getSession(getSessionFactory(),&nbsp; 6.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getEntityInterceptor(),&nbsp; 7.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; getJdbcExceptionTranslator()));&nbsp; 8.&nbsp;&nbsp;&nbsp;&nbsp; boolean existingTransaction =&nbsp;&nbsp;&nbsp; 9.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TransactionSynchronizationManager.hasResource(getSessionFactory());&nbsp; 10.&nbsp;&nbsp;&nbsp; if (!existingTransaction &amp;&amp; getFlushMode() == FLUSH_NEVER) {&nbsp; 11.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.setFlushMode(FlushMode.NEVER);&nbsp; 12.&nbsp;&nbsp;&nbsp; }&nbsp; 13.&nbsp;&nbsp;&nbsp; try {&nbsp; 14.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Object result = action.doInHibernate(session);&nbsp; 15.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; flushIfNecessary(session, existingTransaction);&nbsp; 16.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return result;&nbsp; 17.&nbsp;&nbsp;&nbsp; }&nbsp; 18.&nbsp;&nbsp;&nbsp; catch (HibernateException ex) {&nbsp; 19.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw convertHibernateAccessException(ex);&nbsp; 20.&nbsp;&nbsp;&nbsp; }&nbsp; 21.&nbsp;&nbsp;&nbsp; finally {&nbsp; 22.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SessionFactoryUtils.closeSessionIfNecessary(&nbsp; 23.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session, getSessionFactory());&nbsp; 24.&nbsp;&nbsp;&nbsp; }&nbsp; 25. }<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 而这个SessionFactoryUtils能否得到当前的session以及closeSessionIfNecessary是否真正关闭session，端取决于这个session是否用sessionHolder和这个sessionFactory在我们最开始提到的TransactionSynchronizationManager绑定。 </p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; public static void closeSessionIfNecessary(Session session, SessionFactory sessionFactory)</p>
<p><br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throws CleanupFailureDataAccessException {<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (session == null || TransactionSynchronizationManager.hasResource(sessionFactory)) {<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return;<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; logger.debug("Closing Hibernate session");<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; try {<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.close();<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (JDBCException ex) {<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // SQLException underneath<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex.getSQLException());<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; catch (HibernateException ex) {<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; throw new CleanupFailureDataAccessException("Could not close Hibernate session", ex);<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br>&nbsp;&nbsp;&nbsp; </p>
<p><br>&nbsp;&nbsp;&nbsp; 在这个过程中，若HibernateTemplate 发现自当前session有不是readOnly的transaction，就会获取到FlushMode.AUTO Session，使方法拥有写权限。也即是，如果有不是readOnly的transaction就可以由Flush.NEVER转为Flush.AUTO,拥有insert,update,delete操作权限，如果没有transaction，并且没有另外人为地设flush model的话，则doFilter的整个过程都是Flush.NEVER。所以受transaction保护的方法有写权限，没受保护的则没有。</p>
<p>可能的解決方式有：<br>1、将singleSession设为false，这样只要改web.xml，缺点是Hibernate Session的Instance可能会大增，使用的JDBC Connection量也会大增，如果Connection Pool的maxPoolSize设得太小，很容易就出问题。<br>2、在控制器中自行管理Session的FlushMode，麻烦的是每个有Modify的Method都要多几行程式。<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.setFlushMode(FlushMode.AUTO); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.update(user); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.flush(); <br>3、Extend OpenSessionInViewFilter，Override protected Session getSession(SessionFactory sessionFactory)，将FlushMode直接改为Auto。<br>4、让方法受Spring的事务控制。这就是常使用的方法： <br>采用spring的事务声明,使方法受transaction控制</p>
<p><br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean id="baseTransaction" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; abstract="true"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="transactionManager" ref="transactionManager"/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="proxyTargetClass" value="true"/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="transactionAttributes"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;props&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="get*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="find*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="load*"&gt;PROPAGATION_REQUIRED,readOnly&lt;/prop&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="save*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="add*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="update*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;prop key="remove*"&gt;PROPAGATION_REQUIRED&lt;/prop&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/props&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bean&gt; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean id="userService" parent="baseTransaction"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="target"&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;bean class="com.phopesoft.security.service.impl.UserServiceImpl"/&gt;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/property&gt;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/bean&gt; </p>
<p><br>&nbsp;<br>对于上例，则以save,add,update,remove开头的方法拥有可写的事务，如果当前有某个方法，如命名为importExcel()，则因没有transaction而没有写权限，这时若方法内有insert,update,delete操作的话，则需要手动设置flush model为Flush.AUTO,如</p>
<p>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.setFlushMode(FlushMode.AUTO); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.save(user); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; session.flush(); <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp; 尽管Open Session In View看起来还不错，其实副作用不少。看回上面OpenSessionInViewFilter的doFilterInternal方法代码，这个方法实际上是被父类的doFilter调用的，因此，我们可以大约了解的OpenSessionInViewFilter调用流程: request(请求)-&gt;open session并开始transaction-&gt;controller-&gt;View(Jsp)-&gt;结束transaction并close session.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp; 一切看起来很正确，尤其是在本地开发测试的时候没出现问题，但试想下如果流程中的某一步被阻塞的话，那在这期间connection就一直被占用而不释放。最有可能被阻塞的就是在写Jsp这步，一方面可能是页面内容大，response.write的时间长，另一方面可能是网速慢，服务器与用户间传输时间久。当大量这样的情况出现时，就有连接池连接不足，造成页面假死现象。</p>
<p>Open Session In View是个双刃剑，放在公网上内容多流量大的网站请慎用。</p>
<p>&nbsp;</p>
<p>另外：这样会产生一点危险性，毕竟把数据库访问的环境放到了表现层。（用VO）<br></p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/120900.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2007-05-30 14:05 <a href="http://www.blogjava.net/gm_jing/articles/120900.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate查询--(SQL)</title><link>http://www.blogjava.net/gm_jing/articles/66733.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Wed, 30 Aug 2006 14:59:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/66733.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/66733.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/66733.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/66733.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/66733.html</trackback:ping><description><![CDATA[
		<table cellspacing="1" cellpadding="3" width="100%" align="center" border="0">
				<tbody>
						<tr>
								<td class="code">
										<font size="2">Query queryObject = session.createSQLQuery( <br />                        "select {record.*}" + <br />                        " from " + tableName + " record, Vip_branch branch where branch.companyid = :companyid and branch.branchid = record.branchid order by record.time asc"). <br />                                    addEntity("record", Vip_record.class); <br />                queryObject.setLong("companyid", companyid); <br />                return queryObject.list();</font>
								</td>
						</tr>
				</tbody>
		</table>
		<span class="postbody">
				<br />
				<br />
				<font size="2">其中tableName为表名 <br /><br />得到统计结果也是类似的： <br /><br /></font>
		</span>
		<table cellspacing="1" cellpadding="3" width="100%" align="center" border="0">
				<tbody>
						<tr>
								<td class="code">
										<font size="2">Query queryObject = session.createSQLQuery( <br />                        "select count(*) as count" + <br />                        " from " + tableName + <br />                        " record where record.userid = :userid"). <br />                                    addScalar("count", Hibernate.INTEGER); </font>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/gm_jing/aggbug/66733.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-30 22:59 <a href="http://www.blogjava.net/gm_jing/articles/66733.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>拦截器---Interceptor</title><link>http://www.blogjava.net/gm_jing/articles/66259.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Mon, 28 Aug 2006 12:07:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/66259.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/66259.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/66259.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/66259.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/66259.html</trackback:ping><description><![CDATA[
		<p>Hibernate拦截器可以有两种:<tt class="literal">Session</tt>范围内的，和<tt class="literal">SessionFactory</tt>范围内的。 </p>
		<p>(1)当使用某个重载的SessionFactory.openSession()使用<tt class="literal">Interceptor</tt>作为参数调用打开一个session的时候，就指定了<tt class="literal">Session</tt>范围内的拦截器。 </p>
		<pre class="programlisting">Session session = sf.openSession( new AuditInterceptor() );</pre>
		<p>
				<tt class="literal">(2)SessionFactory</tt>范围内的拦截器要通过<tt class="literal">Configuration</tt>中注册，而这必须在创建<tt class="literal">SessionFactory</tt>之前。在这种情况下，给出的拦截器会被这个<tt class="literal">SessionFactory</tt>所打开的所有session使用了；除非session打开时明确指明了使用的拦截器。<tt class="literal">SessionFactory</tt>范围内的拦截器，必须是线程安全的，因为多个session可能并发使用这个拦截器，要因此小心不要保存与session相关的状态。 </p>
		<pre class="programlisting">new Configuration().setInterceptor( new AuditInterceptor() );<hr /><br /><div><div style="PADDING-RIGHT: 5px; BORDER-TOP: #000000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 14px; PADDING-BOTTOM: 5px; MARGIN: 0px 5px; OVERFLOW: scroll; WIDTH: 73.24%; COLOR: #000000; PADDING-TOP: 5px; BORDER-BOTTOM: #000000 1px solid; FONT-FAMILY: Courier New; HEIGHT: 228px; BACKGROUND-COLOR: #e2e2e2"><p>package com.jason.interceptor;</p><p>import java.io.Serializable;</p><p>import org.hibernate.EmptyInterceptor;<br />import org.hibernate.Transaction;<br />import org.hibernate.type.Type;<br /><br />public class UserInterceptor extends EmptyInterceptor {</p><p>    private int updates;<br />    private int creates;<br />    private int loads;</p><p>    public void onDelete(Object entity,<br />                         Serializable id,<br />                         Object[] state,<br />                         String[] propertyNames,<br />                         Type[] types) {<br />        // do nothing<br />    }</p><p>    public boolean onFlushDirty(Object entity,<br />                                Serializable id,<br />                                Object[] currentState,<br />                                Object[] previousState,<br />                                String[] propertyNames,<br />                                Type[] types) {</p><p>        if ( entity instanceof User ) {<br />            updates++;<br />            <br />        }<br />        return false;<br />    }</p><p>    public boolean onLoad(Object entity,<br />                          Serializable id,<br />                          Object[] state,<br />                          String[] propertyNames,<br />                          Type[] types) {<br />        if ( entity instanceof User ) {<br />            loads++;<br />            for ( int i=0; i&lt;propertyNames.length; i++ ) {<br />                if ( "password".equals( propertyNames[i] ) ) {<br />                 String temp = (state[i]).toString();<br />                    state[i] = temp.substring(3, temp.length()-3);<br />                    return true;<br />                }<br />            }<br />        }<br />        return false;<br />    }</p><p>    public boolean onSave(Object entity,<br />                          Serializable id,<br />                          Object[] state,<br />                          String[] propertyNames,<br />                          Type[] types) {</p><p>        if ( entity instanceof User ) {<br />            creates++;<br />            for ( int i=0; i&lt;propertyNames.length; i++ ) {<br />                if ( "password".equals( propertyNames[i] ) ) {<br />                    state[i] = "abc" +state[i] + "xyz";<br />                    return true;<br />                }<br />            }<br />        }<br />        return false;<br />    }</p><p>    public void afterTransactionCompletion(Transaction tx) {<br />        if ( tx.wasCommitted() ) {<br />            System.out.println("Creations: " <br />+ creates + ", Updates: " + updates + ",Loads: " + loads);<br />        }<br />        updates=0;<br />        creates=0;<br />        loads=0;<br />    }</p><p>}</p></div><br />【注】String[] propertyNames  -- 属性名称<br />      Object[] state         -- 属性对应的值<br /><br /><br /><br /><br /><br /><br /><br /><br /><br /></div><div><br /><br /><br /><br /><br /><br /><br /><br />test:<br />Session session = sf.openSession(new UserInterceptor());<br /><br />session.load(class, id);<br />session.save(obj);</div></pre>
<img src ="http://www.blogjava.net/gm_jing/aggbug/66259.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-28 20:07 <a href="http://www.blogjava.net/gm_jing/articles/66259.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate查询--(Criteria Query)</title><link>http://www.blogjava.net/gm_jing/articles/66252.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Mon, 28 Aug 2006 11:36:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/66252.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/66252.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/66252.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/66252.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/66252.html</trackback:ping><description><![CDATA[
		<h2>Hibernate条件查询(Criteria Query)</h2>
		<script type="text/javascript">
				<!--
google_ad_client = "pub-4889396483226874";
google_ad_width = 728;
google_ad_height = 90;
google_ad_format = "728x90_as";
google_ad_type = "text_image";
google_ad_channel ="";
google_color_border = "FFFFFF";
google_color_bg = "FFFFFF";
google_color_link = "0000FF";
google_color_text = "000000";
google_color_url = "000000";
//-->
		</script>
		<script src="http://pagead2.googlesyndication.com/pagead/show_ads.js" type="text/javascript">
		</script>
		<br />
		<table style="WORD-BREAK: break-all" cellspacing="0" cellpadding="0" width="100%" align="center" border="0">
				<tbody>
						<tr>
								<td width="20" rowspan="2">
										<font color="#993300" size="2">
										</font>
								</td>
								<td class="info_txt" id="fontsize_6562" valign="top" height="97">
										<p>
												<font color="#993300">
														<font size="2">
																<strong>1、创建一个Criteria实例</strong>
																<br />net.sf.hibernate.Criteria这个接口代表对一个特定的持久化类的查询。Session是用来制造Criteria实例的工厂。 </font>
												</font>
										</p>
										<p>
												<font color="#993300" size="2">Criteria crit = sess.createCriteria(Cat.class);<br />crit.setMaxResults(50);<br />List cats = crit.list();</font>
										</p>
										<p>
												<br />
												<font color="#993300">
														<font size="2">
																<strong>2、缩小结果集范围</strong>
																<br />一个查询条件(Criterion)是net.sf.hibernate.expression.Criterion接口的一个实例。类net.sf.hibernate.expression.Expression定义了获得一些内置的Criterion类型。 </font>
												</font>
										</p>
										<p>
												<font color="#993300" size="2">List cats = sess.createCriteria(Cat.class)<br />    .add( Expression.like("name", "Fritz%") )<br />    .add( Expression.between("weight", minWeight, maxWeight) )<br />    .list();<br />表达式（Expressions）可以按照逻辑分组. </font>
										</p>
										<p>
												<font color="#993300" size="2">List cats = sess.createCriteria(Cat.class)<br />    .add( Expression.like("name", "Fritz%") )<br />    .add( Expression.or(<br />     Expression.eq( "age", new Integer(0) ),<br />     Expression.isNull("age")<br />    ) )<br />    .list();<br />List cats = sess.createCriteria(Cat.class)<br />    .add( Expression.in( "name", new String[] { "Fritz", "Izi", "Pk" } ) )<br />    .add( Expression.disjunction()<br />        .add( Expression.isNull("age") )<br />     .add( Expression.eq("age", new Integer(0) ) )<br />     .add( Expression.eq("age", new Integer(1) ) )<br />     .add( Expression.eq("age", new Integer(2) ) )<br />    ) )<br />    .list();<br />有很多预制的条件类型（Expression的子类）。有一个特别有用，可以让你直接嵌入SQL。 </font>
										</p>
										<p>
												<font color="#993300" size="2">List cats = sess.createCriteria(Cat.class)<br />    .add( Expression.sql("lower($alias.name) like lower(?)", "Fritz%", Hibernate.STRING) )<br />    .list();<br />其中的{alias}是一个占位符，它将会被所查询实体的行别名所替代。(原文:The {alias} placeholder with be replaced by the row alias of the queried entity.) </font>
										</p>
										<p>
												<font color="#993300">
														<font size="2">
																<strong>3、对结果排序</strong>
																<br />可以使用net.sf.hibernate.expression.Order对结果集排序. </font>
												</font>
										</p>
										<p>
												<font color="#993300" size="2">List cats = sess.createCriteria(Cat.class)<br />    .add( Expression.like("name", "F%")<br />    .addOrder( Order.asc("name") )<br />    .addOrder( Order.desc("age") )<br />    .setMaxResults(50)<br />    .list();<br /><strong>4、关联（Associations）</strong><br />你可以在关联之间使用createCriteria()，很容易地在存在关系的实体之间指定约束。 </font>
										</p>
										<p>
												<font color="#993300" size="2">List cats = sess.createCriteria(Cat.class)<br />    .add( Expression.like("name", "F%")<br />    .createCriteria("kittens")<br />        .add( Expression.like("name", "F%")<br />    .list();<br />注意，第二个createCriteria()返回一个Criteria的新实例，指向kittens集合类的元素。 </font>
										</p>
										<p>
												<font color="#993300" size="2">下面的替代形式在特定情况下有用。 </font>
										</p>
										<p>
												<font color="#993300" size="2">List cats = </font>
												<font color="#993300">
														<font size="2">
																<strong>sess.createCriteria(Cat.class)<br />    .createAlias("kittens", "kt")<br /></strong>    .createAlias("mate", "mt")<br />    .add( Expression.eqProperty("kt.name", "mt.name") )<br />    .list();<br />（createAlias()）并不会创建一个Criteria的新实例。） </font>
												</font>
										</p>
										<p>
												<font color="#993300" size="2">请注意，前面两个查询中Cat实例所持有的kittens集合类并没有通过criteria预先过滤！如果你希望只返回满足条件的kittens,你必须使用returnMaps()。 </font>
										</p>
										<p>
												<font color="#993300" size="2">List cats = sess.createCriteria(Cat.class)<br />    .createCriteria("kittens", "kt")<br />        .add( Expression.eq("name", "F%") )<br />    .returnMaps()<br />    .list();<br />Iterator iter = cats.iterator();<br />while ( iter.hasNext() ) {<br />    Map map = (Map) iter.next();<br />    Cat cat = (Cat) map.get(Criteria.ROOT_ALIAS);<br />    Cat kitten = (Cat) map.get("kt");<br />}<br /></font>
												<font color="#993300">
														<font size="2">
																<strong>5、动态关联对象获取（Dynamic association fetching）<br /></strong>可以在运行时通过setFetchMode()来改变关联对象自动获取的策略。 </font>
												</font>
										</p>
										<p>
												<font color="#993300" size="2">List cats = sess.createCriteria(Cat.class)<br />    .add( Expression.like("name", "Fritz%") )<br />    .setFetchMode("mate", FetchMode.EAGER)<br />    .list();<br />这个查询会通过外连接(outer join)同时获得 mate和kittens。 </font>
										</p>
										<p>
												<font color="#993300">
														<font size="2">
																<strong>6、根据示例查询（Example queries）</strong>
																<br />net.sf.hibernate.expression.Example类允许你从指定的实例创造查询条件。 </font>
												</font>
										</p>
										<p>
												<font color="#993300" size="2">Cat cat = new Cat();<br />cat.setSex('F');<br />cat.setColor(Color.BLACK);<br />List results = session.createCriteria(Cat.class)<br />    .add( Example.create(cat) )<br />    .list();<br />版本属性，表示符属性和关联都会被忽略。默认情况下，null值的属性也被排除在外。 </font>
										</p>
										<p>
												<font color="#993300" size="2">You can adjust how the Example is applied. 你可以调整示例(Example)如何应用。 </font>
										</p>
										<p>
												<font color="#993300" size="2">Example example = Example.create(cat)<br />    .excludeZeroes()           //exclude zero valued properties<br />    .excludeProperty("color")  //exclude the property named "color"<br />    .ignoreCase()              //perform case insensitive string comparisons<br />    .enableLike();             //use like for string comparisons<br />List results = session.createCriteria(Cat.class)<br />    .add(example)<br />    .list();<br />你甚至可以用示例对关联对象建立criteria。 </font>
										</p>
										<p>
												<font color="#993300" size="2">List results = session.createCriteria(Cat.class)<br />    .add( Example.create(cat) )<br />    .createCriteria("mate")<br />        .add( Example.create( cat.getMate() ) )<br />    .list();</font>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/gm_jing/aggbug/66252.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-28 19:36 <a href="http://www.blogjava.net/gm_jing/articles/66252.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate查询--(HQL)</title><link>http://www.blogjava.net/gm_jing/articles/66179.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Mon, 28 Aug 2006 06:47:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/66179.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/66179.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/66179.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/66179.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/66179.html</trackback:ping><description><![CDATA[<p>//HQL-Associations <br />
String hql = "select s.name, p.name, p.price from Product p inner join p.supplier as s";<br />
Query query = session.createQuery(hql);<br />
List results = query.list();</p>
<p><br />
//HQL-Delete<br />
String hql = "delete from Product where name = :name";<br />
Query query = session.createQuery(hql);<br />
query.setString("name","Product 1");<br />
int rowCount = query.executeUpdate();</p>
<p><br />
//HQL-Function<br />
String hql = "select min(product.price), max(product.price) from Product product";<br />
Query query = session.createQuery(hql);<br />
List results = query.list();</p>
<p><br />
//HQL-Fetch Associations HQL Inner Join <br />
String hql = "from Supplier s inner join fetch s.products as p";<br />
Query query = session.createQuery(hql);<br />
List results = query.list();</p>
<p><br />
//HQL-Named Parameters <br />
String hql = "from Product where price &gt; :price";<br />
Query query = session.createQuery(hql);<br />
query.setDouble("price",2.0);<br />
List results = query.list();<br />
String hql = "from Product as product where product.supplier=:supplier";<br />
Query query = session.createQuery(hql);<br />
query.setEntity("supplier",supplier);<br />
List results = query.list();</p>
<p><br />
//HQL-Update <br />
String hql = "update Supplier set name = :newName where name = :name";<br />
Query query = session.createQuery(hql);<br />
query.setString("name","Supplier Name 1");<br />
query.setString("newName","s1");<br />
int rowCount = query.executeUpdate();</p>
<p><br />
//HQL-where <br />
String hql = "from Product where price &gt; 2.0 and name like 'P%'";<br />
Query query = session.createQuery(hql);<br />
List results = query.list();</p>
<p>//HQL-Map<br />
String hql = " select new map(usr.name as userName, usr.password as password) from User usr";<br />
Query query = session.createQuery(hql);<br />
List list = query.list();<br />
Map goods =(Map)list.get(0);<br />
<br />
【注】<br />
&nbsp;&nbsp;&nbsp;String hql = " select new map(usr.name as userName, usr.password as password)<font style="background-color: #ff1493">　from</font> com.jason.User usr";<br />
&nbsp;&nbsp;&nbsp;String hql = " select new map(usr.name as userName, usr.password as password)&nbsp;from com.jason.User usr";<br />
由于from之前的空格，引起unexpected token: 　from<br />
<br />
<br />
<br />
<table style="table-layout: fixed">
    <tbody>
        <tr>
            <td>
            <div class="cnt" id="blog_text">
            <p><span class="Apple-style-span" style="word-spacing: 0px; font: 12px Verdana; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0"><font color="#ff0000"><font size="2"><span class="Apple-style-span" style="word-spacing: 0px; font: 12px Verdana; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0"><font color="#ff0000"><font color="#0000ff">查询语句可以返回值为任何类型的属性或对象，包括返回类型为某种组件(Component)的属性:</font><br />
            </font></span></font><font size="1"><span class="Apple-style-span" style="word-spacing: 0px; font: 12px Verdana; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0">select <font color="#ff0000">cust.name.firstName </font>from Customer as cust<br />
            <span class="Apple-style-span" style="word-spacing: 0px; font: 12px Verdana; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0">select <font color="#ff0000">cat.mate </font>from Cat cat</span></span></font></font></span></p>
            <p><span class="Apple-style-span" style="word-spacing: 0px; font: 12px Verdana; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0"><font size="+0"><font color="#ff0000" size="1"><span class="Apple-style-span" style="word-spacing: 0px; font: 12px Verdana; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0"><span class="Apple-style-span" style="word-spacing: 0px; font: 12px Verdana; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0"><span class="Apple-style-span" style="word-spacing: 0px; font: 12px Verdana; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0"><font color="#0000ff">查询语句可以返回多个对象和（或）属性，存放在<span class="Apple-converted-space"> </span><tt class="literal"><font face="新宋体">Object[]</font></tt>队列中:</font><font color="#ff0000"><br />
            <span class="Apple-style-span" style="word-spacing: 0px; font: 12px Verdana; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0">select <font color="#ff0000">mother</font>, <font color="#ff0000">offspr</font>, <font color="#ff0000">mate.name</font> <br />
            from DomesticCat as <font color="#ff0000">mother</font><br />
            &nbsp;&nbsp;&nbsp; inner join mother.mate as <font color="#ff0000">mate</font><br />
            &nbsp;&nbsp;&nbsp; left join mother.kittens as <font color="#ff0000">offspr</font></span><br />
            </font></span></span></span></font></font></span></p>
            <span class="Apple-style-span" style="word-spacing: 0px; font: 12px Verdana; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0">
            <p style="margin: 10px 0px"><font color="#0000ff">或存放在一个<tt class="literal"><font face="新宋体">List</font></tt>对象中:</font><br />
            select <font color="#ff0000">new list</font>(mother, offspr, mate.name<font color="#ff0000">)<br />
            </font>from DomesticCat as <font color="#ff0000">mother</font><br />
            &nbsp;&nbsp;&nbsp; inner join mother.mate as <font color="#ff0000">mate</font><br />
            &nbsp;&nbsp;&nbsp; left outer join mother.kittens as <font color="#ff0000">offspr</font></p>
            <p style="margin: 10px 0px"></p>
            <span class="Apple-style-span" style="word-spacing: 0px; font: 12px Verdana; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0">
            <p style="margin: 10px 0px"><font color="#0000ff">也可能直接返回一个实际的类型安全的Java对象(<span class="Apple-style-span" style="word-spacing: 0px; font: 12px Verdana; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0"><font color="#0000ff">假设类<tt class="literal"><font face="新宋体">Family</font></tt>有一个合适的构造函数</font></span>):<br />
            </font>select <font color="#ff0000">new Family(</font>mother, mate, offspr<font color="#ff0000">)</font><br />
            from DomesticCat as <font color="#ff0000">mother</font><br />
            &nbsp;&nbsp;&nbsp; join mother.mate as <font color="#ff0000">mate</font><br />
            &nbsp;&nbsp;&nbsp; left join mother.kittens as <font color="#ff0000">offspr</font></p>
            <font color="#ff0000"><span class="Apple-style-span" style="word-spacing: 0px; font: 12px Verdana; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0">
            <p style="margin: 10px 0px"><font color="#0000ff">也可以使用关键字<tt class="literal"><font face="新宋体">as</font></tt>给&#8220;被选择了的表达式&#8221;指派别名:</font><br />
            select max(bodyWeight) as <font color="#ff0000">max</font>, min(bodyWeight) as <font color="#ff0000">min</font>, count(*) as <font color="#ff0000">n</font><br />
            from Cat cat<br />
            <span class="Apple-style-span" style="word-spacing: 0px; font: 12px Verdana; text-transform: none; color: rgb(0,0,0); text-indent: 0px; white-space: normal; letter-spacing: normal; border-collapse: separate; orphans: 2; widows: 2; -webkit-border-horizontal-spacing: 0px; -webkit-border-vertical-spacing: 0px; -webkit-text-decorations-in-effect: none; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0"><font color="#0000ff">这种做法在与子句<tt class="literal"><font face="新宋体">select new map</font></tt>一起使用时最有用:</font><br />
            select <font color="#0000ff">new map(</font> max(bodyWeight) as max, min(bodyWeight) as min, count(*) as n <font color="#0000ff">)</font><br />
            from Cat cat</span></p>
            </span></font></span>
            <p>&nbsp;</p>
            </span></div>
            </td>
        </tr>
    </tbody>
</table>
</p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/66179.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-28 14:47 <a href="http://www.blogjava.net/gm_jing/articles/66179.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>composite-id 学习</title><link>http://www.blogjava.net/gm_jing/articles/65462.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Thu, 24 Aug 2006 02:42:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/65462.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/65462.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/65462.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/65462.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/65462.html</trackback:ping><description><![CDATA[
		<p>组件作为联合标识符,必须满足： <br />它必须实现java.io.Serializable接口 <br />它必须重新实现equals()和hashCode()方法, 始终和组合关键字在数据库中的概念保持一致 <br />你不能使用一个IdentifierGenerator产生组合关键字。一个应用程序必须分配它自己的标识符。 <br />【注意：在Hibernate3中，第二个要求并非是Hibernate强制必须的。但最好这样做。】<br /><br /> &lt;class name="com.jason.compositeId.OrderDetail" table="t_orderdetail"&gt;<br />  &lt;composite-id name="id" class="com.jason.compositeId.CompositeId"&gt;<br />      &lt;key-property name="orderId" column="order_id" /&gt;<br />      &lt;key-property name="itemId" column="item_id" /&gt;<br />  &lt;/composite-id&gt;<br />  &lt;property name="count" column="count" type="int" /&gt;<br /> &lt;/class&gt;<br /></p>
		<hr />
		<p> &lt;!--<br />  create table t_orderdetail ( order_id bigint not null, item_id bigint not null, count bigint not null, primary key(order_id, item_id) )<br /> --&gt;<br />  </p>
		<hr />
		<br /> <br />public class CompositeId <font color="#ff1493">implements Serializable</font>{<br /> private int orderId;<br /> private int itemId;<br /> public int getItemId() {<br />  return itemId;<br /> }<br /> public void setItemId(int itemId) {<br />  this.itemId = itemId;<br /> }<br /> public int getOrderId() {<br />  return orderId;<br /> }<br /> public void setOrderId(int orderId) {<br />  this.orderId = orderId;<br /> }<br /> @Override<br /> public boolean <font color="#ff1493">equals</font>(Object obj) {<br />  return super.equals(obj);<br /> }<br /> @Override<br /> public int <font color="#ff1493">hashCode()</font> {<br />  return (orderId + itemId)^2;<br /> }<br />  <br />}
<p></p><hr /><br />public class OrderDetail {<br /> private CompositeId id;<br /> private int count;<br /> <br /> public int getCount() {<br />  return count;<br /> }<br /> public void setCount(int count) {<br />  this.count = count;<br /> }<br /> public CompositeId getId() {<br />  return id;<br /> }<br /> public void setId(CompositeId id) {<br />  this.id = id;<br /> }<br />}<img src ="http://www.blogjava.net/gm_jing/aggbug/65462.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-24 10:42 <a href="http://www.blogjava.net/gm_jing/articles/65462.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>集合映射</title><link>http://www.blogjava.net/gm_jing/articles/65310.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Wed, 23 Aug 2006 08:49:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/65310.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/65310.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/65310.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/65310.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/65310.html</trackback:ping><description><![CDATA[
		<p>
				<font color="#0000ff" size="4">
						<strong> Array<br /><br /></strong>
				</font>&lt;class name="com.jason.collections.array.Person" table="PERSON"&gt;<br />  &lt;id name="id" column="PERSON_ID"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;property name="name" column="PERSON_NAME"/&gt;<br />  <br />  &lt;array name="events" cascade="all" fetch="join"  &gt;<br />    &lt;key column="PERSON_ID"/&gt;<br />    &lt;list-index column="idx"/&gt; &lt;!--list-index, index...--&gt;<br />    &lt;one-to-many class="com.jason.collections.array.Event"/&gt;<br />    &lt;!--&lt;element column="title" type="string" /&gt;--&gt;<br />  &lt;/array&gt;<br /> <br /> &lt;/class&gt;<br /> &lt;class name="com.jason.collections.array.Event" table="EVENT"&gt;<br />  &lt;id name="id" column="EVENT_ID"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;property name="title"/&gt;<br /> &lt;/class&gt;<br /> <br /> &lt;!--<br />  CREATE TABLE person (person_Id int PRIMARY KEY, person_Name varchar(20))<br />  CREATE TABLE Event (Event_Id int PRIMARY KEY, PERSON_ID int not null, idx int not null, title varchar2(20))<br /> --&gt;</p>
		<p>
		</p>
		<hr />
		<br /> <font color="#0000ff" size="4"><strong>Bag<br /></strong></font><br /> &lt;class name="com.jason.collections.bag.Person" table="PERSON"&gt;<br />  &lt;id name="id" column="PERSON_ID"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;property name="name" column="PERSON_NAME"/&gt;<br />  <br />  &lt;bag name="events" cascade="all"&gt;<br />   &lt;key column="PERSON_ID"/&gt;<br />   &lt;one-to-many class="com.jason.collections.bag.Event"/&gt;<br />    &lt;!--&lt;element column="title" type="string" /&gt;--&gt;<br />  &lt;/bag&gt;<br /> &lt;/class&gt;<br /> <br /> &lt;class name="com.jason.collections.bag.Event" table="EVENT"&gt;<br />  &lt;id name="id" column="EVENT_ID"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;property name="title"/&gt;<br /> &lt;/class&gt;<br /> &lt;!--<br />  CREATE TABLE person (person_Id int PRIMARY KEY, person_Name varchar(20))<br />  CREATE TABLE Event (Event_Id int PRIMARY KEY, PERSON_ID int not null, title varchar2(20))<br /> --&gt;<br /> <br />  
<hr /><br /> <font color="#0000ff" size="4"><strong>Set<br /></strong></font><br /> &lt;class name="com.jason.collections.set.Person" table="PERSON"&gt;<br />  &lt;id name="id" column="PERSON_ID"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;property name="name" column="PERSON_NAME"/&gt; 
<p>  &lt;set name="events" cascade="all"&gt;<br />   &lt;key column="PERSON_ID"/&gt; <br />   &lt;one-to-many class="com.jason.collections.set.Event"/&gt;<br />   &lt;!--&lt;element column="title" type="string" /&gt;--&gt;<br />  &lt;/set&gt;</p><p> &lt;/class&gt;<br /> &lt;class name="com.jason.collections.set.Event" table="EVENT"&gt;<br />  &lt;id name="id" column="EVENT_ID"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;property name="title"/&gt;<br /> &lt;/class&gt;<br /> &lt;!--<br />  CREATE TABLE person (person_Id int PRIMARY KEY, person_Name varchar(20))<br />  CREATE TABLE Event (Event_Id int PRIMARY KEY, PERSON_ID int not null, title varchar2(20))<br /> --&gt;<br /> <br />  </p><hr /><br /> <font color="#0000ff" size="4"><strong>Map</strong></font><br />&lt;class name="com.jason.collections.map.Person" table="PERSON"&gt;<br />  &lt;id name="id" column="PERSON_ID"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;property name="name" column="PERSON_NAME"/&gt;<br />  <br />  &lt;map name="events" table="event"&gt;<br />        &lt;key column="PERSON_ID"/&gt;<br />        &lt;index column="name" type="string"/&gt;<br />        &lt;element column="title" type="string"/&gt;<br />    &lt;/map&gt; <br /> &lt;/class&gt;<br /> <br /> &lt;!--<br />  CREATE TABLE person (person_Id int PRIMARY KEY, person_Name varchar(20))<br />  CREATE TABLE Event (Event_Id int PRIMARY KEY, person_Id int, name varchar2(20), title varchar2(20)) 
<p></p><p> --&gt;</p><img src ="http://www.blogjava.net/gm_jing/aggbug/65310.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-23 16:49 <a href="http://www.blogjava.net/gm_jing/articles/65310.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关联映射-----&gt;&gt;&gt;总结</title><link>http://www.blogjava.net/gm_jing/articles/64689.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Sun, 20 Aug 2006 16:31:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/64689.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/64689.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/64689.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/64689.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/64689.html</trackback:ping><description><![CDATA[
		<p>
				<br />set的使用<br />&lt;set name="addresses" cascade="all"&gt;<br /> &lt;!--key 是Address表的字段，最后要update Address表.personId = Person表.personId--&gt;<br /> &lt;key column="personId"  not-null="true"/&gt;<br /> &lt;one-to-many <br />     class="com.jason.associations.one2many.unilateralism.one2many.Address"/&gt;<br />&lt;/set&gt;</p>
		<p>&lt;set name="addresses" table="PersonAddress" cascade="all"&gt;<br />      &lt;key column="personId"/&gt;<br />      &lt;many-to-many column="addressId"<br />          unique="true"<br />          class="com.jason.associations.one2many.unilateralism.one2many.table.Address"/&gt;<br />&lt;/set&gt;</p>
		<p>
		</p>
		<hr />
		<br />关联表的使用<br />&lt;join table="PersonAddress" optional="true"&gt;<br />   &lt;key column="personId" unique="true"/&gt;<br />   &lt;many-to-one name="address"<br />       column="addressId" <br />       not-null="true" <br />       cascade="all"<br />       .../&gt;<br />&lt;/join&gt; 
<p>//set,Array,bag,map都行<br />&lt;set name="addresses" table="PersonAddress" cascade="all"&gt;<br />       &lt;key column="personId"/&gt;<br />       &lt;many-to-many column="addressId"<br />           unique="true"<br />           class="com.jason.associations.one2many.unilateralism.one2many.table.Address"/&gt;<br />&lt;/set&gt;<br /></p><br />&lt;map name="events" table="event"&gt;<br />         &lt;key column="PERSON_ID"/&gt;<br />         &lt;index column="name" type="string"/&gt;<br />         &lt;element column="content" type="string"/&gt;<br /> &lt;/map&gt;  
<hr /><p></p><p>&lt;<font color="#ff1493">many-to-one name="address" <br />   class="com.jason.associations.one2one.unilateralism.foreign.Address"   <br />   unique="true"</font><br />   <font color="#0000ff">column="addressId" <br />   cascade="all"<br />   not-null="true"/</font>&gt;</p><p>&lt;<font color="#ff1493">one-to-one name="person" <br />   class="com.jason.associations.one2one.unilateralism.primary.Person"<br />   constrained="true"/</font>&gt;<br />   <br />1、都表示一对一 ,many-to-one指定了对应的column（和column相关的属性cascade，not-null...）<br />       而one-to-one没有对应的column，它主要用于id的generator class="foreign"中<br />2、同样也适用于&lt;many-to-many unique="true"&gt;和&lt;one-to-many&gt;<br /><br /></p><hr /><p><br />&lt;one-to-many&gt;<br />&lt;many-to-one&gt;<br />不管哪个，对应的表是这样的，把one那张表的key，放到many对应的表中，相当于外键。</p><p><br /></p><hr /><br />&lt;one-to-?&gt; 
<p>&lt;set name="addresses" cascade="all"&gt;<br /> &lt;!--key 是Address表的字段，最后要update Address表.personId = Person表.personId--&gt;<br /> &lt;key column="personId"  not-null="true"/&gt;<br /> &lt;one-to-many <br />     class="com.jason.associations.one2many.unilateralism.one2many.Address"/&gt;<br />&lt;/set&gt;</p><p>&lt;id name="id" column="addressId"&gt;<br />    &lt;generator class="foreign"&gt;<br />   &lt;param name="property"&gt;person&lt;/param&gt;<br />  &lt;/generator&gt;<br />&lt;/id&gt;<br />&lt;one-to-one name="person" <br />  class="com.jason.associations.one2one.unilateralism.primary.Person"<br />  constrained="true"/&gt;<br />  <br />&lt;one-to-many&gt;和&lt;one-to-one&gt;都没有column属性，因为one对应的那边不需要相应的列，<br />那么如何保持关系呢？<br />1、最好不使用，<img height="19" src="http://www.blogjava.net/Emoticons/emsmilep.gif" width="19" border="0" /><br />2、向上面那样指定一下</p><p><br /></p><p></p><hr /><br />column的位置<br />1、大多数时候在这个class对应的表中<br />2、在关联表中<br />3、在指定的class对应的表中<br />例如：<br />&lt;set name="addresses" cascade="all"&gt;<br /> &lt;!--key 是Address表的字段，最后要update Address表.personId = Person表.personId--&gt;<br /> &lt;key column="personId"  not-null="true"/&gt;<br /> &lt;one-to-many <br />     class="com.jason.associations.one2many.unilateralism.one2many.Address"/&gt;<br />&lt;/set&gt;   <br /><br /><hr /><br />unique<br />&lt;many-to-? <br />    unique="true"<br />    ..."/&gt;<br />unique是相对于前面的many<br /><hr /><br />inverse 
<p>&lt;class name="Address"&gt;<br />    &lt;id name="id" column="addressId"&gt;<br />        &lt;generator class="native"/&gt;<br />    &lt;/id&gt;<br />    &lt;join table="PersonAddress" <br />        inverse="true" <br />        optional="true"&gt;<br />        &lt;key column="addressId"/&gt;<br />        &lt;many-to-one name="person"<br />            column="personId"<br />            not-null="true"/&gt;<br />    &lt;/join&gt;<br />&lt;/class&gt;<br />         1、为了更好地提高执行效率，需要将“多”的一端设为主控方，就是将关联关系的维护工作交给“多”的一端。inverse="true" 说明主控表是Person表（Address表对面）inverse="false"本身，默认值：false<br /><br />   2、<font face="Courier New">inverse="true"</font>可以出现在关联的任意一端，即collection端或者join端。</p><p></p><hr />
Constrained : 约束，表明主控表的主键上是否存在一个外键（foreigh key）对其进行约束。<br /><br /><hr />
 property-ref:关联类中用于与主控类相关联的属性名，默认为关联类的主键属性名<br /><br /><hr />
 lazy=false:被动方的记录由hibernate负责记取，之后存放在主控方指定的   Collection类型属性中 <br /><br /><hr />
 batch-size:采用延迟加载特征时，一次读入的数据数昨<br /><br /><hr />
 <br /><br /><img src ="http://www.blogjava.net/gm_jing/aggbug/64689.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-21 00:31 <a href="http://www.blogjava.net/gm_jing/articles/64689.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>many2many关联</title><link>http://www.blogjava.net/gm_jing/articles/64688.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Sun, 20 Aug 2006 16:28:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/64688.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/64688.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/64688.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/64688.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/64688.html</trackback:ping><description><![CDATA[
		<p>
				<br />多对多相对于连接表的，有两种<br />1、使用连接表的单向多对多关联<br /> &lt;class name="com.jason.associations.many2many.unilateralism.Person" table="Person"&gt;<br />  &lt;id name="id" column="personId"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;set name="addresses" table="PersonAddress" cascade="all"&gt;<br />   &lt;key column="personId" not-null="true"/&gt;<br />   &lt;many-to-many <br />    column="addressId"<br />    class="com.jason.associations.many2many.unilateralism.Address"/&gt;<br />  &lt;/set&gt;<br />  &lt;property name="name" column="personName" type="string" /&gt;<br /> &lt;/class&gt;<br /> <br /> &lt;class name="com.jason.associations.many2many.unilateralism.Address" table="Address"&gt;<br />  &lt;id name="id" column="addressId"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;property name="country" column="country" type="string" /&gt;<br />  &lt;property name="city" column="city" type="string" /&gt;<br /> &lt;/class&gt;<br /> &lt;!--<br />  create table Person ( personId bigint not null primary key, personName varchar(20))<br />  create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId))<br />  create table Address ( addressId bigint not null primary key, country varchar(20), city varchar(20) )<br /> --&gt;<br /> </p>
		<p>2、使用连接表的双向多对多关联<br /> &lt;class name="com.jason.associations.many2many.both.Person" table="Person"&gt;<br />  &lt;id name="id" column="personId"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;set name="addresses" table="PersonAddress" cascade="all"&gt;<br />   &lt;key column="personId" not-null="true"/&gt;<br />   &lt;many-to-many <br />    column="addressId"<br />    class="com.jason.associations.many2many.both.Address"/&gt;<br />  &lt;/set&gt;<br />  &lt;property name="name" column="personName" type="string" /&gt;<br /> &lt;/class&gt;<br /> <br /> &lt;class name="com.jason.associations.many2many.both.Address" table="Address"&gt;<br />  &lt;id name="id" column="addressId"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;set name="persons" table="PersonAddress" inverse="false" cascade="all"&gt;<br />   &lt;key column="addressId" not-null="true"/&gt;<br />   &lt;many-to-many <br />    column="personId"<br />    class="com.jason.associations.many2many.both.Person"/&gt;<br />  &lt;/set&gt;<br />  &lt;property name="country" column="country" type="string" /&gt;<br />  &lt;property name="city" column="city" type="string" /&gt;<br /> &lt;/class&gt;<br /> &lt;!--<br />  create table Person ( personId bigint not null primary key, personName varchar(20))<br />  create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId))<br />  create table Address ( addressId bigint not null primary key, country varchar(20), city varchar(20) )<br /> --&gt;</p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/64688.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-21 00:28 <a href="http://www.blogjava.net/gm_jing/articles/64688.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>one2many关联</title><link>http://www.blogjava.net/gm_jing/articles/64407.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Fri, 18 Aug 2006 09:21:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/64407.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/64407.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/64407.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/64407.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/64407.html</trackback:ping><description><![CDATA[ 二、单向关系<br /> 1.“单向一对多关系”<br /> 基于外键关联的单向一对多关联是一种很少见的情况，并不推荐使用<br /> &lt;class name="com.jason.associations.one2many.unilateralism.one2many.Person" table="Person"&gt;<br />  &lt;id name="id" column="personId"&gt;<br />      &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;set name="addresses" cascade="all"&gt;<br />      &lt;!--key 是Address表的字段，最后要update Address表.personId = Person表.personId--&gt;<br />      &lt;key column="personId"  not-null="true"/&gt;<br />      &lt;one-to-many <br />          class="com.jason.associations.one2many.unilateralism.one2many.Address"/&gt;<br />  &lt;/set&gt;<br />  &lt;property name="name" column="personName" type="string" /&gt;<br /> &lt;/class&gt;<br /> <br /> &lt;class name="com.jason.associations.one2many.unilateralism.one2many.Address" table="Address"&gt;<br />     &lt;id name="id" column="addressId"&gt;<br />         &lt;generator class="native"/&gt;<br />      &lt;/id&gt;<br />     &lt;property name="country" column="country" type="string" /&gt;<br />     &lt;property name="city" column="city" type="string" /&gt;<br /> &lt;/class&gt;<br /> &lt;!--<br />     create table Person ( personId bigint not null primary key, personName varchar(20))<br />     create table Address ( addressId bigint not null primary key, personId bigint not null, country varchar(20), city varchar(20) )<br /> --&gt;<br /> <br /> <br /> 2.“单向多对一关系”<br />  &lt;class name="com.jason.associations.one2many.unilateralism.many2one.Person" table="Person"&gt;<br />  &lt;id name="id" column="personId"&gt;<br />      &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;many-to-one name="address" <br />       class="com.jason.associations.one2many.unilateralism.many2one.Address"<br />       column="addressId" <br />       cascade="all"<br />       outer-join="auto"<br />       update="true"<br />       insert="true"<br />       access="property"<br />       not-null="true"/&gt;<br />  &lt;property name="name" column="personName" type="string" /&gt;<br /> &lt;/class&gt;<br /> <br /> &lt;class name="com.jason.associations.one2many.unilateralism.many2one.Address" table="Address"&gt;<br />  &lt;id name="id" column="addressId"&gt;<br />      &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;property name="country" column="country" type="string" /&gt;<br />  &lt;property name="city" column="city" type="string" /&gt;<br /> &lt;/class&gt;<br /> &lt;!--<br />     create table Person ( personId bigint not null primary key, addressId bigint not null, personName varchar(20))<br />     create table Address ( addressId bigint not null primary key, country varchar(20), city varchar(20) )<br /> --&gt;<br /><br />3、“单向一对多连接表关系”<br />&lt;hibernate-mapping&gt;<br /> &lt;class name="com.jason.associations.one2many.unilateralism.one2many.table.Person" table="Person"&gt;<br />  &lt;id name="id" column="personId"&gt;<br />      &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;set name="addresses" table="PersonAddress" cascade="all"&gt;<br />      &lt;key column="personId"/&gt;<br />      &lt;many-to-many column="addressId"<br />          unique="true"<br />          class="com.jason.associations.one2many.unilateralism.one2many.table.Address"/&gt;<br />  &lt;/set&gt;<br />  &lt;property name="name" column="personName" type="string" /&gt;<br /> &lt;/class&gt;<br /> <br /> &lt;class name="com.jason.associations.one2many.unilateralism.one2many.table.Address" table="Address"&gt;<br />  &lt;id name="id" column="addressId"&gt;<br />      &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;property name="country" column="country" type="string" /&gt;<br />  &lt;property name="city" column="city" type="string" /&gt;<br /> &lt;/class&gt;<br /> &lt;!--<br />     create table Person ( personId bigint not null primary key, personName varchar(20))<br />     create table PersonAddress ( personId bigint not null, addressId bigint not null primary key)<br />     create table Address ( addressId bigint not null primary key, country varchar(20), city varchar(20))<br /> --&gt;<br /><br /> 4、“单向多对一连接表关系”<br /> 我们认为对于这种关联关系最好使用连接表。<br />  &lt;class name="com.jason.associations.one2many.unilateralism.many2one.table.Person" table="Person"&gt;<br />  &lt;id name="id" column="personId"&gt;<br />      &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;property name="name" column="personName" type="string" /&gt;<br />  &lt;!--join 必须放在最下面--&gt;<br />  &lt;join table="PersonAddress" optional="true"&gt;<br />           &lt;key column="personId" unique="true"/&gt;<br />           &lt;many-to-one name="address" <br />                  class="com.jason.associations.one2many.unilateralism.many2one.table.Address"<br />                  column="addressId" <br />                  not-null="true" <br />                  cascade="all"/&gt;<br />    &lt;/join&gt; <br /> &lt;/class&gt;<br /> <br /> &lt;class name="com.jason.associations.one2many.unilateralism.many2one.table.Address" table="Address"&gt;<br />  &lt;id name="id" column="addressId"&gt;<br />         &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;property name="country" column="country" type="string" /&gt;<br />  &lt;property name="city" column="city" type="string" /&gt;<br /> &lt;/class&gt;<br /> &lt;!--<br />     create table Person ( personId bigint not null primary key, personName varchar(20))<br />     create table PersonAddress ( personId bigint not null primary key, addressId bigint not null)<br />     create table Address ( addressId bigint not null primary key, country varchar(20), city varchar(20))<br /> --&gt;<br /> <br /> <br /> 二、双向关系<br /> 双向一对多关系就是二者的组合<br /> 为了更好地提高执行效率，需要将“多”的一端设为主控方，就是将关联关系的维护工作交给“多”的一端。<img src ="http://www.blogjava.net/gm_jing/aggbug/64407.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-18 17:21 <a href="http://www.blogjava.net/gm_jing/articles/64407.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>one2one关联</title><link>http://www.blogjava.net/gm_jing/articles/64163.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Thu, 17 Aug 2006 09:16:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/64163.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/64163.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/64163.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/64163.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/64163.html</trackback:ping><description><![CDATA[
		<p>one2one</p>
		<p>1、基于外键关联的单向一对一关联<br />   和单向多对一关联几乎是一样的。唯一的不同就是单向一对一关联中的外键字段具有唯一性约束。 </p>
		<p> &lt;class name="com.jason.associations.one2one.unilateralism.foreign.Person" table="Person"&gt;<br />  &lt;id name="id" column="personId"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />  &lt;many-to-one name="address" <br />   class="com.jason.associations.one2one.unilateralism.foreign.Address"<br />   column="addressId" <br />      <font color="#ff1493">unique="true</font>"<br />      cascade="all"<br />      not-null="true"/&gt;<br /> &lt;/class&gt;<br /> <br /> &lt;class name="com.jason.associations.one2one.unilateralism.foreign.Address" table="Address"&gt;<br />  &lt;id name="id" column="addressId"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br /> &lt;/class&gt;<br /> &lt;!--<br />  create table Person ( personId bigint not null primary key, addressId bigint not null unique)<br />  create table Address ( addressId bigint not null primary key)<br /> --&gt;</p>
		<p>
				<br />2、基于主键关联的单向一对一关联<br />   通常使用一个特定的id生成器。（请注意，在这个例子中我们掉换了关联的方向。） </p>
		<p> &lt;class name="com.jason.associations.one2one.unilateralism.primary.Person" table="Person"&gt;<br />  &lt;id name="id" column="personId"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br /> &lt;/class&gt;<br /> <br /> &lt;class name="com.jason.associations.one2one.unilateralism.primary.Address" table="Address"&gt;<br />  &lt;id name="id" column="addressId"&gt;<br />      &lt;generator class="foreign"&gt;<br />    &lt;param name="property"&gt;person&lt;/param&gt;<br />   &lt;/generator&gt;<br />  &lt;/id&gt;<br />  &lt;one-to-one name="person" <br />   class="com.jason.associations.one2one.unilateralism.primary.Person"<br />   constrained="true"/&gt;<br /> &lt;/class&gt;<br /> &lt;!--<br />  create table Person ( personId bigint not null primary key)<br />  create table Address ( addressId bigint not null primary key)  <br />  其中personId= addressId<br /> --&gt;</p>
		<p>
				<br />3、基于连接表的单向一对一关联非常少见，但也是可行的。 </p>
		<p> &lt;class name="com.jason.associations.one2one.unilateralism.table.Person" table="Person"&gt;<br />  &lt;id name="id" column="personId"&gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br />      &lt;!--join 必须放在最下面--&gt;<br />       &lt;join table="PersonAddress" optional="true"&gt;<br />           &lt;key column="personId" unique="true"/&gt;<br />           &lt;many-to-one name="address"<br />               column="addressId" <br />               not-null="true" <br />            cascade="all"<br />               unique="true"/&gt;<br />        &lt;/join&gt; <br /> &lt;/class&gt;<br /> <br /> &lt;class name="com.jason.associations.one2one.unilateralism.table.Address" table="Address"&gt;<br />  &lt;id name="id" column="addressId"&gt;<br />         &lt;generator class="native"/&gt;<br />  &lt;/id&gt;<br /> &lt;/class&gt;<br /> &lt;!--<br />  create table Person ( personId bigint not null primary key)<br />  create table PersonAddress ( personId bigint not null primary key, addressId bigint not null unique )<br />  create table Address ( addressId bigint not null primary key)<br /> --&gt;</p>
		<p>
				<br />4、对应的双向关联<br />a、单向关联和双向关联使用的表是一样的<br />b、双向关联类中多了属性<br />c、双向关联可以从任何一个对象开始操作（比如添加），而单向只能从特定的一方操作</p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/64163.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-17 17:16 <a href="http://www.blogjava.net/gm_jing/articles/64163.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>组件映射</title><link>http://www.blogjava.net/gm_jing/articles/62246.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Mon, 07 Aug 2006 15:16:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/62246.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/62246.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/62246.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/62246.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/62246.html</trackback:ping><description><![CDATA[
		<div>组件(Component)是一个被包含的对象，在持久化的过程中，它被当作值类型，而并非一个实体的引用。在这篇文档中，组件这一术语指的是面向对象的合成概念.<br />·user.java<br /></div>
		<div>
				<div style="FONT-WEIGHT: bold; FONT-SIZE: 15px; MARGIN: 0px 5px; WIDTH: 70.94%; COLOR: black; FONT-STYLE: italic; FONT-FAMILY: Courier New; HEIGHT: 18px; BACKGROUND-COLOR: #cccccc">
						<p>
								<i>User.java</i>
						</p>
				</div>
				<div>
						<div style="PADDING-RIGHT: 5px; BORDER-TOP: #000000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 14px; PADDING-BOTTOM: 5px; MARGIN: 0px 5px; OVERFLOW: scroll; WIDTH: 71.08%; COLOR: #000000; PADDING-TOP: 5px; BORDER-BOTTOM: #000000 1px solid; FONT-FAMILY: Courier New; HEIGHT: 451px; BACKGROUND-COLOR: #e2e2e2">
								<p>package com.jason.component;</p>
								<p>
										<br />public class User{<br /> private Integer id;<br /> private String name;<br /> private String password;<br /> private Contact contact;</p>
								<p>
										<br /> /**<br />  * @return Returns the id.<br />  */<br /> public Integer getId() {<br />  return id;<br /> }<br /> /**<br />  * @param id The id to set.<br />  */<br /> public void setId(Integer id) {<br />  this.id = id;<br /> }<br /> /**<br />  * @return Returns the name.<br />  */<br /> public String getName() {<br />  return name;<br /> }<br /> /**<br />  * @param name The name to set.<br />  */<br /> public void setName(String name) {<br />  this.name = name;<br /> }<br /> /**<br />  * @return Returns the password.<br />  */<br /> public String getPassword() {<br />  return password;<br /> }<br /> /**<br />  * @param password The password to set.<br />  */<br /> public void setPassword(String password) {<br />  this.password = password;<br /> }<br /> /**<br />  * @return Returns the contact.<br />  */<br /> public Contact getContact() {<br />  return contact;<br /> }<br /> /**<br />  * @param contact The contact to set.<br />  */<br /> public void setContact(Contact contact) {<br />  this.contact = contact;<br /> }<br />}</p>
						</div>
				</div>
				<div>
						<br />
						<br />· contact.java</div>
				<div>
						<div style="FONT-WEIGHT: bold; FONT-SIZE: 15px; MARGIN: 0px 5px; WIDTH: 70.94%; COLOR: black; FONT-STYLE: italic; FONT-FAMILY: Courier New; HEIGHT: 18px; BACKGROUND-COLOR: #cccccc">
								<p>
										<i>Contact.java</i>
								</p>
						</div>
						<div>
								<div style="PADDING-RIGHT: 5px; BORDER-TOP: #000000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 14px; PADDING-BOTTOM: 5px; MARGIN: 0px 5px; OVERFLOW: scroll; WIDTH: 71.08%; COLOR: #000000; PADDING-TOP: 5px; BORDER-BOTTOM: #000000 1px solid; FONT-FAMILY: Courier New; HEIGHT: 451px; BACKGROUND-COLOR: #e2e2e2">
										<p>package com.jason.component;</p>
										<p>public class Contact {<br /> private String email;<br /> private String address;</p>
										<p> /**<br />  * @return Returns the address.<br />  */<br /> public String getAddress() {<br />  return address;<br /> }<br /> /**<br />  * @param address The address to set.<br />  */<br /> public void setAddress(String address) {<br />  this.address = address;<br /> }<br /> /**<br />  * @return Returns the email.<br />  */<br /> public String getEmail() {<br />  return email;<br /> }<br /> /**<br />  * @param email The email to set.<br />  */<br /> public void setEmail(String email) {<br />  this.email = email;<br /> }<br />}</p>
								</div>
						</div>
						<div> </div>
				</div>
				<div>· User.hbm.xml</div>
				<div>
						<div>
								<div>
										<div>
												<div style="FONT-WEIGHT: bold; FONT-SIZE: 15px; MARGIN: 0px 5px; WIDTH: 70.94%; COLOR: black; FONT-STYLE: italic; FONT-FAMILY: Courier New; HEIGHT: 18px; BACKGROUND-COLOR: #cccccc">
														<p>
																<i>User.hbm.xml</i>
														</p>
												</div>
												<div>
														<div style="PADDING-RIGHT: 5px; BORDER-TOP: #000000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 14px; PADDING-BOTTOM: 5px; MARGIN: 0px 5px; OVERFLOW: scroll; WIDTH: 71.08%; COLOR: #000000; PADDING-TOP: 5px; BORDER-BOTTOM: #000000 1px solid; FONT-FAMILY: Courier New; HEIGHT: 451px; BACKGROUND-COLOR: #e2e2e2">
																<pre>&lt;?xml version="1.0"?&gt;<br />&lt;!DOCTYPE hibernate-mapping PUBLIC<br /> "-//Hibernate/Hibernate Mapping DTD//EN"<br /> "<a href="http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd</a>" &gt;</pre>
																<pre>&lt;hibernate-mapping package="com.jason.component"&gt;<br /> &lt;class<br />  name="User"<br />  table="user"<br /> &gt;<br />  &lt;meta attribute="sync-DAO"&gt;false&lt;/meta&gt;</pre>
																<pre>  &lt;id<br />   name="Id"<br />   type="integer"<br />   column="id"<br />  &gt;<br />   &lt;generator class="native"/&gt;<br />  &lt;/id&gt;</pre>
																<pre>  &lt;property<br />   name="Name"<br />   column="name"<br />   type="string"<br />   not-null="true"<br />   length="20"<br />  /&gt;<br />  &lt;property<br />   name="Password"<br />   column="password"<br />   type="string"<br />   not-null="true"<br />   length="20"<br />  /&gt;</pre>
																<pre>  &lt;component class="Contact" name="Contact"&gt;<br />   &lt;property<br />    column="email"<br />    length="50"<br />    name="Email"<br />    not-null="false"<br />    type="string"<br />    /&gt;<br />   &lt;property<br />    column="address"<br />    length="100"<br />    name="Address"<br />    not-null="false"<br />    type="string"<br />    /&gt;<br />  &lt;/component&gt;</pre>
																<pre> &lt;/class&gt; <br />&lt;/hibernate-mapping&gt;</pre>
														</div>
														<br />
												</div>
												<div>
														<br />
														<div style="FONT-WEIGHT: bold; FONT-SIZE: 15px; MARGIN: 0px 5px; WIDTH: 70.94%; COLOR: black; FONT-STYLE: italic; FONT-FAMILY: Courier New; HEIGHT: 18px; BACKGROUND-COLOR: #cccccc">
																<p>
																		<i>testComponent.java</i>
																</p>
														</div>
														<div>
																<div style="PADDING-RIGHT: 5px; BORDER-TOP: #000000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 14px; PADDING-BOTTOM: 5px; MARGIN: 0px 5px; OVERFLOW: scroll; WIDTH: 71.08%; COLOR: #000000; PADDING-TOP: 5px; BORDER-BOTTOM: #000000 1px solid; FONT-FAMILY: Courier New; HEIGHT: 451px; BACKGROUND-COLOR: #e2e2e2">
																		<p>package com.jason.component;</p>
																		<p>import java.util.List;<br />import java.util.ListIterator;</p>
																		<p>import org.hibernate.HibernateException;<br />import org.hibernate.Query;<br />import org.hibernate.Session;<br />import org.hibernate.SessionFactory;<br />import org.hibernate.Transaction;<br />import org.hibernate.cfg.Configuration;</p>
																		<p>
																				<br />public class testComponent {<br />    public static void main(String[] args) throws HibernateException {<br />        SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory();<br />        <br />        testInsert(sessionFactory);<br />        testQuery(sessionFactory);<br />                 <br />        sessionFactory.close();<br />        <br />    }<br />    public static void testInsert( SessionFactory sessionFactory )throws HibernateException {<br />     <br />      Session session = sessionFactory.openSession();<br />        Transaction tx= session.beginTransaction();<br />        User user = new User();<br />        Contact contact=new Contact();<br />        contact.setEmail("<a href="mailto:gm_jing@yahoo.com.cn">gm_jing@yahoo.com.cn</a>");<br />        contact.setAddress("beijing");<br />        <br />        user.setName("gm_jing");<br />        user.setPassword("1111111");<br />        user.setContact(contact);<br />        <br />        session.save(user);<br />        tx.commit();<br />        session.close();<br />        System.out.println("OK！");<br />   }<br />    <br />    public static void testQuery( SessionFactory sessionFactory )throws HibernateException {<br />     <br />     Session session = sessionFactory.openSession();<br />        Transaction tx= session.beginTransaction();<br />        User user = new User();<br />                  <br />        Query query=session.createQuery("from User as user");<br />        //query.setCharacter(1, 'M');<br />        List names =query.list();<br />        for(ListIterator it=names.listIterator();it.hasNext();){<br />           user= (User)it.next();<br />           System.out.println("Id: " + user.getId());<br />            System.out.println("name: " + user.getName());<br />            System.out.println("password: " + user.getPassword());<br />            if(user.getContact()!=null){<br />             <br />             if(user.getContact().getEmail()!=null){<br />              System.out.println("Email: " + user.getContact().getEmail());<br />             }<br />             if(user.getContact().getAddress()!=null){<br />              System.out.println("Address: " + user.getContact().getAddress());<br />                <br />             }<br />            }<br />    <br />        }<br />      <br />        tx.commit();<br />        session.close();<br />     <br />    }<br />}</p>
																		<p> </p>
																</div>
																<br />
														</div>
														<div>
																<br />
																<p>就像所有的值类型一样, 组件不支持共享引用。 换句话说，两个Contact可能相同，但是两个User对象应该包含两个独立的Contact对象，只不过这两个Contact对象具有“同样”的值。 组件的值可以为空，其定义如下。 每当Hibernate重新加载一个包含组件的对象,如果该组件的所有字段为空，Hibernate将假定整个组件为空。 在大多数情况下,这样假定应该是没有问题的。 </p>
														</div>
												</div>
										</div>
								</div>
						</div>
				</div>
		</div>
<img src ="http://www.blogjava.net/gm_jing/aggbug/62246.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-07 23:16 <a href="http://www.blogjava.net/gm_jing/articles/62246.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>继承映射-----&gt;&gt;&gt;三种总结</title><link>http://www.blogjava.net/gm_jing/articles/62237.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Mon, 07 Aug 2006 14:00:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/62237.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/62237.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/62237.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/62237.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/62237.html</trackback:ping><description><![CDATA[
		<table class="MsoTableGrid" style="BORDER-RIGHT: medium none; BORDER-TOP: medium none; BORDER-LEFT: medium none; WIDTH: 455.4pt; BORDER-BOTTOM: medium none; BORDER-COLLAPSE: collapse; mso-border-alt: solid windowtext .5pt; mso-yfti-tbllook: 480; mso-padding-alt: 0cm 5.4pt 0cm 5.4pt; mso-border-insideh: .5pt solid windowtext; mso-border-insidev: .5pt solid windowtext" cellspacing="0" cellpadding="0" width="607" border="1">
				<tbody>
						<tr style="mso-yfti-irow: 0; mso-yfti-firstrow: yes">
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 106.5pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt" valign="top" width="142">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span lang="EN-US">
														<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /?>
														<o:p> </o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 123.9pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" valign="top" width="165">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">每个类分层结构一张表</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 144pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" valign="top" width="192">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">每个子类一个表</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 1pt solid; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 81pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt" valign="top" width="108">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">每个具体类一个表</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 1">
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 106.5pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="142">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表的个数</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span lang="EN-US">
														<o:p> </o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 123.9pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width="165">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span lang="EN-US">1</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 144pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width="192">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span lang="EN-US">n</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 81pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width="108">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span lang="EN-US">n-1</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 2">
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 106.5pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="142">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">父表</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span lang="EN-US">
														<o:p> </o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 123.9pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width="165" rowspan="2">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: center" align="center">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">一个表</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 144pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width="192" x:num="">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span lang="EN-US">1</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 81pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width="108" x:num="">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span lang="EN-US">0</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 3">
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 106.5pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="142">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">子表</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span lang="EN-US">
														<o:p> </o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 144pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width="192">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span lang="EN-US">n-1<o:p></o:p></span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 81pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width="108">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span lang="EN-US">n-1<o:p></o:p></span>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 4">
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 106.5pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="142">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表的字段</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span lang="EN-US">
														<o:p> </o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 123.9pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width="165">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">每个类的所有属性＋类型鉴别</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 144pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width="192">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">父表</span>
												<span lang="EN-US">--&gt;</span>
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">父类属性</span>
												<span lang="EN-US">
														<br />
												</span>
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">子表</span>
												<span lang="EN-US">--&gt;</span>
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">子类属性＋父类</span>
												<span lang="EN-US">id</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 81pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width="108">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">子表</span>
												<span lang="EN-US">--&gt;</span>
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">子类属性＋父类属性</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
						</tr>
						<tr style="mso-yfti-irow: 5; mso-yfti-lastrow: yes">
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: windowtext 1pt solid; WIDTH: 106.5pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" valign="top" width="142">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表的关联</span>
												<span lang="EN-US">/</span>
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">表的唯一</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span lang="EN-US">
														<o:p> </o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 123.9pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width="165">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">类型鉴别标识</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 144pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width="192">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Times New Roman'; mso-hansi-font-family: 'Times New Roman'">父类</span>
												<span lang="EN-US">id</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
								<td style="BORDER-RIGHT: windowtext 1pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: #d4d0c8; PADDING-LEFT: 5.4pt; PADDING-BOTTOM: 0cm; BORDER-LEFT: #d4d0c8; WIDTH: 81pt; PADDING-TOP: 0cm; BORDER-BOTTOM: windowtext 1pt solid; BACKGROUND-COLOR: transparent; mso-border-alt: solid windowtext .5pt; mso-border-left-alt: solid windowtext .5pt; mso-border-top-alt: solid windowtext .5pt" width="108">
										<p class="MsoNormal" style="MARGIN: 0cm 0cm 0pt">
												<span lang="EN-US">id</span>
												<span lang="EN-US" style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-bidi-font-family: 宋体">
														<o:p>
														</o:p>
												</span>
										</p>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
<img src ="http://www.blogjava.net/gm_jing/aggbug/62237.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-07 22:00 <a href="http://www.blogjava.net/gm_jing/articles/62237.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>继承映射3 --每个具体类一个表</title><link>http://www.blogjava.net/gm_jing/articles/62196.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Mon, 07 Aug 2006 08:17:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/62196.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/62196.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/62196.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/62196.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/62196.html</trackback:ping><description><![CDATA[
		<p>
				<br />   每个具体类一个表的方式是只有具体类对应一张表，包括父类和子类，<font color="#0000ff">父类和子类的关系是通过<br />在子类中保存父类的id来实现的。<font color="#000000">所以保存一条子类的信息需要同时向父类和子类的表中插入记录。</font><br /></font><br />一个例子如下：<br />·  类Person.java</p>
		<div>
				<div style="PADDING-RIGHT: 5px; BORDER-TOP: #000000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 14px; PADDING-BOTTOM: 5px; MARGIN: 0px 5px; OVERFLOW: scroll; WIDTH: 71.08%; COLOR: #000000; PADDING-TOP: 5px; BORDER-BOTTOM: #000000 1px solid; FONT-FAMILY: Courier New; HEIGHT: 231px; BACKGROUND-COLOR: #e2e2e2">
						<p>package com.jason.inheritance.three;</p>
						<p>public abstract class Person {<br /> private Long id;</p>
						<p> private String name;</p>
						<p> /**<br />  * @hibernate.id <br />  *   column="ID" <br />  *   generator-class="hilo" <br />  *   unsaved-value="null"<br />  */<br /> public Long getId() {<br />  return id;<br /> }</p>
						<p> public void setId(Long id) {<br />  this.id = id;<br /> }</p>
						<p> /**<br />  * @hibernate.property <br />  *   length = "24"<br />  */<br /> public String getName() {<br />  return name;<br /> }</p>
						<p> public void setName(String name) {<br />  this.name = name;<br /> }<br />}</p>
						<p> </p>
				</div>
				<br />
		</div>
		<div>·  子类Professor.java<br /><div style="PADDING-RIGHT: 5px; BORDER-TOP: #000000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 14px; PADDING-BOTTOM: 5px; MARGIN: 0px 5px; OVERFLOW: scroll; WIDTH: 71.08%; COLOR: #000000; PADDING-TOP: 5px; BORDER-BOTTOM: #000000 1px solid; FONT-FAMILY: Courier New; HEIGHT: 231px; BACKGROUND-COLOR: #e2e2e2"><pre><pre><span style="FONT-WEIGHT: bold; COLOR: #7f0055">package com.jason.inheritance.three;</span></pre><pre><span style="FONT-WEIGHT: bold; COLOR: #7f0055">public class Professor extends Person {<br /> private int salary;</span></pre><pre><span style="FONT-WEIGHT: bold; COLOR: #7f0055"> /**<br />  * @hibernate.property<br />  */<br /> public int getSalary() {<br />  return salary;<br /> }</span></pre><pre><span style="FONT-WEIGHT: bold; COLOR: #7f0055"> public void setSalary(int salary) {<br />  this.salary = salary;<br /> }<br />}<br /></span></pre></pre></div><br /></div>
		<div>·  子类Student.java<br /><div style="PADDING-RIGHT: 5px; BORDER-TOP: #000000 1px solid; PADDING-LEFT: 2px; FONT-SIZE: 14px; PADDING-BOTTOM: 5px; MARGIN: 0px 5px; OVERFLOW: scroll; WIDTH: 71.08%; COLOR: #000000; PADDING-TOP: 5px; BORDER-BOTTOM: #000000 1px solid; FONT-FAMILY: Courier New; HEIGHT: 231px; BACKGROUND-COLOR: #e2e2e2"><p>package com.jason.inheritance.three;</p><p>public class Student extends Person {<br /> private String studentNumber;</p><p> /**<br />  * @hibernate.property <br />  *   length = "24"<br />  */<br /> public String getStudentNumber() {<br />  return studentNumber;<br /> }</p><p> public void setStudentNumber(String studentNumber) {<br />  this.studentNumber = studentNumber;<br /> }<br />}</p><p> </p></div><br /><br /></div>
		<div>·  Professor.hbm.xml</div>
		<div>
				<table bordercolor="#000000" cellspacing="0" cellpadding="4" width="70%" border="0">
						<tbody>
								<tr>
										<td style="FONT-WEIGHT: bold; FONT-SIZE: 14px; BORDER-BOTTOM: rgb(51,51,204) thin inset; FONT-STYLE: italic; FONT-FAMILY: Courier New" valign="top" width="100%" bgcolor="#cccccc" height="16">
										</td>
								</tr>
								<tr>
										<td style="FONT-SIZE: 12px; BORDER-TOP-STYLE: none; BORDER-TOP-COLOR: rgb(236,233,216); FONT-FAMILY: Courier New" valign="top" width="100%" bgcolor="#e2e2e2">
												<div>
														<font face="Courier New">
																<pre>&lt;?xml version="1.0"?&gt;<br />&lt;!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br /> "<a href="http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd</a>"&gt;</pre>
																<pre>&lt;hibernate-mapping&gt;<br /> &lt;class name="com.jason.inheritance.three.Professor" table="Professor"<br />  dynamic-update="false" dynamic-insert="false" select-before-update="false"<br />  optimistic-lock="version"&gt;<br />  <br />  &lt;id name="id" column="ID" type="java.lang.Long" unsaved-value="null"&gt;<br />   &lt;generator class="hilo"&gt;<br />   &lt;/generator&gt;<br />  &lt;/id&gt;<br />  <br />  &lt;property name="salary" type="int" update="true" insert="true"<br />   access="property" column="salary"/&gt;<br />  <br />  &lt;property name="name" type="java.lang.String" update="true" insert="true"<br />   access="property" column="name" length="24"/&gt;<br />  <br /> &lt;/class&gt;<br /> <br />&lt;/hibernate-mapping&gt;</pre>
																<pre>
																</pre>
														</font>
												</div>
										</td>
								</tr>
						</tbody>
				</table>
				<br />
				<div>
						<br />·  Student.hbm.xml</div>
				<div>
						<table bordercolor="#000000" cellspacing="0" cellpadding="4" width="70%" border="0">
								<tbody>
										<tr>
												<td style="FONT-WEIGHT: bold; FONT-SIZE: 14px; BORDER-BOTTOM: rgb(51,51,204) thin inset; FONT-STYLE: italic; FONT-FAMILY: Courier New" valign="top" width="100%" bgcolor="#cccccc" height="16">
												</td>
										</tr>
										<tr>
												<td style="FONT-SIZE: 12px; BORDER-TOP-STYLE: none; BORDER-TOP-COLOR: rgb(236,233,216); FONT-FAMILY: Courier New" valign="top" width="100%" bgcolor="#e2e2e2">
														<div>
																<font face="Courier New">
																		<pre>&lt;?xml version="1.0"?&gt;<br />&lt;!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br /> "<a href="http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd</a>"&gt;</pre>
																		<pre>&lt;hibernate-mapping&gt;<br /> &lt;class name="com.jason.inheritance.three.Student" table="Student"<br />  dynamic-update="false" dynamic-insert="false" select-before-update="false"<br />  optimistic-lock="version"&gt;<br />  <br />  &lt;id name="id" column="ID" type="java.lang.Long" unsaved-value="null"&gt;<br />   &lt;generator class="hilo"&gt;<br />   &lt;/generator&gt;<br />  &lt;/id&gt;<br />  <br />  &lt;property name="studentNumber" type="java.lang.String" update="true"<br />   insert="true" access="property" column="studentNumber" length="24"/&gt;<br />  <br />  &lt;property name="name" type="java.lang.String" update="true" insert="true"<br />   access="property" column="name" length="24"/&gt;<br />  <br /> &lt;/class&gt;<br /> <br />&lt;/hibernate-mapping&gt;</pre>
																		<pre>
																		</pre>
																</font>
														</div>
												</td>
										</tr>
								</tbody>
						</table>
						<br />
				</div>
		</div>
		<p>
				<br />      显然对应的表是<br />      professor(id, name, salary)<br />      student(id, name, studentNumber)<br /><font color="#000000">      插入记录的sql如下：<br />      Hibernate: insert into Student (studentNumber, name, ID) values (?, ?, ?)<br /><br /></font></p>
		<div>
				<div>● 优点：<br />· 报表操作实现简单：表中包含了具体子类的所有信息。 </div>
				<div>
						<br />● 缺点：<br />· 类的修改会导致相对应的表及其子类所对应表的更改。<br />· 当含有多重子类时，会造成在数据库表格中生成重复的字段。<br /><br /><br /><br /><br /><br /><br /><br />参考：<br /></div>
		</div>
		<div>· HIBERNATE - 符合Java习惯的关系数据库持久化（第8章）</div>
		<div>· <a href="http://www-900.ibm.com/developerWorks/cn/java/j-hibernate/index.shtml">Hibernate 简化继承映射</a></div>
		<div>· <a href="http://www.agiledata.org/essays/mappingObjects.html#">Mapping Objects to Relational Databases: O/R Mapping In Detail</a></div>
		<div align="left">· <a href="http://www-106.ibm.com/developerworks/webservices/library/ws-mapping-to-rdb/">Mapping objects to relational databases</a></div>
<img src ="http://www.blogjava.net/gm_jing/aggbug/62196.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-07 16:17 <a href="http://www.blogjava.net/gm_jing/articles/62196.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>继承映射2 --每个子类一个表</title><link>http://www.blogjava.net/gm_jing/articles/61605.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Thu, 03 Aug 2006 14:11:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/61605.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/61605.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/61605.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/61605.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/61605.html</trackback:ping><description><![CDATA[<p><br />
&nbsp;&nbsp; 每个子类一个表的方式是将所有的类生成一个表（包括父类），保存子类的时候，<font color="#0000ff">同时向父类和子类添加数据，然后把父类中生成的id，保存到子类中，保持关联</font>。在这个主题中我们将先说明这个方法。<br />
<br />
<br />
一个例子如下：<br />
&#183;&nbsp; 类Vehicle.java</p>
<div>
<div style="padding-right: 5px; border-top: #000000 1px solid; padding-left: 2px; font-size: 14px; padding-bottom: 5px; margin: 0px 5px; overflow: scroll; width: 71.08%; color: #000000; padding-top: 5px; border-bottom: #000000 1px solid; font-family: Courier New; height: 231px; background-color: #e2e2e2">
<p>package com.jason.inheritance.two;</p>
<p>public class Vehicle {<br />
&nbsp;private Long id;</p>
<p>&nbsp;private String name;</p>
<p>&nbsp;/**<br />
&nbsp; * @hibernate.id <br />
&nbsp; *&nbsp;&nbsp; column="ID" <br />
&nbsp; *&nbsp;&nbsp; generator-class="hilo" <br />
&nbsp; *&nbsp;&nbsp; unsaved-value="null"<br />
&nbsp; */<br />
&nbsp;public Long getId() {<br />
&nbsp;&nbsp;return id;<br />
&nbsp;}</p>
<p>&nbsp;public void setId(Long id) {<br />
&nbsp;&nbsp;this.id = id;<br />
&nbsp;}</p>
<p>&nbsp;/**<br />
&nbsp; * @hibernate.property <br />
&nbsp; *&nbsp;&nbsp; length = "24"<br />
&nbsp; */<br />
&nbsp;public String getName() {<br />
&nbsp;&nbsp;return name;<br />
&nbsp;}</p>
<p>&nbsp;public void setName(String name) {<br />
&nbsp;&nbsp;this.name = name;<br />
&nbsp;}</p>
<p>}<br />
</p>
</div>
<br />
</div>
<div>&#183;&nbsp; 子类Car.java<br />
<div style="padding-right: 5px; border-top: #000000 1px solid; padding-left: 2px; font-size: 14px; padding-bottom: 5px; margin: 0px 5px; overflow: scroll; width: 71.08%; color: #000000; padding-top: 5px; border-bottom: #000000 1px solid; font-family: Courier New; height: 231px; background-color: #e2e2e2">
<p>package com.jason.inheritance.two;</p>
<p>public class Car extends Vehicle {<br />
&nbsp;private String seat;<br />
&nbsp;public String getSeat() {<br />
&nbsp;&nbsp;return seat;<br />
&nbsp;}</p>
<p>&nbsp;public void setSeat(String seat) {<br />
&nbsp;&nbsp;this.seat = seat;<br />
&nbsp;}<br />
}</p>
</div>
<br />
</div>
<div>&#183;&nbsp; 子类Truck.java<br />
<div style="padding-right: 5px; border-top: #000000 1px solid; padding-left: 2px; font-size: 14px; padding-bottom: 5px; margin: 0px 5px; overflow: scroll; width: 71.08%; color: #000000; padding-top: 5px; border-bottom: #000000 1px solid; font-family: Courier New; height: 231px; background-color: #e2e2e2">
<p>package com.jason.inheritance.two;</p>
<p>public class Truck extends Vehicle {<br />
&nbsp;private String load;<br />
&nbsp;public String getLoad() {<br />
&nbsp;&nbsp;return load;<br />
&nbsp;}</p>
<p>&nbsp;public void setLoad(String load) {<br />
&nbsp;&nbsp;this.load = load;<br />
&nbsp;}<br />
}</p>
</div>
<br />
<br />
</div>
<div>&#183;&nbsp; Vehicle.hbm.xml</div>
<div>
<table bordercolor="#000000" cellspacing="0" cellpadding="4" width="70%" border="0">
    <tbody>
        <tr>
            <td style="font-weight: bold; font-size: 14px; border-bottom: rgb(51,51,204) thin inset; font-style: italic; font-family: Courier New" valign="top" width="100%" bgcolor="#cccccc" height="16"><font style="background-color: #ffffff"></font></td>
        </tr>
        <tr>
            <td style="font-size: 12px; border-top-style: none; border-top-color: rgb(236,233,216); font-family: Courier New" valign="top" width="100%" bgcolor="#e2e2e2">
            <div><font face="Courier New">
            <pre>&lt;?xml version="1.0"?&gt;<br />
            &lt;!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br />
            &nbsp;"<a href="http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd</a>"&gt;</pre>
            <pre>&lt;hibernate-mapping&gt;<br />
            &nbsp;&lt;class name="com.jason.inheritance.two.Vehicle" dynamic-update="false"<br />
            &nbsp;&nbsp;dynamic-insert="false" select-before-update="false"<br />
            &nbsp;&nbsp;optimistic-lock="version"&gt;<br />
            &nbsp;&nbsp;<br />
            &nbsp;&nbsp;&lt;id name="id" column="ID" type="java.lang.Long" unsaved-value="null"&gt;<br />
            &nbsp;&nbsp;&nbsp;&lt;generator class="hilo"&gt;<br />
            &nbsp;&nbsp;&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&lt;/generator&gt;<br />
            &nbsp;&nbsp;&lt;/id&gt;<br />
            &nbsp;&nbsp;<br />
            &nbsp;&nbsp;&lt;property name="name" type="java.lang.String" update="true" insert="true"<br />
            &nbsp;&nbsp;&nbsp;access="property" column="name" length="24"/&gt;<br />
            &nbsp;&nbsp;<br />
            &nbsp;&nbsp;<font color="#ff1493">&lt;joined-subclass</font> name="com.jason.inheritance.two.Truck"<br />
            &nbsp;&nbsp;&nbsp;dynamic-update="false" dynamic-insert="false"&gt;<br />
            &nbsp;&nbsp;&nbsp;&lt;key column="id"/&gt;<br />
            &nbsp;&nbsp;&nbsp;&lt;property name="load" type="java.lang.String" update="true"<br />
            &nbsp;&nbsp;&nbsp;&nbsp;insert="true" access="property" column="loads" length="24"/&gt;<br />
            &nbsp;&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&lt;/joined-subclass&gt;<br />
            &nbsp;&nbsp;<font color="#ff1493">&lt;joined-subclass</font> name="com.jason.inheritance.two.Car"<br />
            &nbsp;&nbsp;&nbsp;dynamic-update="false" dynamic-insert="false"&gt;<br />
            &nbsp;&nbsp;&nbsp;&lt;key column="id"/&gt;<br />
            &nbsp;&nbsp;&nbsp;&lt;property name="seat" type="java.lang.String" update="true"<br />
            &nbsp;&nbsp;&nbsp;&nbsp;insert="true" access="property" column="seat" length="24"/&gt;<br />
            &nbsp;&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&lt;/joined-subclass&gt;<br />
            &nbsp;&nbsp;<br />
            &nbsp;&lt;/class&gt;<br />
            &nbsp;<br />
            &lt;/hibernate-mapping&gt;</pre>
            </font></div>
            </td>
        </tr>
    </tbody>
</table>
<br />
</div>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;显然对应的表是<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; vehicle(id, name)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;car(id, seat)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;truck(id, loads)&nbsp;&nbsp;&nbsp;<br />
<font color="#0000ff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;需要注意的是：car/truck 中的id 和vehicle中的id是一一对应的。</font><font color="#000000">&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Truck truck = new Truck();<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;truck.setName("西风卡车");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;truck.setLoad("10ton");<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sess.save(truck);*/<br />
&nbsp;&nbsp;&nbsp;插入记录的sql如下：<br />
&nbsp;&nbsp;&nbsp;Hibernate: insert into Vehicle (name, ID) values (?, ?)<br />
&nbsp;&nbsp;&nbsp;Hibernate: insert into Truck (loads, id) values (?, ?)<br />
&nbsp;&nbsp; 保存一条truck信息，要先在Vehicle中保存记录，得到id，然后把得到的id和需要的值一同保存到Truck中。<br />
<br />
<br />
</font></p>
<div>
<div>●&nbsp;优点：<br />
&#183; 与面向对象的概念的一致性最好。对多态的支持最好，对于对象所可能充当的角色仅需要在相应的表中保存记录。<br />
&#183; 易于修改基类和增加新的类。</div>
<div>&#183; 这种映射几乎有最佳的空间节约性。唯一的容易就是额外的OID，来连接不同的层级层次。 </div>
<div><br />
● 缺点：<br />
&#183; 数据库中存在大量的表。<br />
&#183; 访问数据的时间较长。在读写相关的任务上，这种映射方式相当费资源，这个代价还随着继承层次的增多而增大。 <br />
&#183; 对报表的支持较差，除非定义视图。</div>
</div>
<p><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
参考：<br />
</p>
<div>&#183; HIBERNATE - 符合Java习惯的关系数据库持久化（第8章）</div>
<div>&#183; <a href="http://www-900.ibm.com/developerWorks/cn/java/j-hibernate/index.shtml">Hibernate 简化继承映射</a></div>
<div>&#183; <a href="http://www.agiledata.org/essays/mappingObjects.html#">Mapping Objects to Relational Databases: O/R Mapping In Detail</a></div>
<div>&#183; <a href="http://www-106.ibm.com/developerworks/webservices/library/ws-mapping-to-rdb/">Mapping objects to relational databases</a></div>
<img src ="http://www.blogjava.net/gm_jing/aggbug/61605.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-03 22:11 <a href="http://www.blogjava.net/gm_jing/articles/61605.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>继承映射1 --每个类分层结构一张表</title><link>http://www.blogjava.net/gm_jing/articles/61215.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Tue, 01 Aug 2006 08:14:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/61215.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/61215.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/61215.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/61215.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/61215.html</trackback:ping><description><![CDATA[<p>Hibernate中有以下三种策略将这种关系映射到数据表上：<br />
&#183; 每个类层次结构一个表（table per class hierarchy）<br />
&#183; 每个子类一个表(table per subclass) <br />
&#183; 每个具体类一个表(table per concrete class)（有一些限制）<br />
&nbsp;<br />
&nbsp;&nbsp; 每个类层次结构一个表的方式是将所有继承同一父类别的对象储存在同一个表格中，为了做到这一点，<br />
<font color="#0000ff">需要在表中使用识别字段来表示某一列（row）是属于某个子类别或父类别</font>，在这个主题中我们将先说明这个方法。<br />
<br />
<br />
一个例子如下：<br />
&#183;&nbsp; 类Animal.java</p>
<div>
<div style="font-weight: bold; font-size: 15px; margin: 0px 5px; width: 70.94%; color: black; font-style: italic; font-family: Courier New; height: 18px; background-color: #cccccc">
<p><em>Animal.java</em> </p>
</div>
<div style="padding-right: 5px; border-top: #000000 1px solid; padding-left: 2px; font-size: 14px; padding-bottom: 5px; margin: 0px 5px; overflow: scroll; width: 71.08%; color: #000000; padding-top: 5px; border-bottom: #000000 1px solid; font-family: Courier New; height: 231px; background-color: #e2e2e2">
<pre>package com.jason.inheritance;</pre>
<pre>/**<br />
&nbsp;* @hibernate.class <br />
&nbsp;*&nbsp;&nbsp; table="Animal" <br />
&nbsp;*&nbsp;&nbsp; discriminator-value="Animal"<br />
&nbsp;* @hibernate.discriminator <br />
&nbsp;*&nbsp;&nbsp; column="ANIMAL_TYPE" <br />
&nbsp;*&nbsp;&nbsp; type="string" <br />
&nbsp;*&nbsp;&nbsp; length = "10"<br />
&nbsp;*/<br />
public class Animal {<br />
&nbsp;private Long id;</pre>
<pre>&nbsp;private String name;</pre>
<pre>&nbsp;/**<br />
&nbsp; * @hibernate.id <br />
&nbsp; *&nbsp;&nbsp; column="ID" <br />
&nbsp; *&nbsp;&nbsp; generator-class="hilo" <br />
&nbsp; *&nbsp;&nbsp; unsaved-value="null"<br />
&nbsp; */<br />
&nbsp;public Long getId() {<br />
&nbsp;&nbsp;return id;<br />
&nbsp;}</pre>
<pre>&nbsp;public void setId(Long id) {<br />
&nbsp;&nbsp;this.id = id;<br />
&nbsp;}</pre>
<pre>&nbsp;/**<br />
&nbsp; * @hibernate.property <br />
&nbsp; *&nbsp;&nbsp; length = "24"<br />
&nbsp; */<br />
&nbsp;public String getName() {<br />
&nbsp;&nbsp;return name;<br />
&nbsp;}</pre>
<pre>&nbsp;public void setName(String name) {<br />
&nbsp;&nbsp;this.name = name;<br />
&nbsp;}</pre>
<pre>&nbsp;public void makeSound(){};<br />
}<br />
</pre>
</div>
<br />
</div>
<div>&#183;&nbsp; 子类Cat.java<br />
<div style="padding-right: 5px; border-top: #000000 1px solid; padding-left: 2px; font-size: 14px; padding-bottom: 5px; margin: 0px 5px; overflow: scroll; width: 71.08%; color: #000000; padding-top: 5px; border-bottom: #000000 1px solid; font-family: Courier New; height: 231px; background-color: #e2e2e2">
<pre>
<pre><span style="font-weight: bold; color: #7f0055">package com.jason.inheritance;</span><strong><br />
<span style="font-weight: bold; color: #7f0055">public  </span></strong><span style="font-weight: bold; color: #7f0055">class</span> Cat <span style="font-weight: bold; color: #7f0055">extends</span> Animal {
<span style="font-weight: bold; color: #7f0055">private</span><span style="font-weight: bold; color: #7f0055">String</span> FurColor;
<span style="font-weight: bold; color: #7f0055">public</span><span style="font-weight: bold; color: #7f0055">void</span> makeSound() {
<span style="font-weight: bold; color: #7f0055">System</span>.out.println(<span style="color: #2a00ff">"喵喵"</span>);
}
<span style="font-weight: bold; color: #7f0055">public</span><span style="font-weight: bold; color: #7f0055">String</span> getFurColor() {
<span style="font-weight: bold; color: #7f0055">return</span> FurColor;
}
<span style="font-weight: bold; color: #7f0055">public</span><span style="font-weight: bold; color: #7f0055">void</span> setFurColor(<span style="font-weight: bold; color: #7f0055">String</span> furColor) {
FurColor = furColor;
}
}
</pre>
</pre>
</div>
<br />
</div>
<div>&#183;&nbsp; 子类Dog.java<br />
<div style="padding-right: 5px; border-top: #000000 1px solid; padding-left: 2px; font-size: 14px; padding-bottom: 5px; margin: 0px 5px; overflow: scroll; width: 71.08%; color: #000000; padding-top: 5px; border-bottom: #000000 1px solid; font-family: Courier New; height: 231px; background-color: #e2e2e2">
<p>package com.jason.inheritance;</p>
<p>/**<br />
&nbsp;* @hibernate.subclass <br />
&nbsp;*&nbsp;&nbsp; discriminator-value="Dog"<br />
&nbsp;*/<br />
public class Dog extends Animal {<br />
&nbsp;private String category;</p>
<p>&nbsp;public void makeSound() {<br />
&nbsp;&nbsp;System.out.println("汪汪");<br />
&nbsp;}</p>
<p>&nbsp;/**<br />
&nbsp; * @hibernate.property <br />
&nbsp; *&nbsp;&nbsp; length = "24"<br />
&nbsp; */<br />
&nbsp;public String getCategory() {<br />
&nbsp;&nbsp;return category;<br />
&nbsp;}</p>
<p>&nbsp;public void setCategory(String category) {<br />
&nbsp;&nbsp;this.category = category;<br />
&nbsp;}<br />
}</p>
<p>&nbsp;</p>
</div>
<br />
<br />
</div>
<div>&#183;&nbsp; Animal.hbm.xml</div>
<div>
<table bordercolor="#000000" cellspacing="0" cellpadding="4" width="70%" border="0">
    <tbody>
        <tr>
            <td style="font-weight: bold; font-size: 14px; border-bottom: rgb(51,51,204) thin inset; font-style: italic; font-family: Courier New" valign="top" width="100%" bgcolor="#cccccc" height="16"></td>
        </tr>
        <tr>
            <td style="font-size: 12px; border-top-style: none; border-top-color: rgb(236,233,216); font-family: Courier New" valign="top" width="100%" bgcolor="#e2e2e2">
            <div><font face="Courier New">
            <pre>&lt;?xml version="1.0"?&gt;<br />
            &lt;!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br />
            &nbsp;"<a href="http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd</a>"&gt;</pre>
            <pre>&lt;hibernate-mapping&gt;<br />
            &nbsp;&lt;class name="com.jason.inheritance.Animal" table="Animal"<br />
            &nbsp;&nbsp;dynamic-update="false" dynamic-insert="true" select-before-update="false"<br />
            &nbsp;&nbsp;optimistic-lock="version" <font color="#ff1493">discriminator-value="Animal"</font>&gt;<br />
            &nbsp;&nbsp;<br />
            &nbsp;&nbsp;&lt;id name="id" column="ID" type="java.lang.Long" unsaved-value="null"&gt;<br />
            &nbsp;&nbsp;&nbsp;&lt;generator class="hilo"&gt;<br />
            &nbsp;&nbsp;&nbsp;&lt;/generator&gt;<br />
            &nbsp;&nbsp;&lt;/id&gt;<br />
            &nbsp;&nbsp;<br />
            &nbsp;&nbsp;<font color="#ff1493">&lt;discriminator column="ANIMAL_TYPE" type="string" length="10"/&gt;</font><br />
            &nbsp;&nbsp;<br />
            &nbsp;&nbsp;&lt;property name="name" type="java.lang.String" update="true" insert="true"<br />
            &nbsp;&nbsp;&nbsp;access="property" column="name" length="24"/&gt;<br />
            &nbsp;&nbsp;<br />
            &nbsp;&nbsp;&lt;subclass name="com.jason.inheritance.Cat" dynamic-update="false"<br />
            &nbsp;&nbsp;&nbsp;dynamic-insert="false" <font color="#ff1493">discriminator-value="Cat"</font>&gt;<br />
            &nbsp;&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&lt;property name="furColor" type="java.lang.String" update="true"<br />
            &nbsp;&nbsp;&nbsp;&nbsp;insert="true" access="property" column="furColor" length="24"/&gt;<br />
            &nbsp;&nbsp;&lt;/subclass&gt;<br />
            &nbsp;&nbsp;&lt;subclass name="com.jason.inheritance.Dog" dynamic-update="false"<br />
            &nbsp;&nbsp;&nbsp;dynamic-insert="false" <font color="#ff1493">discriminator-value="Dog"</font>&gt;<br />
            &nbsp;&nbsp;&nbsp;<br />
            &nbsp;&nbsp;&nbsp;&lt;property name="category" type="java.lang.String" update="true"<br />
            &nbsp;&nbsp;&nbsp;&nbsp;insert="true" access="property" column="category" length="24"/&gt;<br />
            &nbsp;&nbsp;&lt;/subclass&gt;<br />
            &nbsp;&nbsp;<br />
            &nbsp;&lt;/class&gt;<br />
            &nbsp;<br />
            &lt;/hibernate-mapping&gt;</pre>
            </font></div>
            </td>
        </tr>
    </tbody>
</table>
<br />
</div>
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;显然对应的表是Animal（ID, ANIMAL_TYPE, name, furColor, category）<br />
<font color="#0000ff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;需要在表中使用识别字段来表示某一列（row）是属于某个子类别或父类别,<br />
</font><font color="#000000">就是用ANIMAL_TYPE来表示的！<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 插入记录的sql如下：<br />
Hibernate: insert into Animal (name, ANIMAL_TYPE, ID) values (?, 'Animal', ?)<br />
Hibernate: insert into Animal (name, furColor, ANIMAL_TYPE, ID) values (?, ?, 'Cat', ?)<br />
Hibernate: insert into Animal (name, category, ANIMAL_TYPE, ID) values (?, ?, 'Dog', ?)<br />
<br />
<br />
</font></p>
<div>●&nbsp;优点：<br />
&#183; 实现简单。<br />
&#183; 支持多态——对象角色发生变化，或存在多重角色时。<br />
&#183; 报表操作实现简单：表中包含了所有信息。</div>
<div><br />
● 缺点：<br />
&#183; <span style="color: red">增加类层次中的耦合</span>。类层次中任何类的属性的增加都会导致表的变更；某个子类属性的修改会影响到整个层次结构，而不仅仅是该子类。<br />
&#183; <span style="color: red">浪费了一些数据库空间</span>。浪费空间的多少取决于继承层次的深度。层次越深，不同的属性越多，属性的全集就越大，也就越浪费空间。<br />
&#183; <span style="color: red">要求由子类定义的字段不能有非空（NOT NULL）约束</span>。<br />
<br />
</div>
<p><br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
参考：<br />
</p>
<div>&#183; HIBERNATE - 符合Java习惯的关系数据库持久化（第8章）</div>
<div>&#183; <a href="http://www-900.ibm.com/developerWorks/cn/java/j-hibernate/index.shtml">Hibernate 简化继承映射</a></div>
<div>&#183; <a href="http://www.agiledata.org/essays/mappingObjects.html#">Mapping Objects to Relational Databases: O/R Mapping In Detail</a></div>
<div>&#183; <a href="http://www-106.ibm.com/developerworks/webservices/library/ws-mapping-to-rdb/">Mapping objects to relational databases</a></div>
<img src ="http://www.blogjava.net/gm_jing/aggbug/61215.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-08-01 16:14 <a href="http://www.blogjava.net/gm_jing/articles/61215.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate 得到对象的方法</title><link>http://www.blogjava.net/gm_jing/articles/59304.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Thu, 20 Jul 2006 16:44:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/59304.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/59304.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/59304.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/59304.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/59304.html</trackback:ping><description><![CDATA[1.Criteria<br />
&nbsp;&nbsp;&nbsp;Criteria criteria = session.createCriteria(User.class);<br />
&nbsp;&nbsp;&nbsp;criteria.add(Expression.eq("name","liping"));<br />
&nbsp;&nbsp;&nbsp;//criteria.add(Example.create(user));<br />
&nbsp;&nbsp;&nbsp;List userList = criteria.list();<br />
<br />
2.HQL<br />
&nbsp;&nbsp;&nbsp;String hql = "from org.hibernate.sample.TUser";<br />
&nbsp;&nbsp;&nbsp;Query query = session.createQuery(hql);<br />
&nbsp;&nbsp;&nbsp;List userList = query.list();<br />
<br />
3.SQL<br />
&nbsp;&nbsp; List cats = session.createSQLQuery(<br />
&nbsp;&nbsp;&nbsp; "SELECT {cat.*} FROM CAT {cat} WHERE ROWNUM&lt;10",<br />
&nbsp;&nbsp;&nbsp; "cat",Cat.class).list();<br />
<br />
4.GET<br />
&nbsp;&nbsp;&nbsp;User user = session.get("com.jason.User", new Long(69));<br />
&nbsp;&nbsp;&nbsp; ...<br />
5.Load<br />
&nbsp;&nbsp; User user = (User) session.load( User.class, new Long(69) );<br />
&nbsp;&nbsp;&nbsp;...<br />
&nbsp; //Session.load(Class theClass, Serializable id) 这个id的类型，对应于theClass中id的类型。<br />
<br />
<br />
6.Session.find/iterate<br />
List&nbsp;users = session.find(<span class="string">"from&nbsp;user"</span><span>);&nbsp;&nbsp;&nbsp;</span><br />
<br />
<br />
<br />
<br />
<br />
<img src ="http://www.blogjava.net/gm_jing/aggbug/59304.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-07-21 00:44 <a href="http://www.blogjava.net/gm_jing/articles/59304.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate的锁</title><link>http://www.blogjava.net/gm_jing/articles/59094.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Wed, 19 Jul 2006 17:49:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/59094.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/59094.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/59094.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/59094.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/59094.html</trackback:ping><description><![CDATA[
		<p>【引用】<a href="http://www.tongyi.net/develop/Java/1025649.html">http://www.tongyi.net/develop/Java/1025649.html</a><br /><br />Hibernate的加锁模式有：<br /><br />Ø LockMode.WRITE ：Hibernate在Insert和Update记录的时候会自动获取。<br />         这种锁机制一般由Hibernate内部使用，如Hibernate为了保证Update过程中对象不会被外界修改，会在save方法实现中自动为目标对象加上WRITE锁。<br /><br />Ø LockMode.NONE ： 无锁机制。<br />Ø LockMode.READ ： Hibernate在读取记录的时候会自动获取。//select id from User where id =? <br />Ø LockMode.UPGRADE ：利用数据库的for update子句加锁。//select id from User where id =? for update<br />Ø LockMode. UPGRADE_NOWAIT ：Oracle的特定实现，利用Oracle的for update nowait子句实现加锁。<br />上面这几种锁机制是我们在应用层较为常用的，加锁一般通过以下方法实现：<br />Criteria.setLockMode<br />Query.setLockMode<br />Session.lock<br /><font style="BACKGROUND-COLOR: #ffffff"><font color="#0000ff">注意，只有在查询开始之前（也就是Hiberate 生成SQL 之前）设定加锁，才会<br />真正通过数据库的锁机制进行加锁处理，否则，数据已经通过不包含for update<br />子句的Select SQL加载进来，所谓数据库加锁也就无从谈起</font>。</font></p>
		<p> </p>
		<p>Hibernate 在其数据访问引擎中内置了乐观锁实现。如果不用考虑外部系统对数据库的更新操作，<br />利用Hibernate提供的透明化乐观锁实现，将大大提升我们的生产力。<br />Hibernate中可以通过class描述符的optimistic-lock属性结合version描述符指定。<br />现在，我们为之前示例中的TUser加上乐观锁机制。<br />1． 首先为TUser的class描述符添加optimistic-lock属性：<br /><hibernate-mapping><br /><class><br />name="org.hibernate.sample.TUser"<br />table="t_user"<br />dynamic-update="true"<br />dynamic-insert="true"<br />optimistic-lock="version"<br />&gt;<br />……<br /></class><br /></hibernate-mapping>optimistic-lock属性有如下可选取值：<br />Ø none<br />无乐观锁<br />Ø version<br />通过版本机制实现乐观锁<br />Ø dirty<br />通过检查发生变动过的属性实现乐观锁<br />Ø all<br />通过检查所有属性实现乐观锁<br />其中通过version实现的乐观锁机制是Hibernate官方推荐的乐观锁实现，同时也<br />是Hibernate中，目前唯一在数据对象脱离Session发生修改的情况下依然有效的锁机<br />制。因此，一般情况下，我们都选择version方式作为Hibernate乐观锁实现机制。</p>
<img src ="http://www.blogjava.net/gm_jing/aggbug/59094.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-07-20 01:49 <a href="http://www.blogjava.net/gm_jing/articles/59094.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Session方法</title><link>http://www.blogjava.net/gm_jing/articles/58881.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Tue, 18 Jul 2006 16:51:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/58881.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/58881.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/58881.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/58881.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/58881.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session.get/load的区别：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.如果未能发现符合条件的记录，get方法返回null，而load方法会抛出一个ObejctNotFoundException。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.Load方法可返回实体的代理类类型，而get方法永远直接返回实体类。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.Load方法可以充分利用内部缓存和二级缓存中现有数据，而get方法则仅仅在内部缓存中进行数据查找，如没有发现对应数据，将越过二级缓存，直接调用SQL完成数据读取。 </p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<hr />
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session.find/iterate的区别：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;find方法将执行Select SQL从数据库中获得所有符合条件的记录并构造相应的实体对象，实体对象构建完毕之后，就将其纳入缓存。它对缓存只写不读，因此无法利用缓存。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iterate方法首先执行一条Select SQL以获得所有符合查询条件的数据id，随即，iterate方法首先在本地缓存中根据id查找对应的实体对象是否存在，如果缓存中已经存在对应的数据，则直接以此数据对象作为查询结果，如果没有找到，再执行相应的Select语句获得对应的库表记录（iterate方法如果执行了数据库读取操作并构建了完整的数据对象，也会将其查询结果纳入缓存）。 <br />
<br />
<br />
[<font color="#0000ff">实际的情况是,如果使用了iterate方法返回Iterator类型的查询结果,那么你一旦关闭session,Iterator中的数据立即就会消失.而通过find得到的List则不会如此,我想大部分人的使用习惯都是操作完成后立即关闭session,很多公司也强制要求这样做. <br />
Iterator的另一个麻烦事是fail-fast,在多线程环境下,很容易产生.使用线程安全的List子类,则不会有这个问题]</font></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<hr />
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query Cache产生作用的情况：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.完全相同的Select SQL重复执行。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.在两次查询之间，此Select SQL对应的库表没有发生过改变。 </p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<hr />
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session.save方法的执行步骤：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.在Session内部缓存中寻找待保存对象。内部缓存命中，则认为此数据已经保存（执行过insert操作），实体对象已经处于Persistent状态，直接返回。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.如果实体类实现了lifecycle接口，则调用待保存对象的onSave方法。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.如果实体类实现了validatable接口，则调用其validate()方法。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.调用对应拦截器的Interceptor.onSave方法（如果有的话）。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.构造Insert SQL，并加以执行。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;6.记录插入成功，user.id属性被设定为insert操作返回的新记录id值。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;7.将user对象放入内部缓存。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;8.最后，如果存在级联关系，对级联关系进行递归处理。 </p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<hr />
<p><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session.update方法的执行步骤：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.根据待更新实体对象的Key，在当前session的内部缓存中进行查找，如果发现，则认为当前实体对象已经处于Persistent状态，返回。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.初始化实体对象的状态信息（作为之后脏数据检查的依据），并将其纳入内部缓存。注意这里Session.update方法本身并没有发送Update SQL完成数据更新操作，<span style="color: red">Update SQL将在之后的Session.flush方法中执行，</span>根据id更新所有的字段，如update user set name=?, password=? where id=?。 </p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<hr />
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session.saveOrUpdate方法的执行步骤：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;1.首先在Session内部缓存中进行查找，如果发现则直接返回。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2.执行实体类对应的Interceptor.isUnsaved方法（如果有的话），判断对象是否为未保存状态。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;3.根据unsaved-value判断对象是否处于未保存状态。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;4.如果对象未保存（Transient状态），则调用save方法保存对象。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;5.如果对象为已保存（Detached状态），调用update方法将对象与Session重新关联。</p>
<hr />
<br />
Session.delete(E)<br />
&nbsp;E 由持久状态/游离状态 --&gt;&gt;自由状态<br />
<br />
<hr />
<br />
Session.flush()
<p>调用flush<br />
1.直接调用Session.flush();<br />
2.tx.commit();<br />
//flush before commiting the transaction and closing the session <br />
//Flushing is the process of synchronising the underlying persistent store with persistable state held in memory.<br />
<br />
</p>
<hr />
<p><br />
E1=Session.merge(E)<br />
if E is transient instance,则insert数据库,E状态不变化,E1是一个持久化对象;<br />
if E is detached instance,则重新load,变成persistent instance;<br />
if E is persistent instance,则从缓存中选择;<br />
<br />
// Copy &nbsp; the &nbsp; state &nbsp; of &nbsp; the &nbsp; given &nbsp; object &nbsp; onto &nbsp; the &nbsp; persistent &nbsp; object &nbsp; with &nbsp; the &nbsp; same &nbsp; identifier.&nbsp;&nbsp; <br />
// If &nbsp; there &nbsp; is &nbsp; no &nbsp; persistent &nbsp; instance &nbsp; currently &nbsp; associated &nbsp; with &nbsp; the &nbsp; session,&nbsp;&nbsp;it&nbsp; will &nbsp; be &nbsp; loaded. &nbsp; Return &nbsp; the &nbsp; persistent &nbsp; instance.&nbsp;&nbsp; <br />
// If &nbsp; the &nbsp; given &nbsp; instance &nbsp; is &nbsp; unsaved, &nbsp; save &nbsp; a &nbsp; copy &nbsp; of &nbsp; and &nbsp; <span style="color: red">return &nbsp; it &nbsp; as &nbsp; a &nbsp; newly &nbsp; persistent &nbsp; instance.</span> &nbsp; <span style="color: red">The &nbsp; given &nbsp; instance &nbsp; does &nbsp; not &nbsp; become &nbsp; associated &nbsp; with &nbsp; the &nbsp; session.&nbsp;&nbsp;</span> <br />
// This &nbsp; operation &nbsp; cascades &nbsp; to &nbsp; associated &nbsp; instances &nbsp; if &nbsp; the &nbsp; association &nbsp; is &nbsp; mapped &nbsp; with &nbsp; cascade="merge". </p>
<br />
<hr />
&nbsp;Session.persist(E)<br />
<p><span style="font-size: small">persist() is well defined. It makes a transient instance persistent. However, <br />
it doesn't guarantee that the identifier value will be assigned to the persistent <br />
instance immediately, the assignment might happen at flush time. The spec doesn't say <br />
that, which is the problem I have with persist().</span></p>
<p><span style="font-size: small">persist() also guarantees that it will not execute an INSERT statement if it is <br />
called outside of transaction boundaries. This is useful in long-running conversations <br />
with an extended Session/persistence context.A method like persist() is required.</span></p>
<p><span style="font-size: small">save() does not guarantee the same, it returns an identifier, and if an INSERT <br />
has to be executed to get the identifier (e.g. "identity" generator, not "sequence"), <br />
this INSERT happens immediately, no matter if you are inside or outside of a transaction. This is not good in a long-running conversation with an extended Session/persistence context."</span></p>
<br />
<img src ="http://www.blogjava.net/gm_jing/aggbug/58881.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-07-19 00:51 <a href="http://www.blogjava.net/gm_jing/articles/58881.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>实体对象识别</title><link>http://www.blogjava.net/gm_jing/articles/58880.html</link><dc:creator>黎夕</dc:creator><author>黎夕</author><pubDate>Tue, 18 Jul 2006 16:49:00 GMT</pubDate><guid>http://www.blogjava.net/gm_jing/articles/58880.html</guid><wfw:comment>http://www.blogjava.net/gm_jing/comments/58880.html</wfw:comment><comments>http://www.blogjava.net/gm_jing/articles/58880.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/gm_jing/comments/commentRss/58880.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/gm_jing/services/trackbacks/58880.html</trackback:ping><description><![CDATA[
		<font size="2">【引用】</font>
		<a href="/georgehill/archive/2005/06/22/6546.html">http://www.blogjava.net/georgehill/archive/2005/06/22/6546.html</a>
		<br />
		<br />在Java语言中，对象之间的比较可以通过引用比较(==)和内容比较(equals)两种方式进行，而在Hibernate的实体对象的比较是通过主键值来比较，如果要实现自己的识别逻辑，则需要重写equals方法和hashCode方法。<br /><br />      检查数据对象改变检查的一般策略有下面两种：<br />      1. 数据对象监控<br />         数据对象监控的实现方式，通过拦截器对数据对象的设值方法进行拦截。一旦数据对象的设置方法被调用，则将其标志为“待更新”状态，之后在数据库操作时将其更新到对应的库表。<br />      2. 数据版本对比<br />         在持久层框架中维持数据对象的最近读取版本，当数据提交时将提交数据与此版本进行比对，如果发生变化则将其同步到数据库对应的库表。<br /><br />      Hibernate采取的是第二种检查策略。它采用一个内部数据结构"EntityEntry"保存对应实体类的状态信息。<br /><br />      对于级联对象的更新，Hibernate将根据unsaved-value进行判定。首先Hibernate会取出目标对象的id。之后，将此值与unsaved-value进行比对，如果相等，则认为目标对象尚未保存，否则，认为对象已经保存，无需再进行保存操作。<img src ="http://www.blogjava.net/gm_jing/aggbug/58880.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/gm_jing/" target="_blank">黎夕</a> 2006-07-19 00:49 <a href="http://www.blogjava.net/gm_jing/articles/58880.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>