﻿<?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/alex/category/16525.html</link><description>不求多得,只求一得
about java,hibernate,spring,design,database,linux,etc.
&lt;br/&gt;&lt;br/&gt;
最近关心的内容关键字:web快速开发方案，建模,workshop studio,Ajax
</description><language>zh-cn</language><lastBuildDate>Sun, 13 May 2007 10:31:01 GMT</lastBuildDate><pubDate>Sun, 13 May 2007 10:31:01 GMT</pubDate><ttl>60</ttl><item><title>简单就是美 -- 简化hibernate,简化dao</title><link>http://www.blogjava.net/alex/archive/2007/05/13/117118.html</link><dc:creator>Alex</dc:creator><author>Alex</author><pubDate>Sun, 13 May 2007 08:41:00 GMT</pubDate><guid>http://www.blogjava.net/alex/archive/2007/05/13/117118.html</guid><wfw:comment>http://www.blogjava.net/alex/comments/117118.html</wfw:comment><comments>http://www.blogjava.net/alex/archive/2007/05/13/117118.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/alex/comments/commentRss/117118.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/alex/services/trackbacks/117118.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;<a href='http://www.blogjava.net/alex/archive/2007/05/13/117118.html'>阅读全文</a><img src ="http://www.blogjava.net/alex/aggbug/117118.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/alex/" target="_blank">Alex</a> 2007-05-13 16:41 <a href="http://www.blogjava.net/alex/archive/2007/05/13/117118.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[zt] Hibernate+Spring 对DAO的处理实列!</title><link>http://www.blogjava.net/alex/archive/2007/01/25/95839.html</link><dc:creator>Alex</dc:creator><author>Alex</author><pubDate>Thu, 25 Jan 2007 01:24:00 GMT</pubDate><guid>http://www.blogjava.net/alex/archive/2007/01/25/95839.html</guid><wfw:comment>http://www.blogjava.net/alex/comments/95839.html</wfw:comment><comments>http://www.blogjava.net/alex/archive/2007/01/25/95839.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/alex/comments/commentRss/95839.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/alex/services/trackbacks/95839.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: key words : hibernate spring daocome from : http://lpacec.javaeye.com/blog/46220   1.  package infoweb.dao;         2.         3. import java.util.List;         4. import java.util.Iterator;         5...&nbsp;&nbsp;<a href='http://www.blogjava.net/alex/archive/2007/01/25/95839.html'>阅读全文</a><img src ="http://www.blogjava.net/alex/aggbug/95839.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/alex/" target="_blank">Alex</a> 2007-01-25 09:24 <a href="http://www.blogjava.net/alex/archive/2007/01/25/95839.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>MiddleGen中配置hibernate的many to many属性</title><link>http://www.blogjava.net/alex/archive/2006/12/07/86159.html</link><dc:creator>Alex</dc:creator><author>Alex</author><pubDate>Thu, 07 Dec 2006 12:26:00 GMT</pubDate><guid>http://www.blogjava.net/alex/archive/2006/12/07/86159.html</guid><wfw:comment>http://www.blogjava.net/alex/comments/86159.html</wfw:comment><comments>http://www.blogjava.net/alex/archive/2006/12/07/86159.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/alex/comments/commentRss/86159.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/alex/services/trackbacks/86159.html</trackback:ping><description><![CDATA[key words: MiddleGen,hibernate,many to many,多对多<br /><br />如果你有如下表结构<br /><br />user(user_id,user_name)<br />role(role_id,role_name)<br /><br />user_role(id,user_id,role_id)<br /><br />那么默认MiddleGen生成的是两个一对多，但我们更多的情况是用many to many<br /><br />需要修改middlegen的build.xml文件<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">many2many</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br />            </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">tablea </span><span style="color: rgb(255, 0, 0);">generate</span><span style="color: rgb(0, 0, 255);">="true"</span><span style="color: rgb(255, 0, 0);"> name</span><span style="color: rgb(0, 0, 255);">="user"</span><span style="color: rgb(0, 0, 255);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br />            </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">jointable </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="user_role"</span><span style="color: rgb(255, 0, 0);"> generate</span><span style="color: rgb(0, 0, 255);">="false"</span><span style="color: rgb(0, 0, 255);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br />            </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">tableb </span><span style="color: rgb(255, 0, 0);">generate</span><span style="color: rgb(0, 0, 255);">="true"</span><span style="color: rgb(255, 0, 0);"> name</span><span style="color: rgb(0, 0, 255);">="role"</span><span style="color: rgb(0, 0, 255);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br />         </span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">many2many</span><span style="color: rgb(0, 0, 255);">&gt;</span></div><br /><img src ="http://www.blogjava.net/alex/aggbug/86159.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/alex/" target="_blank">Alex</a> 2006-12-07 20:26 <a href="http://www.blogjava.net/alex/archive/2006/12/07/86159.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate的Fetch</title><link>http://www.blogjava.net/alex/archive/2006/12/01/84808.html</link><dc:creator>Alex</dc:creator><author>Alex</author><pubDate>Fri, 01 Dec 2006 05:01:00 GMT</pubDate><guid>http://www.blogjava.net/alex/archive/2006/12/01/84808.html</guid><wfw:comment>http://www.blogjava.net/alex/comments/84808.html</wfw:comment><comments>http://www.blogjava.net/alex/archive/2006/12/01/84808.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/alex/comments/commentRss/84808.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/alex/services/trackbacks/84808.html</trackback:ping><description><![CDATA[越来越发现其实掌握 hibernate并不容易，Spring用起来其实简单多了，但是在用hibernate的时候真的是需要一定的时间积累，对一个项目组来说如果采用hibernate最好有一个对hibernate比较清楚的人否则碰到问题就会成为项目的风险。<br />我想告诉各位的是，掌握hibernate可能比你预期的难多了，当你轻松的告诉我，hibernate很简单的时候该是你自己多反省了. （只有一种情况例外，你是一个牛人）<br /><br />好了，一个引子废话那么多，其实今天只是想先说一说hibernate里的Fetch的作用.<br /><br />大家都知道，在hibernate里为了性能考虑，引进了lazy的概念，这里我们以Parent和Child为模型来说明，<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> Parent </span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);"> Serializable {<br /><br />    </span><span style="color: rgb(0, 128, 0);">/**</span><span style="color: rgb(0, 128, 0);"> identifier field </span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> Long id;<br /><br />    </span><span style="color: rgb(0, 128, 0);">/**</span><span style="color: rgb(0, 128, 0);"> persistent field </span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> List childs;<br /><br />    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">skip all getter/setter method</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"><br />   <br />}    <br /><br /></span></div><br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> Child </span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);"> Serializable {<br /><br />    </span><span style="color: rgb(0, 128, 0);">/**</span><span style="color: rgb(0, 128, 0);"> identifier field </span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> Long id;<br /><br />    </span><span style="color: rgb(0, 128, 0);">/**</span><span style="color: rgb(0, 128, 0);"> persistent field </span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> net.foxlog.model.Parent parent;<br /><br />    //skip all getter/setter method<br /><br />}</span></div><br />在我们查询Parent对象的时候，默认只有Parent的内容，并不包含childs的信息，如果在Parent.hbm.xml里设置lazy="false"的话才同时取出关联的所有childs内容.<br /><br />问题是我既想要hibernate默认的性能又想要临时的灵活性该怎么办？  这就是fetch的功能。我们可以把fetch与lazy="true"的关系类比为事务当中的编程式事务与声明式事务,不太准确，但是大概是这个意思。<br /><br />总值，fetch就是在代码这一层给你一个主动抓取得机会.<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">Parent parent </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (Parent)hibernateTemplate.execute(</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> HibernateCallback() {<br />            </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> Object doInHibernate(Session session) </span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);"> HibernateException, SQLException {<br />                Query q </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> session.createQuery(<br />                        </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">from Parent as parent </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"><br />                                </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> left outer join fetch parent.childs </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"><br />                                </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> where parent.id = :id</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br />                );<br />                q.setParameter(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">id</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Long(</span><span style="color: rgb(0, 0, 0);">15</span><span style="color: rgb(0, 0, 0);">));<br />                </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> (Parent)q.uniqueResult();<br />            }<br /><br />        });<br /><br />        Assert.assertTrue(parent.getChilds().size() </span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">);</span></div><br /><br />你可以在lazy="true"的情况下把fetch去掉，就会报异常. 当然，如果lazy="false"就不需要fetch了<br /><br /><br />有一个问题,使用Fetch会有重复记录的现象发生,我们可以理解为Fetch实际上不是为Parent服务的,而是为Child服务的.所以直接取Parent会有不匹配的问题.<br /><br /><span style="color: rgb(0, 0, 0);"><br /><br />参考一下下面的这篇文章<br /><a target="_blank" href="http://waterye.blogdriver.com/waterye/395708.html">Hibernate集合初始化</a><br /><br />======================================================================<br /><br />update:以上有些结论错误，实际上在hibernate3.2.1版本下测试，可以不出现重复记录，<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> testNPlusOne() </span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);"> Exception{<br />        List list </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (List)hibernateTemplate.execute(</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> HibernateCallback() {<br />            </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> Object doInHibernate(Session session) </span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);"> HibernateException, SQLException {<br />                Query q </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> session.createQuery(<br />                        </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">select distinct p from net.foxlog.model.Parent p inner join fetch p.childs</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"><br />                );<br />                </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> q.list();<br />            }<br /><br />        });<br /><br />        </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);">((Parent)(list.get(0))).getChilds();</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);">        System.out.println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">list size = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> list.size());<br />        </span><span style="color: rgb(0, 0, 255);">for</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> i</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">0</span><span style="color: rgb(0, 0, 0);">;i</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">list.size();i</span><span style="color: rgb(0, 0, 0);">++</span><span style="color: rgb(0, 0, 0);">){<br />            Parent p </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (Parent)list.get(i);<br />            System.out.println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">===parent = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> p);<br />            System.out.println(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">===parent's child's length = </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> p.getChilds().size());<br />        }<br /><br />    }</span></div><br /><br />打印结果如下:<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">Hibernate: select distinct parent0_.id as id2_0_, childs1_.id as id0_1_, childs1_.parent_id as parent2_0_1_, childs1_.parent_id as parent2_0__, childs1_.id as id0__ from parent parent0_ inner join child childs1_ on parent0_.id</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">childs1_.parent_id<br />list size </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">3</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 0);">===</span><span style="color: rgb(0, 0, 0);">parent </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> net.foxlog.model.Parent@1401d28[id</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">14</span><span style="color: rgb(0, 0, 0);">]<br /></span><span style="color: rgb(0, 0, 0);">===</span><span style="color: rgb(0, 0, 0);">parent</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">s child</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">s length </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">1</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 0);">===</span><span style="color: rgb(0, 0, 0);">parent </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> net.foxlog.model.Parent@14e0e90[id</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">15</span><span style="color: rgb(0, 0, 0);">]<br /></span><span style="color: rgb(0, 0, 0);">===</span><span style="color: rgb(0, 0, 0);">parent</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">s child</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">s length </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">2</span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 0);">===</span><span style="color: rgb(0, 0, 0);">parent </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> net.foxlog.model.Parent@62610b[id</span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);">17</span><span style="color: rgb(0, 0, 0);">]<br /></span><span style="color: rgb(0, 0, 0);">===</span><span style="color: rgb(0, 0, 0);">parent</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">s child</span><span style="color: rgb(0, 0, 0);">'</span><span style="color: rgb(0, 0, 0);">s length </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">3</span><span style="color: rgb(0, 0, 0);"><br /></span></div><br />另外，如果用open session in view模式的话一般不用fetch,但首先推荐fetch,如果非用的话因为有N+1的现象，所以可以结合batch模式来改善下性能.<br /><br /><br /></span><img src ="http://www.blogjava.net/alex/aggbug/84808.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/alex/" target="_blank">Alex</a> 2006-12-01 13:01 <a href="http://www.blogjava.net/alex/archive/2006/12/01/84808.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[zt]hibernate复合主键</title><link>http://www.blogjava.net/alex/archive/2006/11/09/80231.html</link><dc:creator>Alex</dc:creator><author>Alex</author><pubDate>Thu, 09 Nov 2006 11:22:00 GMT</pubDate><guid>http://www.blogjava.net/alex/archive/2006/11/09/80231.html</guid><wfw:comment>http://www.blogjava.net/alex/comments/80231.html</wfw:comment><comments>http://www.blogjava.net/alex/archive/2006/11/09/80231.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/alex/comments/commentRss/80231.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/alex/services/trackbacks/80231.html</trackback:ping><description><![CDATA[key words:hibernate,复合主键，composite-id<br /><br /><br /><br /><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">基于业务需求，您会需要使用两个字段来作复合主键，例如在<span lang="EN-US">User</span>数据表中，您也许会使用<span lang="EN-US">"name"</span>与<span lang="EN-US">"phone"</span>两个字段来定义复合主键。<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">假设您这么建立<span lang="EN-US">User</span>表格：<span lang="EN-US"><o:p></o:p></span></span></p><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">CREATE</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">TABLE</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(255, 0, 255);">user</span><span style="color: rgb(0, 0, 0);"> (<br /><br />    name </span><span style="color: rgb(0, 0, 0); font-weight: bold;">VARCHAR</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(128, 0, 0); font-weight: bold;">100</span><span style="color: rgb(0, 0, 0);">) </span><span style="color: rgb(128, 128, 128);">NOT</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">NULL</span><span style="color: rgb(0, 0, 0);">,<br /><br />    phone </span><span style="color: rgb(0, 0, 0); font-weight: bold;">VARCHAR</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(128, 0, 0); font-weight: bold;">50</span><span style="color: rgb(0, 0, 0);">) </span><span style="color: rgb(128, 128, 128);">NOT</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">NULL</span><span style="color: rgb(0, 0, 0);">,<br /><br />    age </span><span style="color: rgb(0, 0, 0); font-weight: bold;">INT</span><span style="color: rgb(0, 0, 0);">,<br /><br />    </span><span style="color: rgb(0, 0, 255);">PRIMARY</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">KEY</span><span style="color: rgb(0, 0, 0);">(name, phone)<br /><br />);<br /></span></div><br /><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">在表格中，<span lang="EN-US">"name"</span>与<span lang="EN-US">"age"</span>被定义为复合主键，在映像时，您可以让<span lang="EN-US">User</span>类别直接带有<span lang="EN-US">"name"</span>与<span lang="EN-US">"age"</span>这两个属性，而<span lang="EN-US">Hibernate</span>要求复合主键类别要实作<span lang="EN-US">Serializable</span>接口，并定义<span lang="EN-US">equals()</span>与<span lang="EN-US">hashCode()</span>方法：<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="text-align: left;" align="left"><b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">User.java</span></b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">package</span><span style="color: rgb(0, 0, 0);"> onlyfun.caterpillar;<br /><br /> <br /><br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.io.Serializable;<br /><br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> org.apache.commons.lang.builder.EqualsBuilder;<br /><br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> org.apache.commons.lang.builder.HashCodeBuilder;<br /><br /> <br /><br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> 复合主键类的对应类别必须实作Serializable接口</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"><br /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> User </span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);"> Serializable {<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> String name;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> String phone;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> Integer age;<br /><br />   <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> User() {<br /><br />    }<br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> Integer getAge() {<br /><br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> age;<br /><br />    }<br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> setAge(Integer age) {<br /><br />        </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.age </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> age;<br /><br />    }<br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> String getName() {<br /><br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> name;<br /><br />    }<br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> setName(String name) {<br /><br />        </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.name </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> name;<br /><br />    }<br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> String getPhone() {<br /><br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> phone;<br /><br />    }<br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> setPhone(String phone) {<br /><br />        </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.phone </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> phone;<br /><br />    }<br /><br />   <br /><br />    </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> 必须重新定义equals()与hashCode()</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">boolean</span><span style="color: rgb(0, 0, 0);"> equals(Object obj) {<br /><br />        </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(obj </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">) {<br /><br />            </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">;<br /><br />        }<br /><br />       <br /><br />        </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">!</span><span style="color: rgb(0, 0, 0);">(obj </span><span style="color: rgb(0, 0, 255);">instanceof</span><span style="color: rgb(0, 0, 0);"> User)) {<br /><br />            </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);">;<br /><br />        }<br /><br />       <br /><br />        User user </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (User) obj;<br /><br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> EqualsBuilder()<br /><br />                 .append(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.name, user.getName())<br /><br />                 .append(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.phone, user.getPhone())<br /><br />                 .isEquals();<br /><br />       <br /><br />    }<br /><br />   <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> hashCode() {<br /><br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> HashCodeBuilder()<br /><br />                 .append(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.name)<br /><br />                 .append(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.phone)<br /><br />                 .toHashCode();<br /><br />    }<br /><br />}<br /></span></div><br /><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">equals()</span><span style="font-size: 12pt; font-family: 宋体;">与<span lang="EN-US">hashCode()</span>方法被用作两笔不同数据的识别依据；接着您可以使用<span lang="EN-US">&lt;composite-id&gt;</span>在映射文件中定义复合主键与对象的属性对应：<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="text-align: left;" align="left"><b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">User.hbm.xml</span></b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">&lt;?</span><span style="color: rgb(255, 0, 255);">xml version="1.0" encoding="utf-8"</span><span style="color: rgb(0, 0, 255);">?&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br /></span><span style="color: rgb(0, 0, 255);">&lt;!</span><span style="color: rgb(255, 0, 255);">DOCTYPE hibernate-mapping<br /><br />    PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br /><br />    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br /> <br /><br /></span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">hibernate-mapping</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">class </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="onlyfun.caterpillar.User"</span><span style="color: rgb(255, 0, 0);"> table</span><span style="color: rgb(0, 0, 255);">="user"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br />        </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">composite-id</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br />            </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">key-property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="name"</span><span style="color: rgb(255, 0, 0);"><br /><br />                          column</span><span style="color: rgb(0, 0, 255);">="name"</span><span style="color: rgb(255, 0, 0);"><br /><br />                          type</span><span style="color: rgb(0, 0, 255);">="java.lang.String"</span><span style="color: rgb(0, 0, 255);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br />            </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">key-property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="phone"</span><span style="color: rgb(255, 0, 0);"><br /><br />                          column</span><span style="color: rgb(0, 0, 255);">="phone"</span><span style="color: rgb(255, 0, 0);"><br /><br />                          type</span><span style="color: rgb(0, 0, 255);">="java.lang.String"</span><span style="color: rgb(0, 0, 255);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br />        </span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">composite-id</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br /> <br /><br />        </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="age"</span><span style="color: rgb(255, 0, 0);"> column</span><span style="color: rgb(0, 0, 255);">="age"</span><span style="color: rgb(255, 0, 0);"> type</span><span style="color: rgb(0, 0, 255);">="java.lang.Integer"</span><span style="color: rgb(0, 0, 255);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br />   <br /><br />    </span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">class</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br /></span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">hibernate-mapping</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /></span></div><br /><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">在储存数据方面，复合主键的储存没什么区别，现在的问题在于如何依据复合主键来查询数据，例如使用<span lang="EN-US">load()</span>方法，您可以创建一个<span lang="EN-US">User</span>实例，并设定复合主键对应的属性，接着再透过<span lang="EN-US">load()</span>查询对应的数据，例如：<span lang="EN-US"><o:p></o:p></span></span></p><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">User user </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> User();<br /><br />user.setName(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">bush</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br /><br />user.setPhone(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">0970123456</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br /><br />       <br /><br />Session session </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> sessionFactory.openSession();<br /><br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> 以实例设定复合主键并加载对应的数据</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"><br />user </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (User) session.load(User.</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">, user);<br /><br />       <br /><br />System.out.println(user.getAge() </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">\t</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"><br /><br />                                  user.getName() </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">\t</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"><br /><br />                                  user.getPhone());<br /><br />session.close();<br /><br /> <br /></span></div><br /><p class="MsoNormal"><span lang="EN-US"><o:p> </o:p></span></p><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">可以将主键的信息独立为一个类别，例如：<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="text-align: left;" align="left"><b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">UserPK.java</span></b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">package</span><span style="color: rgb(0, 0, 0);"> onlyfun.caterpillar;<br /><br /> <br /><br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.io.Serializable;<br /><br /> <br /><br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> org.apache.commons.lang.builder.EqualsBuilder;<br /><br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> org.apache.commons.lang.builder.HashCodeBuilder;<br /><br /> <br /><br /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> UserPK </span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);"> Serializable {<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> String name;<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> String phone;<br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> String getName() {<br /><br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> name;<br /><br />    }<br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> setName(String name) {<br /><br />        </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.name </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> name;<br /><br />    }<br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> String getPhone() {<br /><br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> phone;<br /><br />    }<br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> setPhone(String phone) {<br /><br />        </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.phone </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> phone;<br /><br />    }<br /><br />   <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">boolean</span><span style="color: rgb(0, 0, 0);"> equals(Object obj) {<br /><br />        </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(obj </span><span style="color: rgb(0, 0, 0);">==</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">) {<br /><br />            </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">true</span><span style="color: rgb(0, 0, 0);">;<br /><br />        }<br /><br />       <br /><br />        </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);">(</span><span style="color: rgb(0, 0, 0);">!</span><span style="color: rgb(0, 0, 0);">(obj </span><span style="color: rgb(0, 0, 255);">instanceof</span><span style="color: rgb(0, 0, 0);"> User)) {<br /><br />            </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);">;<br /><br />        }<br /><br />       <br /><br />        UserPK pk </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (UserPK) obj;<br /><br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> EqualsBuilder()<br /><br />                 .append(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.name, pk.getName())<br /><br />                 .append(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.phone, pk.getPhone())<br /><br />                 .isEquals();<br /><br />       <br /><br />    }<br /><br />   <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> hashCode() {<br /><br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> HashCodeBuilder()<br /><br />                 .append(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.name)<br /><br />                 .append(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.phone)<br /><br />                 .toHashCode();<br /><br />    }<br /><br />}<br /></span></div><br /><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">现在<span lang="EN-US">User</span>类别的主键信息被分离出来了，例如：<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="text-align: left;" align="left"><b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">User.java</span></b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">package</span><span style="color: rgb(0, 0, 0);"> onlyfun.caterpillar;<br /><br /> <br /><br /></span><span style="color: rgb(0, 0, 255);">import</span><span style="color: rgb(0, 0, 0);"> java.io.Serializable;<br /><br /> <br /><br /></span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> User </span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);"> Serializable {<br /><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> UserPK userPK; </span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> 主键</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> Integer age;<br /><br />   <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> User() {<br /><br />    }<br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> UserPK getUserPK() {<br /><br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> userPK;<br /><br />    }<br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> setUserPK(UserPK userPK) {<br /><br />        </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.userPK </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> userPK;<br /><br />    }<br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> Integer getAge() {<br /><br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> age;<br /><br />    }<br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> setAge(Integer age) {<br /><br />        </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.age </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> age;<br /><br />    }<br /><br />}<br /></span></div><br /><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">在映像文件方面，需要指定主键类的信息，例如：<span lang="EN-US"><o:p></o:p></span></span></p><p class="MsoNormal" style="text-align: left;" align="left"><b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">User.hbm.xml</span></b><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">&lt;?</span><span style="color: rgb(255, 0, 255);">xml version="1.0" encoding="utf-8"</span><span style="color: rgb(0, 0, 255);">?&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br /></span><span style="color: rgb(0, 0, 255);">&lt;!</span><span style="color: rgb(255, 0, 255);">DOCTYPE hibernate-mapping<br /><br />    PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"<br /><br />    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br /> <br /><br /></span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">hibernate-mapping</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br /> <br /><br />    </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">class </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="onlyfun.caterpillar.User"</span><span style="color: rgb(255, 0, 0);"> table</span><span style="color: rgb(0, 0, 255);">="user"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br />        </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">composite-id </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="userPK"</span><span style="color: rgb(255, 0, 0);"><br /><br />                      class</span><span style="color: rgb(0, 0, 255);">="onlyfun.caterpillar.UserPK"</span><span style="color: rgb(255, 0, 0);"><br /><br />                      unsaved-value</span><span style="color: rgb(0, 0, 255);">="any"</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br />            </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">key-property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="name"</span><span style="color: rgb(255, 0, 0);"><br /><br />                          column</span><span style="color: rgb(0, 0, 255);">="name"</span><span style="color: rgb(255, 0, 0);"><br /><br />                          type</span><span style="color: rgb(0, 0, 255);">="java.lang.String"</span><span style="color: rgb(0, 0, 255);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br />            </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">key-property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="phone"</span><span style="color: rgb(255, 0, 0);"><br /><br />                          column</span><span style="color: rgb(0, 0, 255);">="phone"</span><span style="color: rgb(255, 0, 0);"><br /><br />                          type</span><span style="color: rgb(0, 0, 255);">="java.lang.String"</span><span style="color: rgb(0, 0, 255);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br />        </span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">composite-id</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br />       <br /><br />        </span><span style="color: rgb(0, 0, 255);">&lt;</span><span style="color: rgb(128, 0, 0);">property </span><span style="color: rgb(255, 0, 0);">name</span><span style="color: rgb(0, 0, 255);">="age"</span><span style="color: rgb(255, 0, 0);"> column</span><span style="color: rgb(0, 0, 255);">="age"</span><span style="color: rgb(255, 0, 0);"> type</span><span style="color: rgb(0, 0, 255);">="java.lang.Integer"</span><span style="color: rgb(0, 0, 255);">/&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br />   <br /><br />    </span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">class</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /><br /> <br /><br /></span><span style="color: rgb(0, 0, 255);">&lt;/</span><span style="color: rgb(128, 0, 0);">hibernate-mapping</span><span style="color: rgb(0, 0, 255);">&gt;</span><span style="color: rgb(0, 0, 0);"><br /></span></div><br /><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p><p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">在查询数据时，必须指定主键信息，例如：<span lang="EN-US"><o:p></o:p></span></span></p><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">UserPK pk </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> UserPK();<br /><br />pk.setName(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">bush</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br /><br />pk.setPhone(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">0970123456</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">);<br /><br />      <br /><br />Session session </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> sessionFactory.openSession();<br /><br /></span><span style="color: rgb(0, 128, 0);">//</span><span style="color: rgb(0, 128, 0);"> 以主键类实例设定复合主键并加载对应的数据</span><span style="color: rgb(0, 128, 0);"><br /></span><span style="color: rgb(0, 0, 0);"><br />User user </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (User) session.load(User.</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">, pk);<br /><br />      <br /><br />System.out.println(user.getAge() </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">\t</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"><br /><br />                                  user.getUserPK().getName() </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">\t</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 0);">+</span><span style="color: rgb(0, 0, 0);"><br /><br />                                  user.getUserPK().getPhone());<br /><br />session.close();<br /><br /> <br /></span></div><br /><br />=================================================<br />再参考robbin的一篇文章<br /><a target="_blank" href="http://www.javaeye.com/topic/8287"><span style="color: rgb(0, 102, 153); font-weight: bold; font-size: 10pt;">一个简单的复合主键的做关联类的例子</span></a>   <br /><img src ="http://www.blogjava.net/alex/aggbug/80231.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/alex/" target="_blank">Alex</a> 2006-11-09 19:22 <a href="http://www.blogjava.net/alex/archive/2006/11/09/80231.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate的load错误，你碰到过这样的问题么?</title><link>http://www.blogjava.net/alex/archive/2006/11/07/79675.html</link><dc:creator>Alex</dc:creator><author>Alex</author><pubDate>Tue, 07 Nov 2006 11:28:00 GMT</pubDate><guid>http://www.blogjava.net/alex/archive/2006/11/07/79675.html</guid><wfw:comment>http://www.blogjava.net/alex/comments/79675.html</wfw:comment><comments>http://www.blogjava.net/alex/archive/2006/11/07/79675.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/alex/comments/commentRss/79675.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/alex/services/trackbacks/79675.html</trackback:ping><description><![CDATA[key words:hibernate,load,session.get,session.load()<br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);"> Parent </span><span style="color: rgb(0, 0, 255);">implements</span><span style="color: rgb(0, 0, 0);"> Serializable {<br /><br />    </span><span style="color: rgb(0, 128, 0);">/**</span><span style="color: rgb(0, 128, 0);"> identifier field </span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> Long id;<br /><br />    </span><span style="color: rgb(0, 128, 0);">/**</span><span style="color: rgb(0, 128, 0);"> persistent field </span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">private</span><span style="color: rgb(0, 0, 0);"> List childs;<br /><br />    </span><span style="color: rgb(0, 128, 0);">/**</span><span style="color: rgb(0, 128, 0);"> full constructor </span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> Parent(Long id, List childs) {<br />        </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.id </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> id;<br />        </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.childs </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> childs;<br />    }<br /><br />    </span><span style="color: rgb(0, 128, 0);">/**</span><span style="color: rgb(0, 128, 0);"> default constructor </span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> Parent() {<br />    }<br /><br />    </span><span style="color: rgb(0, 128, 0);">/**</span><span style="color: rgb(0, 128, 0);"> <br />     *            @hibernate.id<br />     *             generator-class="assigned"<br />     *             type="java.lang.Long"<br />     *             column="id"<br />     *<br />     </span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> Long getId() {<br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.id;<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> setId(Long id) {<br />        </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.id </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> id;<br />    }<br /><br />    </span><span style="color: rgb(0, 128, 0);">/**</span><span style="color: rgb(0, 128, 0);"><br />     *            @hibernate.set<br />     *             lazy="true"<br />     *             inverse="true"<br />     *             cascade="none"<br />     *            @hibernate.collection-key<br />     *             column="parent_id"<br />     *            @hibernate.collection-one-to-many<br />     *             class="net.foxlog.model.Child"<br />     *         <br />     </span><span style="color: rgb(0, 128, 0);">*/</span><span style="color: rgb(0, 0, 0);"><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> List getChilds() {<br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.childs;<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">void</span><span style="color: rgb(0, 0, 0);"> setChilds(List childs) {<br />        </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.childs </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> childs;<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> String toString() {<br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> ToStringBuilder(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">)<br />            .append(</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">id</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">, getId())<br />            .toString();<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">boolean</span><span style="color: rgb(0, 0, 0);"> equals(Object other) {<br />        </span><span style="color: rgb(0, 0, 255);">if</span><span style="color: rgb(0, 0, 0);"> ( </span><span style="color: rgb(0, 0, 0);">!</span><span style="color: rgb(0, 0, 0);">(other </span><span style="color: rgb(0, 0, 255);">instanceof</span><span style="color: rgb(0, 0, 0);"> Parent) ) </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">false</span><span style="color: rgb(0, 0, 0);">;<br />        Parent castOther </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (Parent) other;<br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> EqualsBuilder()<br />            .append(</span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.getId(), castOther.getId())<br />            .isEquals();<br />    }<br /><br />    </span><span style="color: rgb(0, 0, 255);">public</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">int</span><span style="color: rgb(0, 0, 0);"> hashCode() {<br />        </span><span style="color: rgb(0, 0, 255);">return</span><span style="color: rgb(0, 0, 0);"> </span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> HashCodeBuilder()<br />            .append(getId())<br />            .toHashCode();<br />    }<br /><br />}<br /></span></div><br /><br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">Parent parent </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (Parent)session.load(Parent.</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Integer(</span><span style="color: rgb(0, 0, 0);">7</span><span style="color: rgb(0, 0, 0);">));</span></div><br />运行提示出错，"can't get Entity.."<br /><br />知道是什么低级错误么?  其实很弱智的东西，但是不注意还就会出现，呵呵，答案如下:<br /><div style="border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; background-color: rgb(238, 238, 238); font-size: 13px; width: 98%;"><img id="Code_Closed_Image_192733" onclick="this.style.display='none'; Code_Closed_Text_192733.style.display='none'; Code_Open_Image_192733.style.display='inline'; Code_Open_Text_192733.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ContractedBlock.gif" align="top" height="16" width="11" /><img id="Code_Open_Image_192733" style="display: none;" onclick="this.style.display='none'; Code_Open_Text_192733.style.display='none'; Code_Closed_Image_192733.style.display='inline'; Code_Closed_Text_192733.style.display='inline';" src="http://www.blogjava.net/images/OutliningIndicators/ExpandedBlockStart.gif" align="top" height="16" width="11" /><span id="Code_Closed_Text_192733" style="border: 1px solid rgb(128, 128, 128); background-color: rgb(255, 255, 255);"></span><span id="Code_Open_Text_192733" style="display: none;"><br /><!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>--><span style="color: rgb(0, 0, 0);">Parent parent </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (Parent)session.load(Parent.</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">,</span><span style="color: rgb(0, 0, 255);">new</span><span style="color: rgb(0, 0, 0);"> Long(</span><span style="color: rgb(0, 0, 0);">7</span><span style="color: rgb(0, 0, 0);">))</span></span></div><br /><br /><img src ="http://www.blogjava.net/alex/aggbug/79675.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/alex/" target="_blank">Alex</a> 2006-11-07 19:28 <a href="http://www.blogjava.net/alex/archive/2006/11/07/79675.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[zt]hibernate二级缓存攻略</title><link>http://www.blogjava.net/alex/archive/2006/10/23/76750.html</link><dc:creator>Alex</dc:creator><author>Alex</author><pubDate>Mon, 23 Oct 2006 06:30:00 GMT</pubDate><guid>http://www.blogjava.net/alex/archive/2006/10/23/76750.html</guid><wfw:comment>http://www.blogjava.net/alex/comments/76750.html</wfw:comment><comments>http://www.blogjava.net/alex/archive/2006/10/23/76750.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/alex/comments/commentRss/76750.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/alex/services/trackbacks/76750.html</trackback:ping><description><![CDATA[转自 <a href="http://www.javaeye.com/topic/18904">javaEye</a><br /><p><br /></p><p>很多人对二级缓存都不太了解，或者是有错误的认识，我一直想写一篇文章介绍一下hibernate的二级缓存的，今天终于忍不住了。
<br />我的经验主要来自hibernate2.1版本，基本原理和3.0、3.1是一样的，请原谅我的顽固不化。</p><p>hibernate的session提供了一级缓存，每个session，对同一个id进行两次load，不会发送两条sql给数据库，但是session关闭的时候，一级缓存就失效了。</p><p>二级缓存是SessionFactory级别的全局缓存，它底下可以使用不同的缓存类库，比如ehcache、oscache等，需要设置hibernate.cache.provider_class，我们这里用ehcache，在2.1中就是
<br />hibernate.cache.provider_class=net.sf.hibernate.cache.EhCacheProvider
<br />如果使用查询缓存，加上
<br />hibernate.cache.use_query_cache=true</p><p>缓存可以简单的看成一个Map，通过key在缓存里面找value。</p><p><b>Class的缓存</b><br />对于一条记录，也就是一个PO来说，是根据ID来找的，缓存的key就是ID，value是POJO。无论list，load还是
iterate，只要读出一个对象，都会填充缓存。但是list不会使用缓存，而iterate会先取数据库select
id出来，然后一个id一个id的load，如果在缓存里面有，就从缓存取，没有的话就去数据库load。假设是读写缓存，需要设置：
<br />&lt;cache usage="read-write"/&gt;
<br />如果你使用的二级缓存实现是ehcache的话，需要配置ehcache.xml
<br />&lt;cache name="com.xxx.pojo.Foo" maxElementsInMemory="500"
eternal="false" timeToLiveSeconds="7200" timeToIdleSeconds="3600"
overflowToDisk="true" /&gt;
<br />其中eternal表示缓存是不是永远不超时，timeToLiveSeconds是缓存中每个元素（这里也就是一个POJO）的超时时间，如
果eternal="false"，超过指定的时间，这个元素就被移走了。timeToIdleSeconds是发呆时间，是可选的。当往缓存里面put
的元素超过500个时，如果overflowToDisk="true"，就会把缓存中的部分数据保存在硬盘上的临时文件里面。
<br />每个需要缓存的class都要这样配置。如果你没有配置，hibernate会在启动的时候警告你，然后使用defaultCache的配置，这样多个class会共享一个配置。
<br />当某个ID通过hibernate修改时，hibernate会知道，于是移除缓存。
<br />这样大家可能会想，同样的查询条件，第一次先list，第二次再iterate，就可以使用到缓存了。实际上这是很难的，因为你无法判断什么时候
是第一次，而且每次查询的条件通常是不一样的，假如数据库里面有100条记录，id从1到100，第一次list的时候出了前50个id，第二次
iterate的时候却查询到30至70号id，那么30-50是从缓存里面取的，51到70是从数据库取的，共发送1+20条sql。所以我一直认为
iterate没有什么用，总是会有1+N的问题。
<br />（题外话：有说法说大型查询用list会把整个结果集装入内存，很慢，而iterate只select
id比较好，但是大型查询总是要分页查的，谁也不会真的把整个结果集装进来，假如一页20条的话，iterate共需要执行21条语句，list虽然选择
若干字段，比iterate第一条select
id语句慢一些，但只有一条语句，不装入整个结果集hibernate还会根据数据库方言做优化，比如使用mysql的limit，整体看来应该还是
list快。）
<br />如果想要对list或者iterate查询的结果缓存，就要用到查询缓存了</p><p><b>查询缓存</b><br />首先需要配置hibernate.cache.use_query_cache=true
<br />如果用ehcache，配置ehcache.xml，注意hibernate3.0以后不是net.sf的包名了
<br />&lt;cache name="net.sf.hibernate.cache.StandardQueryCache" 
<br />   maxElementsInMemory="50" eternal="false" timeToIdleSeconds="3600" 
<br />   timeToLiveSeconds="7200" overflowToDisk="true"/&gt;
<br />&lt;cache name="net.sf.hibernate.cache.UpdateTimestampsCache" 
<br />   maxElementsInMemory="5000" eternal="true" overflowToDisk="true"/&gt;
<br />然后
<br />query.setCacheable(true);//激活查询缓存
<br />query.setCacheRegion("myCacheRegion");//指定要使用的cacheRegion，可选
<br />第二行指定要使用的cacheRegion是myCacheRegion，即你可以给每个查询缓存做一个单独的配置，使用setCacheRegion来做这个指定，需要在ehcache.xml里面配置它：
<br />&lt;cache name="myCacheRegion" maxElementsInMemory="10"
eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200"
overflowToDisk="true" /&gt;
<br />如果省略第二行，不设置cacheRegion的话，那么会使用上面提到的标准查询缓存的配置，也就是net.sf.hibernate.cache.StandardQueryCache</p><p>对于查询缓存来说，缓存的key是根据hql生成的sql，再加上参数，分页等信息（可以通过日志输出看到，不过它的输出不是很可读，最好改一下它的代码）。
<br />比如hql：
<br />from Cat c where c.name like ?
<br />生成大致如下的sql：
<br />select * from cat c where c.name like ?
<br />参数是"tiger%"，那么查询缓存的key*大约*是这样的字符串（我是凭记忆写的，并不精确，不过看了也该明白了）：
<br />select * from cat c where c.name like ? , parameter:tiger%
<br />这样，保证了同样的查询、同样的参数等条件下具有一样的key。
<br />现在说说缓存的value，如果是list方式的话，value在这里并不是整个结果集，而是查询出来的这一串ID。也就是说，不管是list方
法还是iterate方法，第一次查询的时候，它们的查询方式很它们平时的方式是一样的，list执行一条sql，iterate执行1+N条，多出来的
行为是它们填充了缓存。但是到同样条件第二次查询的时候，就都和iterate的行为一样了，根据缓存的key去缓存里面查到了value，value是
一串id，然后在到class的缓存里面去一个一个的load出来。这样做是为了节约内存。
<br />可以看出来，查询缓存需要打开相关类的class缓存。list和iterate方法第一次执行的时候，都是既填充查询缓存又填充class缓存的。
<br /><b>这里还有一个很容易被忽视的重要问题，即打开查询缓存以后，即使是list方法也可能遇到1+N的问题！</b>相同条件第一次list的
时候，因为查询缓存中找不到，不管class缓存是否存在数据，总是发送一条sql语句到数据库获取全部数据，然后填充查询缓存和class缓存。但是第
二次执行的时候，问题就来了，如果你的class缓存的超时时间比较短，现在class缓存都超时了，但是查询缓存还在，那么list方法在获取id串以
后，将会一个一个去数据库load！因此，class缓存的超时时间一定不能短于查询缓存设置的超时时间！如果还设置了发呆时间的话，保证class缓存
的发呆时间也大于查询的缓存的生存时间。这里还有其他情况，比如class缓存被程序强制evict了，这种情况就请自己注意了。</p><p>另外，如果hql查询包含select字句，那么查询缓存里面的value就是整个结果集了。</p><p>当hibernate更新数据库的时候，它怎么知道更新哪些查询缓存呢？
<br />hibernate在一个地方维护每个表的最后更新时间，其实也就是放在上面net.sf.hibernate.cache.UpdateTimestampsCache所指定的缓存配置里面。
<br />当通过hibernate更新的时候，hibernate会知道这次更新影响了哪些表。然后它更新这些表的最后更新时间。每个缓存都有一个生成时
间和这个缓存所查询的表，当hibernate查询一个缓存是否存在的时候，如果缓存存在，它还要取出缓存的生成时间和这个缓存所查询的表，然后去查找这
些表的最后更新时间，如果有一个表在生成时间后更新过了，那么这个缓存是无效的。
<br />可以看出，只要更新过一个表，那么凡是涉及到这个表的查询缓存就失效了，因此查询缓存的命中率可能会比较低。</p><p><b>Collection缓存</b><br />需要在hbm的collection里面设置
<br />&lt;cache usage="read-write"/&gt;
<br />假如class是Cat，collection叫children，那么ehcache里面配置
<br />&lt;cache name="com.xxx.pojo.Cat.children" 
<br />   maxElementsInMemory="20" eternal="false" timeToIdleSeconds="3600" timeToLiveSeconds="7200" 
<br />   overflowToDisk="true" /&gt;
<br />Collection的缓存和前面查询缓存的list一样，也是只保持一串id，但它不会因为这个表更新过就失效，一个collection缓存仅在这个collection里面的元素有增删时才失效。
<br />这样有一个问题，如果你的collection是根据某个字段排序的，当其中一个元素更新了该字段时，导致顺序改变时，collection缓存里面的顺序没有做更新。</p><p><b>缓存策略</b><br />只读缓存（read-only）：没有什么好说的
<br />读/写缓存（read-write）:程序可能要的更新数据
<br />不严格的读/写缓存（nonstrict-read-write）：需要更新数据，但是两个事务更新同一条记录的可能性很小，性能比读写缓存好
<br />事务缓存（transactional）：缓存支持事务，发生异常的时候，缓存也能够回滚，只支持jta环境，这个我没有怎么研究过</p><p>读写缓存和不严格读写缓存在实现上的区别在于，读写缓存更新缓存的时候会把缓存里面的数据换成一个锁，其他事务如果去取相应的缓存数据，发现被锁住了，然后就直接取数据库查询。
<br />在hibernate2.1的ehcache实现中，如果锁住部分缓存的事务发生了异常，那么缓存会一直被锁住，直到60秒后超时。
<br />不严格读写缓存不锁定缓存中的数据。</p><p><b>使用二级缓存的前置条件</b><br />你的hibernate程序对数据库有独占的写访问权，其他的进程更新了数据库，hibernate是不可能知道的。你操作数据库必需直接通过
hibernate，如果你调用存储过程，或者自己使用jdbc更新数据库，hibernate也是不知道的。hibernate3.0的大批量更新和删
除是不更新二级缓存的，但是据说3.1已经解决了这个问题。
<br />这个限制相当的棘手，有时候hibernate做批量更新、删除很慢，但是你却不能自己写jdbc来优化，很郁闷吧。
<br />SessionFactory也提供了移除缓存的方法，你一定要自己写一些JDBC的话，可以调用这些方法移除缓存，这些方法是：
<br /> void evict(Class persistentClass)
<br />          Evict all entries from the second-level cache.
<br /> void evict(Class persistentClass, Serializable id)
<br />          Evict an entry from the second-level cache.
<br /> void evictCollection(String roleName)
<br />          Evict all entries from the second-level cache.
<br /> void evictCollection(String roleName, Serializable id)
<br />          Evict an entry from the second-level cache.
<br /> void evictQueries()
<br />          Evict any query result sets cached in the default query cache region.
<br /> void evictQueries(String cacheRegion)
<br />          Evict any query result sets cached in the named query cache region.
<br />不过我不建议这样做，因为这样很难维护。比如你现在用JDBC批量更新了某个表，有3个查询缓存会用到这个表，用evictQueries
(String cacheRegion)移除了3个查询缓存，然后用evict(Class
persistentClass)移除了class缓存，看上去好像完整了。不过哪天你添加了一个相关查询缓存，可能会忘记更新这里的移除代码。如果你的
jdbc代码到处都是，在你添加一个查询缓存的时候，还知道其他什么地方也要做相应的改动吗？</p><p>----------------------------------------------------</p><p><b>总结：</b><br />不要想当然的以为缓存一定能提高性能，仅仅在你能够驾驭它并且条件合适的情况下才是这样的。hibernate的二级缓存限制还是比较多的，不方便用jdbc可能会大大的降低更新性能。在不了解原理的情况下乱用，可能会有1+N的问题。不当的使用还可能导致读出脏数据。
<br />如果受不了hibernate的诸多限制，那么还是自己在应用程序的层面上做缓存吧。
<br />在越高的层面上做缓存，效果就会越好。就好像尽管磁盘有缓存，数据库还是要实现自己的缓存，尽管数据库有缓存，咱们的应用程序还是要做缓存。因为
底层的缓存它并不知道高层要用这些数据干什么，只能做的比较通用，而高层可以有针对性的实现缓存，所以在更高的级别上做缓存，效果也要好些吧。</p><p>终于写完了，好累……</p><img src ="http://www.blogjava.net/alex/aggbug/76750.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/alex/" target="_blank">Alex</a> 2006-10-23 14:30 <a href="http://www.blogjava.net/alex/archive/2006/10/23/76750.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>