﻿<?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-黑灵客栈-随笔分类-ORM</title><link>http://www.blogjava.net/mstar/category/1162.html</link><description>搞软件开发就像被强奸,如果不能反抗,就享受它吧！</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 18:33:49 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 18:33:49 GMT</pubDate><ttl>60</ttl><item><title>Hibernate3中取得多层数据的所产生的n+1 selects问题的解决。</title><link>http://www.blogjava.net/mstar/archive/2005/09/30/14477.html</link><dc:creator>黑灵</dc:creator><author>黑灵</author><pubDate>Fri, 30 Sep 2005 01:12:00 GMT</pubDate><guid>http://www.blogjava.net/mstar/archive/2005/09/30/14477.html</guid><wfw:comment>http://www.blogjava.net/mstar/comments/14477.html</wfw:comment><comments>http://www.blogjava.net/mstar/archive/2005/09/30/14477.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.blogjava.net/mstar/comments/commentRss/14477.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mstar/services/trackbacks/14477.html</trackback:ping><description><![CDATA[其实这个问题在Hibernate in Action中已经有很多种解决办法了。但我觉得其中最好的办法是用Criteria的FetchMode来解决，但是Hibernate in Action中写的很不详细。我昨晚试了好长时间来的到答案。下面总结一下。<BR>需求这样的，我有四张表（one,two,three,four）从one一直外键关联到four。结构如下<BR><IMG height=296 alt=hibernatefetch.jpg src="http://www.blogjava.net/images/blogjava_net/mstar/pics20050930/hibernatefetch.jpg" width=502 border=0><BR>现在在Session中得到One，并从One里一直取到Four里的内容。如果简单的用Session.get来实现是这样的。<BR>
<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: #000000">One&nbsp;one&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(One)session.get(One.</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Integer(</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;iterone&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;one.getTwos().iterator();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">while</SPAN><SPAN style="COLOR: #000000">(iterone.hasNext()){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Two&nbsp;two&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(Two)&nbsp;iterone.next();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Iterator&nbsp;itertwo&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;two.getThrees().iterator();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">while</SPAN><SPAN style="COLOR: #000000">(itertwo.hasNext()){<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Three&nbsp;three&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(Three)&nbsp;itertwo.next();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;three.getFours().size();&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;}<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</SPAN></DIV>这样我在Session关闭后返回的One里是从One到Four的信息都有的。<BR>然而这样做所导致的结果是生成大量的SQL查询，这是一个典型的n+1 Selects问题。如果系统结构层次多，符合条件的记录多，那么Hibernate为你生成的SQL查询将是难以接受的。<BR>对于这个例子生成的SQL是这样的<BR>Hibernate: select one0_.c_one_id as c1_0_, one0_.c_one_text as c2_3_0_ from One one0_ where one0_.c_one_id=?<BR>Hibernate: select twos0_.c_one_id as c2_1_, twos0_.c_two_id as c1_1_, twos0_.c_two_id as c1_0_, twos0_.c_one_id as c2_2_0_, twos0_.c_two_text as c3_2_0_ from Two twos0_ where twos0_.c_one_id=?<BR>Hibernate: select threes0_.c_two_id as c2_1_, threes0_.c_three_id as c1_1_, threes0_.c_three_id as c1_0_, threes0_.c_two_id as c2_1_0_, threes0_.c_three_text as c3_1_0_ from Three threes0_ where threes0_.c_two_id=?<BR>Hibernate: select fours0_.c_three_id as c2_1_, fours0_.c_four_id as c1_1_, fours0_.c_four_id as c1_0_, fours0_.c_three_id as c2_0_0_, fours0_.c_four_text as c3_0_0_ from Four fours0_ where fours0_.c_three_id=?<BR>Hibernate: select fours0_.c_three_id as c2_1_, fours0_.c_four_id as c1_1_, fours0_.c_four_id as c1_0_, fours0_.c_three_id as c2_0_0_, fours0_.c_four_text as c3_0_0_ from Four fours0_ where fours0_.c_three_id=?<BR>Hibernate: select threes0_.c_two_id as c2_1_, threes0_.c_three_id as c1_1_, threes0_.c_three_id as c1_0_, threes0_.c_two_id as c2_1_0_, threes0_.c_three_text as c3_1_0_ from Three threes0_ where threes0_.c_two_id=?<BR>Hibernate: select fours0_.c_three_id as c2_1_, fours0_.c_four_id as c1_1_, fours0_.c_four_id as c1_0_, fours0_.c_three_id as c2_0_0_, fours0_.c_four_text as c3_0_0_ from Four fours0_ where fours0_.c_three_id=?<BR>Hibernate: select fours0_.c_three_id as c2_1_, fours0_.c_four_id as c1_1_, fours0_.c_four_id as c1_0_, fours0_.c_three_id as c2_0_0_, fours0_.c_four_text as c3_0_0_ from Four fours0_ where fours0_.c_three_id=?<BR>对于这样的问题，在没有Hibernate以前我们一般都用jdbc来做，那样的话我们其实用一个进行3次join的sql语句就可以实现，但是这样解决也有问题，就是返回的ResultSet中的数据非常多，而且杂乱，其实是从one到four平行排列的。对于这样的结果集我们要把它手动影射曾对象结构也是一个很复杂的操作。<BR>幸好Hibernate3可以为我们做这些事情(我再一次被Hibernate的强大所震撼)。<BR>上面的实现可以用Criteria来实现：<BR>
<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: #000000">session&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;sessionFactory.openSession();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Criteria&nbsp;criteria&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;session.createCriteria(One.</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;criteria.add(Expression.eq(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">COneId</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;Integer(</SPAN><SPAN style="COLOR: #000000">1</SPAN><SPAN style="COLOR: #000000">)));<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;one&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(One)criteria.setFetchMode(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">twos</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,FetchMode.JOIN).setFetchMode(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">twos.threes</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,FetchMode.JOIN).setFetchMode(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">twos.threes.fours</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,FetchMode.JOIN).uniqueResult();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.close();</SPAN></DIV>
<P>这里的重点是这句话criteria.setFetchMode(<SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">twos</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,FetchMode.JOIN).setFetchMode(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">twos.threes</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,FetchMode.JOIN).setFetchMode(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">twos.threes.fours</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,FetchMode.JOIN).uniqueResult();<BR>在用Criteria之前先设置FetchMode，应为Criteria是动态生成sql语句的，所以生成的sql就是一层层Join下去的。<BR>setFetchMode（String，Mode）第一个参数是association path，用"."来表示路径。这一点具体的例子很少，文档也没有写清楚。我也是试了很久才试出来的。<BR>就这个例子来所把因为取道第四层，所以要进行三次setFetchMode<BR>第一次的路径是twos，一位one中有two的Set。这个具体要更具hbm.xml的配置来定。<BR>第二个路径就是twos.threes<BR>第三个就是twos.threes.fours<BR>一次类推，一层层增加的。<BR>这样做法最终生成的SQL是这样的：<BR>Hibernate: select this_.c_one_id as c1_3_, this_.c_one_text as c2_3_3_, twos2_.c_one_id as c2_5_, twos2_.c_two_id as c1_5_, twos2_.c_two_id as c1_0_, twos2_.c_one_id as c2_2_0_, twos2_.c_two_text as c3_2_0_, threes3_.c_two_id as c2_6_, threes3_.c_three_id as c1_6_, threes3_.c_three_id as c1_1_, threes3_.c_two_id as c2_1_1_, threes3_.c_three_text as c3_1_1_, fours4_.c_three_id as c2_7_, fours4_.c_four_id as c1_7_, fours4_.c_four_id as c1_2_, fours4_.c_three_id as c2_0_2_, fours4_.c_four_text as c3_0_2_ from One this_ left outer join Two twos2_ on this_.c_one_id=twos2_.c_one_id left outer join Three threes3_ on twos2_.c_two_id=threes3_.c_two_id left outer join Four fours4_ on threes3_.c_three_id=fours4_.c_three_id where this_.c_one_id=?<BR>虽然很长但是只有一条SQL语句。性能要好很多。Hibernate的强大之处是它会把返回的ResultSet自动影射到你的对象模型里面去。这就为我们省了很多事。<BR><BR>看来Hibernate真是一个耐人寻味的Framework啊。<BR></SPAN><SPAN style="COLOR: #000000"><BR>源码，没什么东西。<BR><A href="http://www.blogjava.net/mstar/Files/mstar/HiberFetch2.rar">http://www.blogjava.net/Files/mstar/HiberFetch2.rar</A></P></SPAN><img src ="http://www.blogjava.net/mstar/aggbug/14477.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mstar/" target="_blank">黑灵</a> 2005-09-30 09:12 <a href="http://www.blogjava.net/mstar/archive/2005/09/30/14477.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate3中的更新与删除</title><link>http://www.blogjava.net/mstar/archive/2005/09/15/13130.html</link><dc:creator>黑灵</dc:creator><author>黑灵</author><pubDate>Thu, 15 Sep 2005 15:52:00 GMT</pubDate><guid>http://www.blogjava.net/mstar/archive/2005/09/15/13130.html</guid><wfw:comment>http://www.blogjava.net/mstar/comments/13130.html</wfw:comment><comments>http://www.blogjava.net/mstar/archive/2005/09/15/13130.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mstar/comments/commentRss/13130.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mstar/services/trackbacks/13130.html</trackback:ping><description><![CDATA[在Hibernate2中对某个表进行更新和删除，必须先把它Load出来，在后更改，然后再保存。<BR>这个过程对于批量操作或者对于表关系比较复杂的情况，是很复杂的。<BR>在Hibernate3中HQL语句中已经支持update 和delete 了<BR>但是要注意的是update和delete的HQL不是面向对象的了。你用对象方式的语句返回会出错。<BR>下面是一个简单的例子。<BR>用对象的方式，不用HQL：<BR>
<DIV style="BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #000 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #000 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session&nbsp;session&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;getSession();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Customer&nbsp;host&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(Customer)&nbsp;session.load(Customer.</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">,hostEmail);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Customer&nbsp;guest&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(Customer)session.load(Customer.</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">,guestEmail);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ContactId&nbsp;id</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">new</SPAN><SPAN style="COLOR: #000000">&nbsp;ContactId(host,guest);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Contact&nbsp;contact&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(Contact)<FONT size=3>session</FONT>.load(Contact.</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">,id);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;RelationShip&nbsp;relation&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;(RelationShip)session.load(RelationShip.</SPAN><SPAN style="COLOR: #0000ff">class</SPAN><SPAN style="COLOR: #000000">,&nbsp;</SPAN><SPAN style="COLOR: #000000">2</SPAN><SPAN style="COLOR: #000000">);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;contact.setRelationShip(relation);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;contact.setUpdateTime(Calendar.getInstance().getTime());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.flush();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.close();</SPAN></DIV>用HQL：<BR>
<DIV style="BORDER-RIGHT: #000 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: #000 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: #000 1px solid; WIDTH: 98%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: #000 1px solid; BACKGROUND-COLOR: #eeeeee"><SPAN style="COLOR: #000000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</SPAN><SPAN style="COLOR: #0000ff">private</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">static</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #0000ff">final</SPAN><SPAN style="COLOR: #000000">&nbsp;String&nbsp;HQL_BADGUY_TO_FRIEND&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">update&nbsp;Contact&nbsp;set&nbsp;relation_id&nbsp;=&nbsp;1,&nbsp;updateTime&nbsp;=&nbsp;:updateTime&nbsp;where&nbsp;host&nbsp;=&nbsp;:hostEmail&nbsp;and&nbsp;guest&nbsp;=&nbsp;:guestEmail</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">;<BR><BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Session&nbsp;session&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;getSession();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Query&nbsp;query&nbsp;</SPAN><SPAN style="COLOR: #000000">=</SPAN><SPAN style="COLOR: #000000">&nbsp;session.createQuery(HQL_BADGUY_TO_FRIEND);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setString(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">hostEmail</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,hostEmail);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setString(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">guestEmail</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,guestEmail);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.setDate(</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">updateTime</SPAN><SPAN style="COLOR: #000000">"</SPAN><SPAN style="COLOR: #000000">,Calendar.getInstance().getTime());<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;query.executeUpdate();<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;session.close();</SPAN></DIV>如果你把HQL写成这个样子：<BR>update Contact as c set c.relationShip.relationId =1 ......<BR>反而会出错，也就是说，你就按照native SQL去写就行了。<BR>还有，如果能使用这样的功能<BR><STRONG>hibernate.query.factory_class&nbsp;&nbsp;= &nbsp;org.hibernate.hql.classic.ClassicQueryTranslatorFactory</STRONG><BR>这个Hibernate配置属性要不去掉，要不换成<STRONG>org.hibernate.hql.ast.ASTQueryTranslatorFactory</STRONG><BR>上面那个是支持Hibernate2的。<BR>但是有一点要注意，如果你用update语句来做的话，可能产生缓存同步问题，而且两种方法最后Hibernate执行的语句差不多，对于第一种方法Hibernate也是就生成一条update语句，当然因为我是根据主键来update的，如果批量处理的话还是用Update HQL快。<BR><img src ="http://www.blogjava.net/mstar/aggbug/13130.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mstar/" target="_blank">黑灵</a> 2005-09-15 23:52 <a href="http://www.blogjava.net/mstar/archive/2005/09/15/13130.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Could not initialize proxy - the owning Session was closed</title><link>http://www.blogjava.net/mstar/archive/2005/09/05/12125.html</link><dc:creator>黑灵</dc:creator><author>黑灵</author><pubDate>Mon, 05 Sep 2005 15:57:00 GMT</pubDate><guid>http://www.blogjava.net/mstar/archive/2005/09/05/12125.html</guid><wfw:comment>http://www.blogjava.net/mstar/comments/12125.html</wfw:comment><comments>http://www.blogjava.net/mstar/archive/2005/09/05/12125.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/mstar/comments/commentRss/12125.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mstar/services/trackbacks/12125.html</trackback:ping><description><![CDATA[<FONT color=#000000>Hibernate类的initialize()静态方法用于在Session范围内显式初始化代理类实例，isInitialized()方法用于判断代理类实例是否已经被初始化。例如： </FONT>
<P><FONT color=#000000><SPAN style="COLOR: #003366">tx = session.beginTransaction(); <BR>Customer customer=(Customer)session.load(Customer.class,new Long(1)); <BR>if(!Hibernate.isInitialized(customer)) <BR>Hibernate.initialize(customer); <BR>tx.commit(); <BR>session.close(); <BR>customer.getName();</SPAN> </FONT></P>
<P><SPAN style="COLOR: #003366"><FONT color=#000000>以上代码在Session范围内通过Hibernate类的initialize()方法显式初始化了Customer代理类实例，因此当Session关闭后，可以正常访问Customer游离对象。</FONT></SPAN></P><img src ="http://www.blogjava.net/mstar/aggbug/12125.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mstar/" target="_blank">黑灵</a> 2005-09-05 23:57 <a href="http://www.blogjava.net/mstar/archive/2005/09/05/12125.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>iBatis实战小结！</title><link>http://www.blogjava.net/mstar/archive/2005/08/23/10790.html</link><dc:creator>黑灵</dc:creator><author>黑灵</author><pubDate>Tue, 23 Aug 2005 05:59:00 GMT</pubDate><guid>http://www.blogjava.net/mstar/archive/2005/08/23/10790.html</guid><wfw:comment>http://www.blogjava.net/mstar/comments/10790.html</wfw:comment><comments>http://www.blogjava.net/mstar/archive/2005/08/23/10790.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mstar/comments/commentRss/10790.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mstar/services/trackbacks/10790.html</trackback:ping><description><![CDATA[<P><FONT color=#000000>头一次在项目中用iBatis，以前用过Hibernate所以接受起来比较快，但是iBatis和Hibernate在细节上还是有很多不同之处的。<BR>在这篇文章里，我主要总结iBatis中一些容易产生莫名其妙的错误的地方。<BR>一、<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iBatis会对你写在xml中的sql语句进行优化。它不是傻傻的按照你写的东西原封不动的执行。在这里我目前只发现了一点对于你的resultClass中没有的属性，即便是你写在select语句中有这个属性，它在执行的实现也会去掉。返回的ResultSet中是没有的。<BR>二、<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;写在sql-map-config.xml里面的那些sqlMap的顺序不是随便怎么样都可以的。对于的A-sqlMap要用到B-sqlMap中定义的东西的时候，A一定要写在B前面。不然会报错，说你B中有些什么东西找不到定义。<BR>三、<BR>&lt;insert id="..." parameterClass="..."&gt;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;selectKey resultClass="..." keyProperty="..." &gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; select&nbsp;....<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/selectKey&gt;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.....<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.....<BR>&lt;/insert&gt;<BR>这是主动生成主键编号并执行插入的方法。在使用这个方法的时候，你的parameterClass中一定要有与keyProperty对应的属性，这样ibatis会把select出来的编号放回parameterClass中，然后再执行insert操作。<BR>四、<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sqlMap中的定义是全局的，尽量不要出现重复的定义，如typeAlias，sql-id等等。</FONT></P><img src ="http://www.blogjava.net/mstar/aggbug/10790.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mstar/" target="_blank">黑灵</a> 2005-08-23 13:59 <a href="http://www.blogjava.net/mstar/archive/2005/08/23/10790.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个困扰了我好几天的Hibernate+Spring的问题，算是解决了吧！</title><link>http://www.blogjava.net/mstar/archive/2005/06/02/5485.html</link><dc:creator>黑灵</dc:creator><author>黑灵</author><pubDate>Thu, 02 Jun 2005 13:32:00 GMT</pubDate><guid>http://www.blogjava.net/mstar/archive/2005/06/02/5485.html</guid><wfw:comment>http://www.blogjava.net/mstar/comments/5485.html</wfw:comment><comments>http://www.blogjava.net/mstar/archive/2005/06/02/5485.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.blogjava.net/mstar/comments/commentRss/5485.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mstar/services/trackbacks/5485.html</trackback:ping><description><![CDATA[String hql = "from TradeRecord as tr where tr.TradeTime&gt;= :startTime&nbsp;and tr.TradeTime &lt;= :endTime and tr.CustomerId =:cid";<BR>&nbsp;&nbsp;String[] params = { "startTime", "endTime", "cid" };<BR>&nbsp;&nbsp;Object[] args = { startTime, endTime, new Long(cid) };<BR>&nbsp;List list= this.getHibernateTemplate().findByNamedParam(hql,params,args);<BR>这是你调用list中的对象的get方法，如果这个get方法需要lazy load，你将看到如下异常：<BR>&nbsp;ERROR LazyInitializationException:19 - could not initialize proxy - the owning Session was closed<BR><BR>这个问题困扰的我都要跳楼了。<BR><BR>现在这样就可以了：<BR>Session session = this.getSession();<BR>&nbsp;&nbsp;String hql = "from TradeRecord as tr where tr.TradeTime&gt;= :startTime "<BR>&nbsp;&nbsp;&nbsp;&nbsp;+ "and tr.TradeTime &lt;= :endTime and tr.CustomerId =:cid";<BR>&nbsp;&nbsp;String[] params = { "startTime", "endTime", "cid" };<BR>&nbsp;&nbsp;Object[] args = { startTime, endTime, new Long(cid) };<BR>&nbsp;&nbsp;Query query = session.createQuery(hql);<BR>&nbsp;&nbsp;query.setDate("startTime",startTime);<BR>&nbsp;&nbsp;query.setDate("endTime",endTime);<BR>&nbsp;&nbsp;query.setLong("cid", cid);<BR>&nbsp;&nbsp;List list = query.list();<BR><BR>也就是说，调用HibernateTemplate的findByNamedParam方法，他在执行完以后会把session自动关掉。<BR><BR>我现在在找源码看个究竟。<BR><BR>这个问题虽然解决了，但是并不值得高兴，因为我发现hibernate执行的SQL语句要比我用JDBC写的sql语句多很多。我很怀疑hibernate的效率。<img src ="http://www.blogjava.net/mstar/aggbug/5485.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mstar/" target="_blank">黑灵</a> 2005-06-02 21:32 <a href="http://www.blogjava.net/mstar/archive/2005/06/02/5485.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>对于昨天User -- Friend关系的解决！</title><link>http://www.blogjava.net/mstar/archive/2005/04/28/3888.html</link><dc:creator>黑灵</dc:creator><author>黑灵</author><pubDate>Thu, 28 Apr 2005 06:00:00 GMT</pubDate><guid>http://www.blogjava.net/mstar/archive/2005/04/28/3888.html</guid><wfw:comment>http://www.blogjava.net/mstar/comments/3888.html</wfw:comment><comments>http://www.blogjava.net/mstar/archive/2005/04/28/3888.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mstar/comments/commentRss/3888.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mstar/services/trackbacks/3888.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 昨天在回复中我写了一个别人给我的解决方案。这种方法简单，但是在数据库的结构上不时很好。我自己也找了一个方法，但是比较麻烦。从数据库底层做起，原来我的数据库设计有问题。我在用PowerDesigner建立概念模型的时候有一定问题。对于Friend表我用的是Entity，其实这个关系不应该是Entity，而应该是Association。如下图：这样在生成物理数据模型时就会把 host，friend一起...&nbsp;&nbsp;<a href='http://www.blogjava.net/mstar/archive/2005/04/28/3888.html'>阅读全文</a><img src ="http://www.blogjava.net/mstar/aggbug/3888.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mstar/" target="_blank">黑灵</a> 2005-04-28 14:00 <a href="http://www.blogjava.net/mstar/archive/2005/04/28/3888.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>这样的表结构Hibernate映射应该是什么样子？ </title><link>http://www.blogjava.net/mstar/archive/2005/04/27/3869.html</link><dc:creator>黑灵</dc:creator><author>黑灵</author><pubDate>Wed, 27 Apr 2005 14:33:00 GMT</pubDate><guid>http://www.blogjava.net/mstar/archive/2005/04/27/3869.html</guid><wfw:comment>http://www.blogjava.net/mstar/comments/3869.html</wfw:comment><comments>http://www.blogjava.net/mstar/archive/2005/04/27/3869.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/mstar/comments/commentRss/3869.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mstar/services/trackbacks/3869.html</trackback:ping><description><![CDATA[<P>一个User表存放用户信息，一个好友表存放好友关系。<BR>好友表有两个字段，一个是host，一个是friend，这两个字段都是User表中userid的外键。</P>
<P>我在用工具生成代码时总是有问题。几乎所有工具都试过了，所以我决定自己写。但我也明白该怎么写？是不是这个好友表不应该有映射文件和java类啊？如果是，那么在User表中的映射文件应该怎么写呢？<BR></P><img src ="http://www.blogjava.net/mstar/aggbug/3869.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mstar/" target="_blank">黑灵</a> 2005-04-27 22:33 <a href="http://www.blogjava.net/mstar/archive/2005/04/27/3869.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate用Mysql的中文问题</title><link>http://www.blogjava.net/mstar/archive/2005/04/27/3849.html</link><dc:creator>黑灵</dc:creator><author>黑灵</author><pubDate>Wed, 27 Apr 2005 07:48:00 GMT</pubDate><guid>http://www.blogjava.net/mstar/archive/2005/04/27/3849.html</guid><wfw:comment>http://www.blogjava.net/mstar/comments/3849.html</wfw:comment><comments>http://www.blogjava.net/mstar/archive/2005/04/27/3849.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mstar/comments/commentRss/3849.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mstar/services/trackbacks/3849.html</trackback:ping><description><![CDATA[<P>hibernate.cfg.xml在&lt;session-factory&gt;和&lt;/session-factory&gt;之间加入这么一段：&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="connection.useUnicode"&gt;true&lt;/property&gt; <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;property name="connection.characterEncoding"&gt;UTF-8&lt;/property&gt;<BR><BR>这样一来，是可以解决乱码问题。<BR>但是如果你用一些数据库管理器，看见的中文数据都是乱码！因为它存进去的是Unicode<BR>也就是说，在这种解决方法下的MySQL中的数据只能针对Hibernate使用，如果这个数据库并非只针对Hibernate而设计，还有其他的系统在用这这个数据库，甚至有可能这个系统都不是使用java编写的。那么这个系统所能看见的只有乱码了。<BR><BR>有没有更好的解决方法呢？<BR><BR>我能想到的就是不用Mysql！<IMG height=19 src="http://www.blogjava.net/Emoticons/teeth_smile.gif" width=19 border=0><BR><BR>但是这肯定不是最终的解决办法。<BR></P><img src ="http://www.blogjava.net/mstar/aggbug/3849.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mstar/" target="_blank">黑灵</a> 2005-04-27 15:48 <a href="http://www.blogjava.net/mstar/archive/2005/04/27/3849.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>caveatemptor中的HibernateUtil</title><link>http://www.blogjava.net/mstar/archive/2005/04/26/3804.html</link><dc:creator>黑灵</dc:creator><author>黑灵</author><pubDate>Tue, 26 Apr 2005 00:26:00 GMT</pubDate><guid>http://www.blogjava.net/mstar/archive/2005/04/26/3804.html</guid><wfw:comment>http://www.blogjava.net/mstar/comments/3804.html</wfw:comment><comments>http://www.blogjava.net/mstar/archive/2005/04/26/3804.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/mstar/comments/commentRss/3804.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/mstar/services/trackbacks/3804.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 昨天看hibernate in action是找到的，很值得借鉴啊&nbsp;&nbsp;1package&nbsp;org.hibernate.auction.persistence;&nbsp;&nbsp;2&nbsp;&nbsp;3import&nbsp;net.sf.hibernate.*;&nbsp;&nbsp;4import&nbsp;net.sf.hibernate.cfg....&nbsp;&nbsp;<a href='http://www.blogjava.net/mstar/archive/2005/04/26/3804.html'>阅读全文</a><img src ="http://www.blogjava.net/mstar/aggbug/3804.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/mstar/" target="_blank">黑灵</a> 2005-04-26 08:26 <a href="http://www.blogjava.net/mstar/archive/2005/04/26/3804.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>