﻿<?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-rox-随笔分类-hibernate</title><link>http://www.blogjava.net/rox/category/14645.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 03 Jun 2008 07:25:27 GMT</lastBuildDate><pubDate>Tue, 03 Jun 2008 07:25:27 GMT</pubDate><ttl>60</ttl><item><title>开发者请注意oracle jdbc的resultSet.last()方法的效率问题【转载】</title><link>http://www.blogjava.net/rox/archive/2008/05/28/203431.html</link><dc:creator>rox</dc:creator><author>rox</author><pubDate>Wed, 28 May 2008 03:26:00 GMT</pubDate><guid>http://www.blogjava.net/rox/archive/2008/05/28/203431.html</guid><wfw:comment>http://www.blogjava.net/rox/comments/203431.html</wfw:comment><comments>http://www.blogjava.net/rox/archive/2008/05/28/203431.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/rox/comments/commentRss/203431.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/rox/services/trackbacks/203431.html</trackback:ping><description><![CDATA[<p><font style="color: #0000ff; background-color: #d4d0c8">同事在公司论坛里面发的，其实是我接手的一个项目中存在这个问题。<br />
在使用Hibernate分页器时，习惯使用直接把查询语句、页数、分页大小，传给分页器，这样会默认使用last来获取总记录数，效率非常的低。<br />
解决方法，很简单，就是用SQL来count查询条件获得总记录的Query，再给Hibernate分页器（本身就写好了的）。<br />
这样就必须多写几行代码，就是因为自己懒，觉着效果都一样，就简单的写了。<br />
数据量大了以后，就很明显的速度慢下来了。又全部重头改过，很是郁闷。<br />
转载此文，以示提醒！<br />
即使懒得研究Hibernate底层，也要注意它的效率问题。</font></p>
<p><font style="background-color: #d4d0c8"></font>&nbsp;</p>
<p><font style="background-color: #d4d0c8">&nbsp;</font></p>
<p><span style="font-size: 14pt">我看到一些资料这样说，oracle的jdbc驱动是不支持服务器端的游标的，当你调用resultSet.last()时，jdbc驱动程序会把整个结果集的数据读到内存，然后在内存中进行结果集的遍历。</span></p>
<p><span style="font-size: 14pt">如果在做分页的时候，用这样的方式获取结果的总记录数：<br />
&nbsp; rs.last(); <br />
&nbsp; int rowcount = rs.getRow(); <br />
在结果集很大的时候，这个性能是相当低下的，并且会用掉很多的内存。</span></p>
<p><span style="font-size: 14pt">这个问题是昨天在检查人才网的代码时发现的，随着数据增加，原来被掩盖的问题才开始暴露出来。我们用jprofiler对程序进行剖析的情况也间接的证明了上面的说法：1) 连续几次刷新工作列表后，虚拟机的内存被占满了，运行垃圾回收后内存又被释放出来。2) 从页面请求到完成响应，resultSet.last()方法的调用占去了cpu的绝大部分时间。</span></p>
<p><span style="font-size: 14pt">因为上面提到的分页方法是一种常用的方法，我建议大家考虑一下自己的代码是否存在这样的问题，这对办公系统的稳定运行可能是很重要的。</span></p>
<font style="background-color: #d4d0c8">
<p><br />
<span style="font-size: 14pt">参考：<br />
http://www.oracle.com/technology/global/cn/sample_code/tech/java/codesnippet/jdbc/rs/CountResult.html<br />
提到了：<br />
如果 ResultSet 非常大，则 resultset.last() 有可能是非常费时的操作，因为它将使用服务器端的更多资源。因此，除非确实需要可滚动结果集，应避免使用这种方法。</span></p>
<p><span style="font-size: 14pt">http://forum.springframework.org/showthread.php?t=50044&amp;page=2<br />
提到了：<br />
Anyway, if it's a normal behaviour of the oracle driver to keep data in memory when using SCROLLABLE resultset</span></p>
<p><span style="font-size: 14pt">http://xiongbo.javaeye.com/blog/38481<br />
对几种游标类型做了介绍，并给出了建议<br />
</span></font></p>
<img src ="http://www.blogjava.net/rox/aggbug/203431.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/rox/" target="_blank">rox</a> 2008-05-28 11:26 <a href="http://www.blogjava.net/rox/archive/2008/05/28/203431.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hibernate与Mysql使用c3p0连接池时的一点注意。</title><link>http://www.blogjava.net/rox/archive/2006/02/14/30657.html</link><dc:creator>rox</dc:creator><author>rox</author><pubDate>Tue, 14 Feb 2006 11:43:00 GMT</pubDate><guid>http://www.blogjava.net/rox/archive/2006/02/14/30657.html</guid><wfw:comment>http://www.blogjava.net/rox/comments/30657.html</wfw:comment><comments>http://www.blogjava.net/rox/archive/2006/02/14/30657.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/rox/comments/commentRss/30657.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/rox/services/trackbacks/30657.html</trackback:ping><description><![CDATA[最近用 Hibernate 3 连接 Mysql 4 数据库。<br />调试时都还好，真正发布的时候毛病来了。<br />每天早晨都要都会报错，不能正常操作数据库。<br />Mysql 重启，无效，Tomcat 重启，有效。<br /><br />Mysql(MySQL 4.1) 文档 7.5.2 节 <br /><a href="http://dev.mysql.com/doc/refman/4.1/en/server-parameters.html">Tuning Server Parameters</a> 里面<br />在 Mysql控制台下输入 SHOW VARIABLES; <br />最后一个参数<br />wait_timeout    28800<br />如果单位是秒，也就是 8 个小时。<br />程序最后一次建立连接完毕之后 8 个小时，<br />Mysql 单方面关闭了这个连接。<br />但 Hibernate 还在记忆着这个连接基本信息。<br />程序再次连接的时候，已经不存在了。<br /><br />不过，Hibernate 可以设置它自己的 timeout 。<br />到了 Hibernate 3 默认第三方的连接池管理，<br />由 Apache 的 DBCP 项目更换成了 <a href="http://sourceforge.net/projects/c3p0">c3p0 项目</a>。<a href="http://sourceforge.net/projects/c3p0"></a><br />它的属性在 Hibernate 配置属性有对应的写法，如：<br />c3p0.maxIdleTime = hibernate.c3p0.timeout<br />c3p0.maxPoolSize = hibernate.c3p0.max_size <br />所以，要修改一下 hibernate.cfg.xml 文档<br />将 Hibernate 默认连接池参数<br />&lt;property name="connection.pool_size"&gt;5&lt;/property&gt;<br />删除或注释掉，Hibernate 默认连接池比较初级。<br />然后，加入以下属性<br />&lt;property name="hibernate.c3p0.timeout"&gt;1800&lt;/property&gt;<br />&lt;property name="hibernate.c3p0.max_size"&gt;5&lt;/property&gt;<br />就可以使用 c3p0 来管理连接池了。<br />其实这些属性的参数名都可以在 Hibernate 文档 3.3 节<br /><a href="http://www.hibernate.org/hib_docs/v3/reference/en/html/session-configuration.html#configuration-hibernatejdbc">JDBC connections</a> 里面找到。<br />按照相应的格式更改名字和值就可以了。<br /><br /><img src ="http://www.blogjava.net/rox/aggbug/30657.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/rox/" target="_blank">rox</a> 2006-02-14 19:43 <a href="http://www.blogjava.net/rox/archive/2006/02/14/30657.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>