﻿<?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--随笔分类-jdbc、事务、并发</title><link>http://www.blogjava.net/leekiang/category/32578.html</link><description>MDA/MDD/TDD/DDD/DDDDDDD</description><language>zh-cn</language><lastBuildDate>Sat, 08 Oct 2011 10:08:13 GMT</lastBuildDate><pubDate>Sat, 08 Oct 2011 10:08:13 GMT</pubDate><ttl>60</ttl><item><title>Dbutils笔记</title><link>http://www.blogjava.net/leekiang/archive/2011/10/07/360119.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Fri, 07 Oct 2011 09:22:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2011/10/07/360119.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/360119.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2011/10/07/360119.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/360119.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/360119.html</trackback:ping><description><![CDATA[		ResultSetHandler的实现类有很多种，涉及数组、map 、javabean等，都接受一个RowProcessor类型的参数来实现结果集向对象的转化。其中RowProcessor的默认实现类为BasicRowProcessor， 用户也可以自己实现RowProcessor。 BasicRowProcessor使用BeanProcessor来完成resultset中的值向javabean的映射，前提要求列名和bean属性名必须一致。<br /><br />ArrayHandler ：将ResultSet中第一行的数据转化成对象数组<br />ArrayListHandler : 将ResultSet中所有的数据转化成List，List中存放的是Object[]<br />BeanHandler ：将ResultSet中第一行的数据转化成类对象<br />BeanListHandler ：将ResultSet中所有的数据转化成List，List中存放的是类对象<br />MapHandler ：将ResultSet中第一行的数据存成Map映射<br />MapListHandler ：将ResultSet中所有的数据存成List。List中存放的是Map<br />ColumnListHandler ：将ResultSet中某一列的数据存成List，List中存放的是Object对象<br />KeyedHandler ：将ResultSet中所有数据存成Map，Map中key为某一列的值，value为Map，存放key对应的行的数据<br />ScalarHandler ：将ResultSet中一条记录的其中某一列的数据存成Object<br /><br />查询的基本用法:<br /><div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; 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);">        String url </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);">jdbc:mysql://localhost:3306/blog</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br />        String jdbcDriver </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);">com.mysql.jdbc.Driver</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br />        String user </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);">root</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br />        String password </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);">root</span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">;<br />        DbUtils.loadDriver(jdbcDriver);<br />        Connection conn </span><span style="color: rgb(0, 0, 0);">=</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 />        </span><span style="color: rgb(0, 0, 255);">try</span><span style="color: rgb(0, 0, 0);"> {<br />            conn </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> DriverManager.getConnection(url, user, password);<br />            QueryRunner qr </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);"> QueryRunner();<br />            List  results </span><span style="color: rgb(0, 0, 0);">=</span><span style="color: rgb(0, 0, 0);"> (List)qr.query(conn, </span><span style="color: rgb(0, 0, 0);">"</span><span style="color: rgb(0, 0, 0);">select  *  from T_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);"> BeanListHandler(User.</span><span style="color: rgb(0, 0, 255);">class</span><span style="color: rgb(0, 0, 0);">) );<br />        } </span><span style="color: rgb(0, 0, 255);">catch</span><span style="color: rgb(0, 0, 0);"> (SQLException e) {<br />            e.printStackTrace();<br />        } </span><span style="color: rgb(0, 0, 255);">finally</span><span style="color: rgb(0, 0, 0);"> {<br />            DbUtils.closeQuietly(conn);<br />        }</span></div>该query方法执行后会自己关闭rs和stmt，但没有关闭连接。<br />如果传入dataSource, QueryRunner run = new QueryRunner( dataSource ),则执行不含conn参数的查询方法时，会自己关闭连接。<br /><div style="background-color: rgb(238, 238, 238); font-size: 13px; border: 1px solid rgb(204, 204, 204); padding: 4px 5px 4px 4px; 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, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">T</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"> T query(String sql, ResultSetHandler</span><span style="color: rgb(0, 0, 0);">&lt;</span><span style="color: rgb(0, 0, 0);">T</span><span style="color: rgb(0, 0, 0);">&gt;</span><span style="color: rgb(0, 0, 0);"> rsh, Object<img src="http://www.blogjava.net/images/dot.gif" /> params)<br />        </span><span style="color: rgb(0, 0, 255);">throws</span><span style="color: rgb(0, 0, 0);"> SQLException {<br /><br />        Connection conn </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);">.prepareConnection();<br /><br />        </span><span style="color: rgb(0, 0, 255);">try</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);"> </span><span style="color: rgb(0, 0, 255);">this</span><span style="color: rgb(0, 0, 0);">.query(conn, sql, rsh, params);<br />        } </span><span style="color: rgb(0, 0, 255);">finally</span><span style="color: rgb(0, 0, 0);"> {<br />            close(conn);<br />        }<br />    }</span></div><br /><br /><a href="http://dean-liu.iteye.com/blog/588753">扩展ApacheCommos的DbUtils以支持字段名下划线映射</a><br /><a href="http://www.iteye.com/topic/802197">对 DBUtils 包中 BeanProcessor 的优化</a><br /><a href="http://www.iteye.com/topic/381714">修改DbUtils支持表名下划线映射</a><br /><a href="http://iloveoracle.iteye.com/blog/1139285">dbutils</a><br /><a href="http://cuics-100.iteye.com/blog/832988">Commons DbUtils 源码阅读四</a><br /><a href="http://www.iteye.com/topic/759644">让你的DBUtils支持enum</a><br /><a href="http://www.oschina.net/code/snippet_12_6">OSChina底层数据库操作的类(QueryHelper)源码</a><br /><a href="http://www.oschina.net/question/12_3900">OSChina底层数据库操作的类(QueryHelper)源码2</a><br /><a href="http://bbs.weblogicfans.net/thread-1758-1-1.html">基于JDBC+Oracle+Apache Dbutil的泛型DAO</a><br /><a target="_blank" href="http://hi.baidu.com/naivebaby/blog/item/73794a4c919f76f4d62afc44.html">日常数据库操作的烦恼及解药--DbUtils、MyBatis和Hibernate</a><br /><a href="http://hszdz.iteye.com/blog/1109977">基于dbutils支持annotation的简易orm</a><br /><br /><img src ="http://www.blogjava.net/leekiang/aggbug/360119.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2011-10-07 17:22 <a href="http://www.blogjava.net/leekiang/archive/2011/10/07/360119.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>CAP、BASE、Sharding等</title><link>http://www.blogjava.net/leekiang/archive/2010/04/26/319347.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Sun, 25 Apr 2010 16:20:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2010/04/26/319347.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/319347.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2010/04/26/319347.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/319347.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/319347.html</trackback:ping><description><![CDATA[CAP原理(CAP Theorem)<br /><span class="Apple-style-span" style=""><span class="Apple-style-span" style="">Consistency(一致性), 数据一致更新，所有数据变动都是同步的<br />Availability(可用性), 
好的响应性能<br />Partition tolerance(分区容错性) 可靠性</span></span><br />CAP原理指的是，这三个要素最多只能同时实现两点，不可能三者兼顾<br />http://www.javaeye.com/articles/2367<br /><br /><br /><span class="Apple-style-span" style=""><span class="Apple-style-span" style="">BASE模型反ACID模型，完全不同ACID模型，牺牲高一致性，获得可用性或可靠性：<br />Basically 
Available基本可用。支持分区失败(e.g. sharding碎片划分数据库)<br />Soft state软状态 
状态可以有一段时间不同步，异步。<br />Eventually consistent最终一致，最终数据是一致的就可以了，而不是时时高一致。<br /></span></span>http://lovewhzlq.javaeye.com/blog/619965<br /><span class="Apple-style-span" style=""><span class="Apple-style-span" style=""><br /></span></span>Sharding:<br />Sharding(分片)，与分区(Partition)不一样，分区不能跨数据库<br />http://www.dbanotes.net/database/database_sharding.html<img src ="http://www.blogjava.net/leekiang/aggbug/319347.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2010-04-26 00:20 <a href="http://www.blogjava.net/leekiang/archive/2010/04/26/319347.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ibatis</title><link>http://www.blogjava.net/leekiang/archive/2010/03/04/314473.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Wed, 03 Mar 2010 17:26:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2010/03/04/314473.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/314473.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2010/03/04/314473.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/314473.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/314473.html</trackback:ping><description><![CDATA[
		<a href="http://coolsql.sourceforge.net/webexplore.html">基于Ibator(Abator)的可视化代码生成工具</a>
		<br />
		<br />
<img src ="http://www.blogjava.net/leekiang/aggbug/314473.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2010-03-04 01:26 <a href="http://www.blogjava.net/leekiang/archive/2010/03/04/314473.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>createStatement(resultSetType, resultSetConcurrency)</title><link>http://www.blogjava.net/leekiang/archive/2010/01/03/308117.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Sun, 03 Jan 2010 15:57:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2010/01/03/308117.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/308117.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2010/01/03/308117.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/308117.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/308117.html</trackback:ping><description><![CDATA[
		<span> resultSetType</span>
		<span>的可选值有：</span>
		<span>ResultSet.TYPE_FORWARD_ONLY</span>
		<span>、<span lang="EN-US">ResultSet.TYPE_SCROLL_INSENSITIVE</span>
、<span lang="EN-US">ResultSet.TYPE_SCROLL_SENSITIVE<br />1)</span></span>
		<span>TYPE_FORWARD_ONLY是默认值,</span>
		<span>仅支持结果集<span lang="EN-US">forward</span>
，不支持滚动,也不是</span>
		<span>
				<span lang="EN-US">SENSITIVE的<br />2)</span>
		</span>
		<span>
				<span lang="EN-US">ResultSet.TYPE_SCROLL_INSENSITIVE,<br /></span>
		</span>
		<span>支持结果集<span lang="EN-US">backforward</span> ，<span lang="EN-US">last</span>
，<span lang="EN-US">first</span>
等操作，对其它<span lang="EN-US">session</span>对数据库中数据做出的更改是不敏感的</span>
		<br />原因:JDBC对数据库进行数据查询executeQuery时，数据库会创建查询结果的cache和cursor，如下面sql:<br />
    select name,id from foo<br />
   
用jdbc执行上面的sql语句时，数据库会把foo表所有记录的name和id字段缓存到cache中，之后cache和真正的数据库数据文件没有任何联系了，foo表发生的改变在查询完成后不会自动同步到cache上去，因此TYPE_SCROLL_INSENSITIVE对选择数据做出的更改是不敏
感，不可见。<br />3)<span><span lang="EN-US">ResultSet.TYPE_SCROLL_SENSITIVE<br /></span></span><span>支持结果集<span lang="EN-US">backforward</span>
，<span lang="EN-US">last</span>
，<span lang="EN-US">first</span>
等操作，对其它<span lang="EN-US">session</span>对数据库中数据做出的更改是敏感的，即其他<span lang="EN-US">session</span>
修改了数据库中的数据，会反映到本结果集中</span><br />上面的select name,id from foo语句用TYPE_SCROLL_SENSITIVE的Statement来执行，会转化成以下的sql语句：<br />
    select rowid from foo<br />
    数据库这时候是把foo表所有记录的rowid缓存到cache中，用户代码在fetch记录时，再继续做以下查询：<br />
    select name,id from foo where rowid=?<br />
   
因此这时候发生的查询是实时从真正的数据库数据文件中取，因此对期间发生的数据更改是可见的，敏感的。但是这种可见性仅限于update操作，而
insert和delete同样是不可见的。因为如果查询发生在insert之前，insert生成的rowid并不会反应在cache中的rowid结果集上。在一个记录的rowid已经缓存到cache中，这时候被删除了，但一般数据库的删除是标记删除，也就是说rowid对应那行记录并没有真正从数
据库文件中抹去，一般是可以再次取到记录的。<br /><br />结论：是否<span><span lang="EN-US">SENSITIVE与</span></span><span><span lang="EN-US">fetchsize没有什么关系。</span></span>是否<span><span lang="EN-US">SENSITIVE是告诉数据库如何作查询的缓存。</span></span><span><span lang="EN-US"></span></span><span><span lang="EN-US">fetchsize是客户端jdbc的设置。<br /><br />另外oracle的</span></span><span><span lang="EN-US"></span></span><span><span lang="EN-US">fetchsize默认为10</span></span><span><span lang="EN-US">，</span></span><span><span lang="EN-US"><br />stmt.setFetchSize(0)时stmt.getFetchSize()=1</span></span><span><span lang="EN-US">0<br />stmt.setFetchSize(1)时stmt.getFetchSize()=1<br /><br />另外如果查询的sql复杂时，我发现就算设为</span></span><span><span lang="EN-US">ResultSet.TYPE_SCROLL_SENSITIVE也不起作用，如</span></span><br /><span><span lang="EN-US">select t.*  from test t left join testp p on t.pid=p.id where p.title like '%国%'，在运行中修改title的值，发现仍然可以取到。是否可以理解为</span></span><span><span lang="EN-US">SENSITIVE只对查询的主表起作用。</span></span><br /><span><span lang="EN-US"><br />摘自：<br />http://www.javaeye.com/topic/128636<br />http://www.javaeye.com/topic/560109<br />http://www.javaeye.com/topic/418604<br /></span></span><span><span></span></span><img src ="http://www.blogjava.net/leekiang/aggbug/308117.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2010-01-03 23:57 <a href="http://www.blogjava.net/leekiang/archive/2010/01/03/308117.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>连接池等</title><link>http://www.blogjava.net/leekiang/archive/2009/12/25/307226.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Thu, 24 Dec 2009 18:31:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2009/12/25/307226.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/307226.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2009/12/25/307226.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/307226.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/307226.html</trackback:ping><description><![CDATA[
		<p>1,关于statement,resultset和connection的问题</p>
		<p>statement,resultset属于弱refrence，即如果statement关掉，resultset就会被自动释构,弱
refrence的做法不保险，所以JDBC3.0开始明确规定了如果connection被关，所有statement都应该关,不过这取决于使用的数
据库驱动。<br />应该DBMS 执行操作后，显式的关闭statement ，因为在connection关闭前，JDBC statement仍旧处于打开状态，当返回resultset后，关闭statement是必要的，尤其在遇到异常的时候。<br />如果不使用connection pool可以直接关闭connection，不考虑statement的关闭，使用连接池的时候，务必关闭statement，否则你的连接马上被用光，使用statement pooling除外。</p>
		<p>http://www.w3china.org/blog/more.asp?name=hongrui&amp;id=10283</p>
		<p>
				<br />
		</p>
		<p>
				<br />
		</p>
		<p style="">2,Software caused connection abort: socket write error</p>
		<p style="">最终找到了原因:sql写错了，写成了where name='?'<br /></p>
		<p>
				<a href="http://www.betalog.com/read.php/16.htm">有人</a>说原因:<br />oracle数据库连接与连接池之间冲突导至.<br />oracle database把空闲一段时间的连接关闭了，而应用服务器连接池却认为该边接还是可用的，再次访问时还是使用该连接，导致出现连接异常。<br />方法,当然是改数据库配置了. <br /></p>
		<p>
				<a target="_blank" href="http://www.w3china.org/blog/more.asp?name=hongrui&amp;id=5156">spring对oracle的clob和StoredProcedure 的处理</a>
				<br />
		</p>
		<p>经过几天的夜战，终于知道使用spring对oracle的存储过程操作，程序死掉的真正原因，一旦执行存储过程没有任何返回值，因为 “Statement.getUpdateCount() returns 1 instead of -1”，是oracle的驱动的bug，10.1.0.2的驱动就不行，听说10.1.0.3就没有问题，但是10.1.0.3的jdbc驱动不能下载。大家可以使用weblogic8.1SP3带的10.1.0.2或weblogic9beta的10.1.0.2，可以解决这个问题。不知道开发 oracle jdbc的程序员是什末人，没毕业的大学生，还是拖欠了工资的程序员，开发水平远不如开源数据库的jdbc驱动的人呢，再次建议oracle驱动最好是自己命名，把文件名加上版本信息，要不会死人的。<br /></p>
		<p>http://72.5.124.102/thread.jspa?messageID=1424984</p>
		<p>http://group.gimoo.net/review/44109</p>
		<p>http://azi.javaeye.com/blog/182146</p>
		<p>http://hi.baidu.com/happyidea/blog/item/c84b313de75add0abba16779.html</p>
		<p style="">
				<br />
		</p>
		<p>
				<br />
		</p>
		<p>3,Random Connection Closed Exceptions</p>
		<p>These can occur when one request gets a db connection from the connection
pool and closes it twice. <br /></p>
		<p>见http://tomcat.apache.org/tomcat-4.1-doc/jndi-datasource-examples-howto.html<br /></p>
<img src ="http://www.blogjava.net/leekiang/aggbug/307226.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2009-12-25 02:31 <a href="http://www.blogjava.net/leekiang/archive/2009/12/25/307226.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring jdbc笔记</title><link>http://www.blogjava.net/leekiang/archive/2009/12/23/307061.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Wed, 23 Dec 2009 09:29:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2009/12/23/307061.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/307061.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2009/12/23/307061.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/307061.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/307061.html</trackback:ping><description><![CDATA[SQL标准允许基于一个带参数列表的表达式进行查询。一个典型的例子可能像这样："select * from T_ACTOR where id in (1, 2, 3)"。 不过这种参数列表的方式并不能直接被JDBC标准所支持 - 因为并不存在这种声明一个列表参数作为占位符的方式。 你不得不为此写多个占位符来表示多个参数，或者当你知道占位符的数量时，你可以动态构建SQL字符串。 NamedParameterJdbcTemplate和SimpleJdbcTemplate中所提供的命名参数的特性，采用的是后面一种做法。 当你传入参数时，你需要传入一个java.util.List类型，支持基本类型。而这个list将会在SQL执行时替换占位符并传入参数。<br />在使用IN语句时，当你传入大批量的值时要小心，JDBC标准并不确保超过100个元素在IN语句中。 有不少数据库可以超出这个值的限制，但是不同的数据库会有不同的数量限制，比如Oracle的限制数量是1000个。<br />除了基本类型之外，你还可以创建一个java.util.List的对象数组，这可以让你支持在IN表达式中编写多重表达式，例如"select * from T_ACTOR where (id, last_name) in ((1, 'Johnson'), (2, 'Harrop'))". 当然，这样做的前提是数据库底层的语法支持。 <br /><br />http://www.javaeye.com/problems/6124<br />select count(*) num from lottery_term where term_issuenum in (?) and 
term_lotteryid = ?<br />改成getJdbcTemplate().queryForInt(sql,new Object[]{new 
String[]{"2008326","2008325","2008324"},103}); <br />List 
list=new ArrayList();<br />list.add("****");<br />getJdbcTemplate().queryForInt(sql,new
 Object[]{list,103}); <br />或<br />select count(*) from info_document where category_id in 
(:category_id_list);<br />Map&lt;String,Object&gt; parm = new 
HashMap&lt;String,Object&gt;();<br />parm.put("category_id_list", idList);<br /><br /><br /><span style="font-size: 10pt; color: rgb(0, 0, 0);"><span>  </span></span><strong><span style="font-size: 10pt; color: rgb(127, 0, 85);">public</span></strong><span style="font-size: 10pt; color: rgb(0, 0, 0);"> List getAllStu() {</span><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: rgb(0, 0, 0);"><span>       </span>String sql=</span><span style="font-size: 10pt; color: rgb(42, 0, 255);">"select s_id as sid,s_name as sname,s_sex as ssex,s_brith as sbrith from stu"</span><span style="font-size: 10pt; color: rgb(0, 0, 0);">;</span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: rgb(0, 0, 0);"><span>       </span>List list=</span><span style="font-size: 10pt; color: rgb(0, 0, 192);">this.getJdbcTemplate()</span><span style="font-size: 10pt; color: rgb(0, 0, 0);">.query(sql,</span><strong><span style="font-size: 10pt; color: rgb(127, 0, 85);">new</span></strong><span style="font-size: 10pt; color: rgb(0, 0, 0);"> BeanPropertyRowMapper(Stu.</span><strong><span style="font-size: 10pt; color: rgb(127, 0, 85);">class</span></strong><span style="font-size: 10pt; color: rgb(0, 0, 0);">));</span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: rgb(0, 0, 0);"><span>       </span></span><strong><span style="font-size: 10pt; color: rgb(127, 0, 85);">return</span></strong><span style="font-size: 10pt; color: rgb(0, 0, 0);"> list;</span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: rgb(0, 0, 0);"><span>    </span>}</span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><br /><span style="font-size: 10pt; color: rgb(0, 0, 0);"></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: rgb(0, 0, 0);">关于execute和update方法之间的区别，update方法返回的是受影响的记录数目的 一个计数，并且如果传入参数的话，使用的是java.sql.PreparedStatement,而execute方法总是使用 java.sql.Statement,不接受参数，而且他不返回受影响记录的计数，更适合于创建和丢弃表的语句，而update方法更适合于插入，更新 和删除操作，这也是我们在使用时需要注意的。</span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><br /><span style="font-size: 10pt; color: rgb(0, 0, 0);"></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><br /><span style="font-size: 10pt; color: rgb(0, 0, 0);"></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: rgb(0, 0, 0);">Connection conn=DataSourceUtils.getConnection(getJdbcTempldate().getDataSource());</span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: rgb(0, 0, 0);">conn=getJdbcTemplate().getNativeJdbcExtractor().getNativeConnection(conn);</span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: rgb(0, 0, 0);">OracleConnection oconn=(OracleConnection)conn;</span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span style="font-size: 10pt; color: rgb(0, 0, 0);">通过</span><span style="font-size: 10pt; color: rgb(0, 0, 0);">DataSourceUtils获取当前线程绑定的数据连接，为了使用线程上下文相关的事务，这样写是正确的写法，如果直接从DataSource获取连接，得到的是和当前线程上下文无关的新的数据库连接实例。</span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">http://www.javaeye.com/topic/49932?page=2</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">http://www.javaeye.com/problems/15846</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">http://www.javaeye.com/topic/87034<br /></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">http://www.javaeye.com/topic/508799</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">http://ttitfly.javaeye.com/blog/151560</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><br /></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">jdbcTemplate的方式里如果带上int[] argTypes显示指定每个占位符所对应的字段数据类型，可以保证类型安全，当参数值为null时，提供了更好的支持。</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">-----------------------</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">上面这句话如何理解？</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><br /></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">后在http://javazoo.bokee.com/viewdiary.15850865.html找到原因了</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">今天在调试程序的时候,在后台业务逻辑类中利用JdbcTemplate进行数据同步操作时,发现当<br />执行jdbcTemplate.update(带?的SQL语句,new Object[]{tmp.getName( ),tmp.getNo( ),tmp.getSpeciality( ),tmp.getMounterofficer( ),tmp.getDesigner( ),tmp.getProductivity( ),tmp.getState( ))<br />这种操作时,如果后面参数中有值为null时,后台会报异常,细想下也是,如果是null,那就要执行jdbc的setNull(Spring底层还是用JDBC做的)方法了,但是setNull方法要知道具体的数据库字段的类型.如setNull(1,Types.VARCHAR).而在上面的方法没有体现.<br />终于体会到update方法中第三个参数new int[]的作用了.!<br />spring还是很伟大的.</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><br /></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">如果字段名和属性名是严格对应的，那么就可以不用自己写RowMapper了，使用<span><span style="">BeanPropertyRowMapper:</span></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><span><span style="">getJdbcTemplate().query(sql, </span><span class="keyword">new</span><span style=""> BeanPropertyRowMapper(User.</span><span class="keyword">class</span><span>));  </span></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">类的属性字段名称要数据库中的字段名称一样或者数据库字段名为s_id类的名称为SId,<br />如果你没有遵守这个规范则可以在select语句后面给数据库字段名取别名</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><br /></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">//绑定参数时，日期类型的写法,未经过验证<br /></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">    public void updStu(Stu stu) {<br />String sql = "update stu set s_name=?,s_sex=?,s_brith=? where s_id=?";<br />Object[] obj = new Object[] { stu.getSname(), stu.getSsex(),new java.sql.Date(stu.getSbrith().getTime()), stu.getSid() };<br />      <span><span style="">getJdbcTemplate()</span></span>.update(sql, obj, new int[] { Types.VARCHAR, Types.VARCHAR,Types.DATE, Types.INTEGER });<br />    }</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><br /></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><br /></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">ConnectionCallback的用法，使用完要手动关闭连接吗？<br /><br /><span style="font-size: 10pt; color: rgb(0, 0, 0);"></span></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">spring的AbstractRoutingDataSource，可以多态切换数据库?</p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left"><br /></p><p class="MsoNormal" style="margin: 0cm 0cm 0pt; text-align: left;" align="left">事务抽象层http://blog.csdn.net/congqian1120/archive/2008/01/16/2046311.aspx<br /></p><br /><br /><br />http://www.oracle.com/technology/global/cn/pub/articles/marx_spring.html<img src ="http://www.blogjava.net/leekiang/aggbug/307061.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2009-12-23 17:29 <a href="http://www.blogjava.net/leekiang/archive/2009/12/23/307061.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在一个单独的DAO中混合使用Hibernate 和 JDBC </title><link>http://www.blogjava.net/leekiang/archive/2009/12/18/306589.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Fri, 18 Dec 2009 08:51:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2009/12/18/306589.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/306589.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2009/12/18/306589.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/306589.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/306589.html</trackback:ping><description><![CDATA[
		<p class="11" style="margin: 0cm 0cm 0pt; text-indent: 19pt;">
				<font size="2">
						<span lang="EN-US">
								<font face="Times New Roman">Hibernate </font>
						</span>
						<span style="font-family: 宋体;">的确通过</span>
						<span style="font-family: TheSansMonoConSemiLight;" lang="EN-US">
								<font face="Times New Roman">PersistentEnum</font>
						</span>
						<span style="font-family: 宋体;">接口提供了对标准化</span>
						<font face="Times New Roman">
						</font>
						<span style="font-family: 宋体;">的支持，这使得我们的域对象实现了一个与</span>
						<span lang="EN-US">
								<font face="Times New Roman">ShippingCompany</font>
						</span>
						<span style="font-family: 宋体;">对象非常类似的结构。然而，我们可能对将域对象与某个特定的持久化实现过于耦合持保守态度。如果我们计划长期使用</span>
						<span lang="EN-US">
								<font face="Times New Roman">Hibernate</font>
						</span>
						<span style="font-family: 宋体;">，这可能并不是一个太大的问题，但是请谨慎考虑这个决策。如果我们使用</span>
						<span lang="EN-US">
								<font face="Times New Roman">ibatis</font>
						</span>
						<span style="font-family: 宋体;">，那么我们就完全没那么幸运了；它完全不支持标准化。谢天谢地，如果我们的</span>
						<span lang="EN-US">
								<font face="Times New Roman">ORM</font>
						</span>
						<span style="font-family: 宋体;">导致过耦合或者完全没有这方面的支持，还有个解决方案——使用</span>
						<span lang="EN-US">
								<font face="Times New Roman">JDBC</font>
						</span>
						<span style="font-family: 宋体;">。</span>
				</font>
		</p>
		<p class="11" style="margin: 0cm 0cm 0pt; text-indent: 19pt;">
				<font size="2">
						<span style="font-family: 宋体;">有</span>
						<span lang="EN-US">
								<font face="Times New Roman">Spring</font>
						</span>
						<span style="font-family: 宋体;">的支持，使用</span>
						<span lang="EN-US">
								<font face="Times New Roman">JDBC</font>
						</span>
						<span style="font-family: 宋体;">变得如此简单，我们不会再因为它的复杂性而将其的优先级打个折扣。可是，如果我们选择使用某个特定的</span>
						<span lang="EN-US">
								<font face="Times New Roman">ORM</font>
						</span>
						<span style="font-family: 宋体;">工具，那么我们就很难用基于</span>
						<span lang="EN-US">
								<font face="Times New Roman">JDBC</font>
						</span>
						<span style="font-family: 宋体;">的</span>
						<span lang="EN-US">
								<font face="Times New Roman">DAO</font>
						</span>
						<span style="font-family: 宋体;">实现进行替换了——目前我们就是这样。当我们同时在一个类中包含了</span>
						<span lang="EN-US">
								<font face="Times New Roman">JDBC</font>
						</span>
						<span style="font-family: 宋体;">和</span>
						<span lang="EN-US">
								<font face="Times New Roman">hibernate</font>
						</span>
						<span style="font-family: 宋体;">代码时，我们就无法使用</span>
						<span lang="EN-US">
								<font face="Times New Roman">Spring</font>
						</span>
						<span style="font-family: 宋体;">提供的支持。因为我们的</span>
						<span lang="EN-US">
								<font face="Times New Roman">DAO</font>
						</span>
						<span style="font-family: 宋体;">只能扩展</span>
						<span style="font-family: TheSansMonoConSemiLight;" lang="EN-US">
								<font face="Times New Roman">HibernateDaoSupport </font>
						</span>
						<span style="font-family: 宋体;">或</span>
						<font face="Times New Roman">
								<span style="font-family: TheSansMonoConSemiLight;" lang="EN-US">JdbcDaoSupport</span>
						</font>
						<span style="font-family: 宋体;">二者之一。幸运的是，这里有一个优雅的解决方案，它允许我们将</span>
						<span lang="EN-US">
								<font face="Times New Roman">Hibernate</font>
						</span>
						<span style="font-family: 宋体;">和</span>
						<span lang="EN-US">
								<font face="Times New Roman">JDBC</font>
						</span>
						<span style="font-family: 宋体;">代码封装在同一个类之内，而不会因此失去</span>
						<span lang="EN-US">
								<font face="Times New Roman">Spring</font>
						</span>
						<span style="font-family: 宋体;">的支持。这个方案的关键在于将</span>
						<span lang="EN-US">
								<font face="Times New Roman">JDBC</font>
						</span>
						<span style="font-family: 宋体;">代码封装在内部类中，之后将主体</span>
						<span lang="EN-US">
								<font face="Times New Roman">DAO</font>
						</span>
						<span style="font-family: 宋体;">的调用委托给这个内部类去完成。代码清单</span>
						<span lang="EN-US">
								<font face="Times New Roman"> 11-6</font>
						</span>
						<span style="font-family: 宋体;">提供了一个示例：</span>
				</font>
		</p>
		<p class="10" style="margin: 8pt 0cm 6pt;">
				<b>
						<span style="font-family: 黑体;">代码清单</span>
				</b>
				<b>
						<span style="font-family: HelveticaNeue-BoldCond;" lang="EN-US"> 11-16. </span>
				</b>
				<span style="font-family: 黑体;">在一个单独的</span>
				<span lang="EN-US">DAO</span>
				<span style="font-family: 黑体;">中混合使用</span>
				<span lang="EN-US">Hibernate </span>
				<span style="font-family: 黑体;">和</span>
				<span lang="EN-US"> JDBC </span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">package com.apress.prospring.ch11.canonicalization;</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New"> </font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">import org.springframework.jdbc.core.support.JdbcDaoSupport;</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">import org.springframework.orm.hibernate.support.HibernateDaoSupport;</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New"> </font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">public class MyDao extends HibernateDaoSupport {</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New"> </font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">   private MyJdbcDao innerDao;</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New"> </font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">   public MyDao() {</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">      innerDao = new MyJdbcDao();</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">   }</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New"> </font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">   public void update(MyDomainObject obj) {</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">      // use Hibernate to persist the data</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">   }</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New"> </font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">   public MyDomainObject getById(int someId) {</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">      return innerDao.getBy(someId);</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">   }</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New"> </font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">   private static class MyJdbcDao extends JdbcDaoSupport {</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New"> </font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">      public MyDomainObject getBy(int someId) {</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">         // do some real processing</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">         return null;</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">      }</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">   }</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New">}</font>
				</span>
		</p>
		<p class="2" style="margin: 0cm 0cm 0pt;">
				<span lang="EN-US">
						<font size="2" face="Courier New"> </font>
				</span>
		</p>
		<p class="11" style="margin: 0cm 0cm 0pt; text-indent: 19pt;">
				<font size="2">
						<span style="font-family: 宋体;">尽管这只是一个简单的实现，我们也可以从中得到启发。所有的</span>
						<span lang="EN-US">
								<font face="Times New Roman">JDBC</font>
						</span>
						<span style="font-family: 宋体;">相关代码都被转移到一个内部类中，而此内部类扩展了</span>
						<font face="Times New Roman">
								<span style="font-family: TheSansMonoConSemiLight;" lang="EN-US">JdbcDaoSupport</span>
								<span lang="EN-US">,</span>
						</font>
						<span style="font-family: 宋体;">所有的</span>
						<span lang="EN-US">
								<font face="Times New Roman">Hibernate</font>
						</span>
						<span style="font-family: 宋体;">相关功能都留在外部，外部类仍然是</span>
						<font face="Times New Roman">
								<span style="font-family: TheSansMonoConSemiLight;" lang="EN-US">HibernateDaoSupport</span>
								<span lang="EN-US">.</span>
						</font>
						<span style="font-family: 宋体;">的子类。通过这个类，我们可以使用</span>
						<span lang="EN-US">
								<font face="Times New Roman">Hibernate</font>
						</span>
						<span style="font-family: 宋体;">完成域对象的持久化，但是我们可以将查询功能交给嵌入的</span>
						<span lang="EN-US">
								<font face="Times New Roman">JDBC DAO</font>
						</span>
						<span style="font-family: 宋体;">去完成。</span>
				</font>
		</p>
		<p class="11" style="margin: 0cm 0cm 0pt; text-indent: 19pt;">
				<font size="2">
						<span style="font-family: 宋体;">在我们的应用中有效利用标准化</span>
						<font face="Times New Roman">
						</font>
						<span style="font-family: 宋体;">，可以通过避免大量无谓对象的创建，从而极大提升内存使用效率。如果我们必须更新标准化对象相关的数据，同时我们在</span>
						<span lang="EN-US">
								<font face="Times New Roman">DAO</font>
						</span>
						<span style="font-family: 宋体;">中使用了</span>
						<span lang="EN-US">
								<font face="Times New Roman">ORM</font>
						</span>
						<span style="font-family: 宋体;">框架，那么我们就可以以</span>
						<span lang="EN-US">
								<font face="Times New Roman">ORM</font>
						</span>
						<span style="font-family: 宋体;">无关的形式引入一些</span>
						<span lang="EN-US">
								<font face="Times New Roman">JDBC</font>
						</span>
						<span style="font-family: 宋体;">代码来加入标准化</span>
						<font face="Times New Roman">
						</font>
						<span style="font-family: 宋体;">支持。</span>
				</font>
		</p>
		<p class="11" style="margin: 0cm 0cm 0pt; text-indent: 19pt;">
				<br />
				<font size="2">
						<span style="font-family: 宋体;">
						</span>
				</font>
		</p>
		<p class="11" style="margin: 0cm 0cm 0pt; text-indent: 19pt;">
				<font size="2">
						<span style="font-family: 宋体;">来源:Pro Spring中文版 http://book.csdn.net/bookfiles/48/100481407.shtml</span>
				</font>
		</p>
		<p class="11" style="margin: 0cm 0cm 0pt; text-indent: 19pt;">
				<font size="2">
						<span style="font-family: 宋体;">http://hi.baidu.com/%D3%F4%C3%C6%BB%A8%C9%FA%BD%B4/blog/item/7768d41e8c06ceffe0fe0ba6.html<br /></span>
				</font>
		</p>
<img src ="http://www.blogjava.net/leekiang/aggbug/306589.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2009-12-18 16:51 <a href="http://www.blogjava.net/leekiang/archive/2009/12/18/306589.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate和jdbc事务统一控制</title><link>http://www.blogjava.net/leekiang/archive/2009/12/11/305492.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Thu, 10 Dec 2009 16:14:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2009/12/11/305492.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/305492.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2009/12/11/305492.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/305492.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/305492.html</trackback:ping><description><![CDATA[“Hibernate与JDBC(iBATIS)  都使用 DataSourceTransactionManager 同样可以保证事务<br />
原理就是保证了 connection 的唯一性。<br />
jdbc我是调spring的jdbcTemplate来操作，<br />
经过测试。在同一个数据源的情况下直接使用Hibernate的TxManager可以同步事务，问题解决。<br />
”<br />
Rod Johnson的话： <br />
引用<br />
It is possible--and sometimes useful--to have coordinated transactions
for both. Your JDBC transactions will be managed by the
HibernateTransactionManager if you work with the same JDBC DataSource
in the same transaction. That is, create the SessionFactory using
Spring's SessionFactoryBean using the same DataSource that your
JdbcTemplates use. <br /><br />
The only issue to watch, of course, is that you may be invalidating
your Hibernate cache by JDBC changes. Generally I find it best to use
JDBC to update only tables that don't have Hibernate mappings. <br /><br />
Juergen Hoeller的话： <br />
引用<br />
As Rod said, simply keep using HibernateTransactionManager, which
auto-detects the DataSource used by Hibernate and seamlessly exposes
Hibernate transactions as JDBC transactions for that DataSource. JDBC
code that accesses the same DataSource via Spring will automatically
participate in such transactions. <br /><br />
Note that you must specify the DataSource for Hibernate via
LocalSessionFactoryBean's "dataSource" property to allow
HibernateTransactionManager to auto-detect it. Alternatively, you can
explicitly pass the DataSource to HibernateTransactionManager's
"dataSource" property.<br />http://www.fireflow.org/redirect.php?tid=498<br /><br />Rod Johnson在spring 论坛中有一句话很好的总结了如何在测试中处理hibernate缓存: <br />Remember that you can clear the Hibernate session, removing objects already associated with it. This is often necessary before requerying in tests, and solves most (if not all) problems.<br />I typically use JDBC for verification. The pattern is<br />- do Hibernate operation<br />- flush Hibernate session<br />- issue JDBC query to verify results<br />That way I'm verifying what Hibernate did to the database in the same transaction.<br /><img src ="http://www.blogjava.net/leekiang/aggbug/305492.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2009-12-11 00:14 <a href="http://www.blogjava.net/leekiang/archive/2009/12/11/305492.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring的JdbcTemplate用法</title><link>http://www.blogjava.net/leekiang/archive/2009/11/30/304186.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Sun, 29 Nov 2009 20:46:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2009/11/30/304186.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/304186.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2009/11/30/304186.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/304186.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/304186.html</trackback:ping><description><![CDATA[1，基本用法<br />http://blog.163.com/fxf_java/blog/static/59268637200822833715185/<br />2,JdbcTemplate的连接<br />http://www.javaeye.com/topic/89845<br />http://forum.springsource.org/showthread.php?t=63444<br />3,ConnectionCallback<br />http://blog.csdn.net/lin49940/archive/2009/10/22/4712883.aspx<br /><br /><dl><dt></dt><pre>public interface <b>ConnectionCallback</b></pre></dl><p>
Generic callback interface for code that operates on a JDBC Connection.
 Allows to execute any number of operations on a single Connection,
 using any type and number of Statements.

 </p><p>This is particularly useful for delegating to existing data access code
 that expects a Connection to work on and throws SQLException. For newly
 written code, it is strongly recommended to use JdbcTemplate's more specific
 operations, for example a <code>query</code> or <code>updat</code> variant.
</p><h3>
doInConnection</h3><pre><a href="http://java.sun.com/javase/6/docs/api/java/lang/Object.html?is-external=true" title="class or interface in java.lang">Object</a><b>doInConnection</b>(<a href="http://java.sun.com/javase/6/docs/api/java/sql/Connection.html?is-external=true" title="class or interface in java.sql">Connection</a> con)<br />                      throws <a href="http://java.sun.com/javase/6/docs/api/java/sql/SQLException.html?is-external=true" title="class or interface in java.sql">SQLException</a>,<br /><a href="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/dao/DataAccessException.html" title="class in org.springframework.dao">DataAccessException</a></pre><dl><dd>Gets called by <code>JdbcTemplate.execute</code> with an active JDBC
 Connection. Does not need to care about activating or closing the
 Connection, or handling transactions.

 <p>If called without a thread-bound JDBC transaction (initiated by
 DataSourceTransactionManager), the code will simply get executed on the
 JDBC connection with its transactional semantics. If JdbcTemplate is
 configured to use a JTA-aware DataSource, the JDBC Connection and thus
 the callback code will be transactional if a JTA transaction is active.

 </p><p>Allows for returning a result object created within the callback, i.e.
 a domain object or a collection of domain objects. Note that there's special
 support for single step actions: see <code>JdbcTemplate.queryForObject</code>
 etc. A thrown RuntimeException is treated as application exception:
 it gets propagated to the caller of the template.
</p><p></p></dd><dd><dl><dt><b>Parameters:</b></dt><dd><code>con</code> - active JDBC Connection
</dd><dt><b>Returns:</b></dt><dd>a result object, or <code>null</code> if none
</dd><dt><b>Throws:</b></dt><dd><code><a href="http://java.sun.com/javase/6/docs/api/java/sql/SQLException.html?is-external=true" title="class or interface in java.sql">SQLException</a></code> - if thrown by a JDBC method, to be auto-converted
 to a DataAccessException by a SQLExceptionTranslator
</dd><dd><code><a href="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/dao/DataAccessException.html" title="class in org.springframework.dao">DataAccessException</a></code> - in case of custom exceptions</dd><dt><b>See Also:</b></dt><dd><a href="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/jdbc/core/JdbcTemplate.html#queryForObject%28java.lang.String,%20java.lang.Class%29"><code>JdbcTemplate.queryForObject(String, Class)</code></a>, 
<a href="http://static.springsource.org/spring/docs/2.5.x/api/org/springframework/jdbc/core/JdbcTemplate.html#queryForRowSet%28java.lang.String%29"><code>JdbcTemplate.queryForRowSet(String)</code></a></dd></dl></dd></dl><br /><br />2,<br /><img src ="http://www.blogjava.net/leekiang/aggbug/304186.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2009-11-30 04:46 <a href="http://www.blogjava.net/leekiang/archive/2009/11/30/304186.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java调oracle存储过程</title><link>http://www.blogjava.net/leekiang/archive/2009/08/12/290778.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Wed, 12 Aug 2009 03:46:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2009/08/12/290778.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/290778.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2009/08/12/290778.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/290778.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/290778.html</trackback:ping><description><![CDATA[        OracleCallableStatement cst = null;<br />        int oracleId = CharacterSet.ZHS16GBK_CHARSET;<br />        oracle.sql.CharacterSet dbCharset = oracle.sql.CharacterSet.make(oracleId);<br />            cst = (OracleCallableStatement) conn<br />                    .prepareCall("begin ?:= pkg_test.f_getList(?); end;");<br />//String sql = "{?=call PckgStudSltCourse.addStudPreSltCourse(?,?,?,?)}";也可以这样写<br />//sql="{call sp(?,?,?,?,?)}";//如果无返回值<br />            cst.registerOutParameter(1, OracleTypes.ARRAY, "T_ARRAY");//第一个问号表示返回结果<br />            cst.setString(2, userid);//第二个问号<br />            cst.executeUpdate();//哪怕是个查询也用executeUpdate<br /><br />            oracle.sql.ARRAY simpleArray = cst.getARRAY(1);//从statement获取，而不是rs<br />            String[] values = (String[]) simpleArray.getArray();<br />            for (int i = 0; i &lt; values.length; i++) {<br />                oracle.sql.CHAR out_value = new oracle.sql.CHAR(values[i],dbCharset);<br />                System.out.println(out_value.stringValue());<br />            }<br />            <br />注意：在new oracle.sql.CHAR处，可能会报<br />java.lang.NoClassDefFoundError: oracle/gss/util/NLSError<br />    at oracle.sql.CharacterSetUnknown.failCharsetUnknown(CharacterSetFactoryThin.java:178)<br />    at oracle.sql.CharacterSetUnknown.convert(CharacterSetFactoryThin.java:145)<br />    at oracle.sql.CHAR.(CHAR.java:147)<br />    即missing some jar file in runtime environment<br />    原因是weblogic没有加载web应用下的classes12.jar,而是加载了weblogic81\server\lib里的ojdbc14.jar,<br />    而ojdbc14.jar里没有oracle.gss.util.NLSError。<br />    修改classpath先加载classes12.jar,打印出来的是乱码，只出现乱码，这次没有出现类似这样的异常java.sql.SQLException:   Non   supported   character   set:   oracle-character-set-850  。<br />    还需要修改classpath先加载nls_charset12.jar;(必须这样，光放在web应用的lib下或光放在weblogic81\server\lib都<br />    不行，jar包放置或加载的这三种方式是有区别的)<br />问题：如果使用的是ojdbc.jar,我觉得可能就不要nls_charset12.jar了,并且不需要new oracle.sql.CHAR(values[i],dbCharset)来转换<br />    <br />http://topic.csdn.net/t/20051110/17/4385336.html<br />    类是通过类加载器classloader载入的。  <br />  缺省情况下web容器遵循java的标准标准类载入机制   --   由现载入父加载器level的类。  <br />  weblogic的web容器的classloader继承自ejb容器的classloader，ejb容器的classloader又继承自 application   classloader--该loader负责加载classpath下面的类，所以缺省情况下classpath下面的类会被优先载入，即使相同的类存在于web应用的lib目录。  <br />  可以通过配置文件来修改这种加载顺序，使得lib目录中的类得到优先调用，在weblogic   8.1中，方法是在weblogic.xml中加入下面的代码段：  <br />  &lt;container-descriptor&gt;  <br />  &lt;prefer-web-inf-classes&gt;true&lt;/prefer-web-inf-classes&gt;  <br />  &lt;/container-descriptor&gt;   <br />  weblogic   的加载顺序就是weblogic   classpath优先？ <br />  <br />  <br />  一下见http://www.javaeye.com/topic/21141<br />  ClassNotFoundException发生在装入阶段。<br />当应用程序试图通过类的字符串名称，使用常规的三种方法装入类，但却找不到指定名称的类定义时就抛出该异常。<br /><br />NoClassDefFoundError： 当目前执行的类已经编译，但是找不到它的定义时<br /><br />也就是说你如果编译了一个类B，在类A中调用，编译完成以后，你又删除掉B，运行A的时候那么就会出现这个错误 <br />当你使用字符串去转换类，也就是尝试使用Class.forName等方法去获得一个类的时候，如果这个类不存在，就会抛出ClassNotFoundException。<br />   而你编译的类无错，但是在运行时刻，缺乏某些必须的类时，就是抛出NoClassDefFoundError。这种情况最常见就是你在编译时，在classpath下有这个类，但是在运行时，你的classpath缺少这个类。 <br />   <br />  加载时从外存储器找不到需要的class就出现ClassNotFoundException<br />  连接时从内存找不到需要的class就出现NoClassDefFoundError <br />  问题:加载和连接的区别<br /><br /><div id="blog_text" class="cnt"><p>创建测试用表</p><p><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" /><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);"> T_TEST(<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />I_ID </span><span style="font-weight: bold; color: rgb(0, 0, 0);">NVARCHAR</span><span style="color: rgb(0, 0, 0);">(</span><span style="font-weight: bold; color: rgb(128, 0, 0);">20</span><span style="color: rgb(0, 0, 0);">),<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />I_NAME </span><span style="font-weight: bold; color: rgb(0, 0, 0);">NVARCHAR</span><span style="color: rgb(0, 0, 0);">(</span><span style="font-weight: bold; color: rgb(128, 0, 0);">20</span><span style="color: rgb(0, 0, 0);">)<br /><img src="http://images.csdn.net/syntaxhighlighting/OutliningIndicators/None.gif" align="top" />)</span></p><div><p><span style="color: rgb(0, 0, 0);">一：无返回值的存储过程</span></p></div><p>1、建立存储过程<br />
CREATE OR REPLACE PROCEDURE TESTA(PARA1 IN VARCHAR2,PARA2 IN VARCHAR2)  AS<br />
BEGIN <br />
    INSERT INTO T_TEST (I_ID,I_NAME) VALUES (PARA1, PARA2);<br />
END TESTA;</p><p><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 0, 255);"><font color="#000000">2、相应的JAVA程序<br />
import java.sql.*; <br />
import java.io.OutputStream;<br />
import java.io.Writer;<br />
import java.sql.PreparedStatement;<br />
import java.sql.ResultSet;<br />
import oracle.jdbc.driver.*;<br />
public class TestProcedureOne {<br />
     public TestProcedureOne() {<br />
       }<br />
       public static void main(String[] args ){<br />
         String driver = "oracle.jdbc.driver.OracleDriver";<br />
         String strUrl = "jdbc:oracle:thin:@192.168.10.216:1521:ctbu"; <br />
         Statement stmt = null; <br />
         ResultSet rs = null; <br />
         Connection conn = null;<br />
         CallableStatement cstmt = null; <br />
         try {<br />
           Class.forName(driver);<br />
           conn =  DriverManager.getConnection(strUrl, "dbname", "password"); <br />
           CallableStatement proc = null; <br />
           proc = conn.prepareCall("{ call dbname.TESTA(?,?) }"); <br />
           proc.setString(1, "100"); <br />
           proc.setString(2, "TestOne"); <br />
           proc.execute();<br />
         }<br />
         catch (SQLException ex2) {<br />
           ex2.printStackTrace();<br />
         }<br />
         catch (Exception ex2) {<br />
           ex2.printStackTrace(); <br />
         }<br />
         finally{ <br />
           try {<br />
             if(rs != null){<br />
               rs.close(); <br />
               if(stmt!=null){ <br />
                 stmt.close();<br />
               } <br />
               if(conn!=null){<br />
                 conn.close(); <br />
               }<br />
             } <br />
           }<br />
           catch (SQLException ex1) {<br />
           }<br />
         }<br />
       } <br />
     }</font></span></span></p><p><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 0, 255);"><font color="#000000"><span style="color: rgb(0, 0, 0);">二：有返回值的存储过程（非列表）</span></font></span></span></p><p><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 0, 255);"><font color="#000000"><span style="color: rgb(0, 0, 0);">1、存储过程为<br />
CREATE OR REPLACE PROCEDURE TESTB(PARA1 IN VARCHAR2,PARA2 OUT VARCHAR2)  AS<br />
BEGIN<br />
    SELECT INTO PARA2 FROM TESTTB WHERE I_ID= PARA1;<br />
END TESTB;</span></font></span></span></p><p><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 0, 255);"><font color="#000000"><span style="color: rgb(0, 0, 0);"><span style="color: rgb(0, 0, 0);">2、JAVA代码<br />
public class TestProcedureTWO {<br />
  public TestProcedureTWO() {<br />
  }<br />
  public static void main(String[] args ){<br />
     String driver = "oracle.jdbc.driver.OracleDriver";<br />
     String strUrl = "jdbc:oracle:thin:@192.168.10.216:1521:ctbu"; <br />
     Statement stmt = null;<br />
     ResultSet rs = null;<br />
     Connection conn = null;<br />
     try {<br />
       Class.forName(driver);<br />
       conn =  DriverManager.getConnection(strUrl, "dbname", "password");<br />
       CallableStatement proc = null;<br />
       proc = conn.prepareCall("{ call HYQ.TESTB(?,?) }");<br />
       proc.setString(1, "100");<br />
       proc.registerOutParameter(2, Types.VARCHAR);<br />
       proc.execute();<br />
       String testPrint = proc.getString(2);<br />
       System.out.println("=testPrint=is="+testPrint);<br />
     }<br />
     catch (SQLException ex2) {<br />
       ex2.printStackTrace();<br />
     }<br />
     catch (Exception ex2) {<br />
       ex2.printStackTrace();<br />
     }<br />
     finally{<br />
       try {<br />
         if(rs != null){<br />
           rs.close();<br />
           if(stmt!=null){<br />
             stmt.close();<br />
           }<br />
           if(conn!=null){<br />
             conn.close();<br />
           }<br />
         }<br />
       }<br />
       catch (SQLException ex1) {<br />
       }<br />
     }<br />
  }<br />
}<br />
}<br />
注意，这里的proc.getString(2)中的数值2并非任意的，而是和存储过程中的out列对应的，如果out是在第一个位置，那就是
proc.getString(1)，如果是第三个位置，就是proc.getString(3)，当然也可以同时有多个返回值，那就是再多加几个out
参数了。<br /><br />
三：返回列表<br />
由于oracle存储过程没有返回值，它的所有返回值都是通过out参数来替代的，列表同样也不例外，但由于是集合，所以不能用一般的参数，必须要用pagkage了.所以要分两部分。<br />
1、在SQL*PLUS中建一个程序包</span></span></font></span></span></p><p>CREATE OR REPLACE PACKAGE TESTPACKAGE  AS  <br />
TYPE Test_CURSOR IS REF CURSOR; <br />
procedure TESTC(cur_ref out Test_CURSOR); <br />
end TESTPACKAGE;</p><p>建立存储过程，存储过程为：<br />
create or replace package body TESTPACKAGE as <br />
procedure TESTC(cur_ref out Test_CURSOR) is <br />
begin    <br />
OPEN cur_ref FOR SELECT * FROM T_TEST;<br />
end TESTC;<br />
END TESTPACKAGE;<br />
可以看到，它是把游标（可以理解为一个指针），作为一个out 参数来返回值的。<br />
JAVA程序如下：</p><p>import java.sql.*; <br />
import java.io.OutputStream;<br />
import java.io.Writer; <br />
import java.sql.PreparedStatement; <br />
import java.sql.ResultSet;<br />
import oracle.jdbc.driver.*;</p><p>public class TestProcedureOne {<br />
     public TestProcedureOne() {<br />
       } <br />
       public static void main(String[] args ){<br />
         String driver = "oracle.jdbc.driver.OracleDriver";<br />
         String strUrl = "jdbc:oracle:thin:@192.168.10.216:1521:ctbu";<br />
         Statement stmt = null; <br />
         ResultSet rs = null; <br />
         Connection conn = null; <br />
         CallableStatement cstmt = null;<br />
         try { <br />
           Class.forName(driver); <br />
           conn = DriverManager.getConnection(strUrl,"databasename" "password");<br />
           CallableStatement proc = null; <br />
           proc = conn.prepareCall("{ call cqsb.TESTA(?,?) }"); <br />
           proc.setString(1, "100"); <br />
           proc.setString(2, "TestOne"); <br />
           proc.execute(); <br />
         } <br />
         catch (SQLException ex2) {<br />
           ex2.printStackTrace(); <br />
         } <br />
         catch (Exception ex2) {<br />
           ex2.printStackTrace(); <br />
         } <br />
         finally{ <br />
           try { <br />
             if(rs != null){ <br />
               rs.close(); <br />
               if(stmt!=null){<br />
                 stmt.close(); <br />
               } <br />
               if(conn!=null){<br />
                 conn.close();<br />
               } <br />
             } <br />
           } <br />
           catch (SQLException ex1) {<br />
           }<br />
         } <br />
       } <br />
     }</p><p>特别注意：<br />
1、在执行前一定要先把oracle的驱动包放到class路径里。<br />
2、Toad在我建立存储过程中搞了很多莫名的错误，多数是没有创建成功而不报错，<br />
或者是创建有误而不提示，应当引起重视。所以最好还是在SQL*PLUS玩这些。<br />
3、在SQL*PLUS中的换行是无效的，要换行的时候一定要空格结尾，特别是你直接复制代码的时候！</p></div><br /><img src ="http://www.blogjava.net/leekiang/aggbug/290778.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2009-08-12 11:46 <a href="http://www.blogjava.net/leekiang/archive/2009/08/12/290778.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ORA-00060:等待资源的时候检测到死锁</title><link>http://www.blogjava.net/leekiang/archive/2009/07/31/289194.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Thu, 30 Jul 2009 16:08:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2009/07/31/289194.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/289194.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2009/07/31/289194.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/289194.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/289194.html</trackback:ping><description><![CDATA[
		<br />参见：<br />http://www.d9soft.com/article/353/Article25047_1.htm<br />http://topic.csdn.net/u/20070719/09/13f24bd3-5fc4-43dc-b1e4-5475718031b4.html<br /><img src ="http://www.blogjava.net/leekiang/aggbug/289194.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2009-07-31 00:08 <a href="http://www.blogjava.net/leekiang/archive/2009/07/31/289194.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>两阶段提交</title><link>http://www.blogjava.net/leekiang/archive/2009/01/23/252417.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Thu, 22 Jan 2009 17:22:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2009/01/23/252417.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/252417.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2009/01/23/252417.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/252417.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/252417.html</trackback:ping><description><![CDATA[Two-Phase Commit<br /><br />http://www.blogjava.net/javababy/archive/2006/06/01/49515.html<br />http://blog.csdn.net/junli0310/archive/2007/09/12/1781736.aspx<br /><img src ="http://www.blogjava.net/leekiang/aggbug/252417.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2009-01-23 01:22 <a href="http://www.blogjava.net/leekiang/archive/2009/01/23/252417.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>悲观锁与乐观锁(转)</title><link>http://www.blogjava.net/leekiang/archive/2008/10/19/235252.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Sat, 18 Oct 2008 16:51:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2008/10/19/235252.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/235252.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2008/10/19/235252.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/235252.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/235252.html</trackback:ping><description><![CDATA[
		<p class="MsoNormal">
				<span style="font-family: 宋体;">离线并发的来源</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>
				</span>
				<span style="font-family: 宋体;">在</span>
				<span lang="EN-US">Web</span>
				<span style="font-family: 宋体;">项目中，离线并发显得尤其严重。例如，用户</span>
				<span lang="EN-US">A</span>
				<span style="font-family: 宋体;">和用户</span>
				<span lang="EN-US">B</span>
				<span style="font-family: 宋体;">同时修改数据库中的某张表的</span>
				<span lang="EN-US">R</span>
				<span style="font-family: 宋体;">行，加入</span>
				<span lang="EN-US">R</span>
				<span style="font-family: 宋体;">行有两个字段分别是</span>
				<span lang="EN-US">C1</span>
				<span style="font-family: 宋体;">，</span>
				<span lang="EN-US">C2</span>
				<span style="font-family: 宋体;">。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>
				</span>
				<span style="font-family: 宋体;">假如按照如下过程修改：</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>1 </span>
				<span style="font-family: 宋体;">用户</span>
				<span lang="EN-US">A</span>
				<span style="font-family: 宋体;">将数据</span>
				<span lang="EN-US">R</span>
				<span style="font-family: 宋体;">（</span>
				<span lang="EN-US">C1,C2</span>
				<span style="font-family: 宋体;">）读取到</span>
				<span lang="EN-US">A</span>
				<span style="font-family: 宋体;">的浏览器中。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>2 </span>
				<span style="font-family: 宋体;">用户</span>
				<span lang="EN-US">B</span>
				<span style="font-family: 宋体;">将数据</span>
				<span lang="EN-US">R</span>
				<span style="font-family: 宋体;">（</span>
				<span lang="EN-US">C1,C2</span>
				<span style="font-family: 宋体;">）读取到</span>
				<span lang="EN-US">B</span>
				<span style="font-family: 宋体;">的浏览器中。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>3 </span>
				<span style="font-family: 宋体;">用户</span>
				<span lang="EN-US">A</span>
				<span style="font-family: 宋体;">在浏览器上将数据修改为</span>
				<span lang="EN-US">R</span>
				<span style="font-family: 宋体;">（</span>
				<span lang="EN-US">C1’</span>
				<span style="font-family: 宋体;">，</span>
				<span lang="EN-US">C2</span>
				<span style="font-family: 宋体;">），同时更新到数据库。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>4 </span>
				<span style="font-family: 宋体;">用户</span>
				<span lang="EN-US">B</span>
				<span style="font-family: 宋体;">在浏览器上将数据修改为</span>
				<span lang="EN-US">R</span>
				<span style="font-family: 宋体;">（</span>
				<span lang="EN-US">C1</span>
				<span style="font-family: 宋体;">，</span>
				<span lang="EN-US">C2’</span>
				<span style="font-family: 宋体;">），同时更新到数据库。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>
				</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>
				</span>
				<span style="font-family: 宋体;">上述过程存在两个问题，第一，第</span>
				<span lang="EN-US">4</span>
				<span style="font-family: 宋体;">步</span>
				<span lang="EN-US">B</span>
				<span style="font-family: 宋体;">在修改数据的时候数据库中的数据和</span>
				<span lang="EN-US">B</span>
				<span style="font-family: 宋体;">的浏览器中数据已经不一致了；第二，如果程序按照哪个字段变化在数据库中更新哪个字段的方式处理的话，那么经过上述四步修改，数据库中</span>
				<span lang="EN-US">R</span>
				<span style="font-family: 宋体;">行的内容是（</span>
				<span lang="EN-US">C1’,C2’</span>
				<span style="font-family: 宋体;">），这和</span>
				<span lang="EN-US">A</span>
				<span style="font-family: 宋体;">或者</span>
				<span lang="EN-US">B</span>
				<span style="font-family: 宋体;">的想法都不同（</span>
				<span lang="EN-US">A</span>
				<span style="font-family: 宋体;">认为是（</span>
				<span lang="EN-US">C1’</span>
				<span style="font-family: 宋体;">，</span>
				<span lang="EN-US">C2</span>
				<span style="font-family: 宋体;">），</span>
				<span lang="EN-US">B</span>
				<span style="font-family: 宋体;">认为是（</span>
				<span lang="EN-US">C1</span>
				<span style="font-family: 宋体;">，</span>
				<span lang="EN-US">C2’</span>
				<span style="font-family: 宋体;">））。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<o:p> </o:p>
				</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>
				</span>
				<span style="font-family: 宋体;">上述过程中</span>
				<span lang="EN-US">A</span>
				<span style="font-family: 宋体;">对数据库的修改过程或者</span>
				<span lang="EN-US">B</span>
				<span style="font-family: 宋体;">对数据库的修改过程，都是无法根据数据库的最新内容做修改，所以成为离线。</span>
				<span lang="EN-US">A</span>
				<span style="font-family: 宋体;">和</span>
				<span lang="EN-US">B</span>
				<span style="font-family: 宋体;">同时对记录</span>
				<span lang="EN-US">R</span>
				<span style="font-family: 宋体;">进行就该叫离线。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>
				</span>
				<span style="font-family: 宋体;">以上的环境叫离线并发。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>
				</span>
				<span style="font-family: 宋体;">那么如何解决离线并发过程中遇到的问题呢？我们引入锁机制。</span>
		</p>
		<p class="MsoNormal">
				<span style="font-family: 宋体;">锁机制</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>
				</span>
				<span style="font-family: 宋体;">锁机制，就是在需要修改的数据上加互斥锁，通过互斥锁避免数据被同时修改。锁机制更具其应用环境又分为<strong style="">乐观锁</strong>和<strong style="">悲观锁</strong></span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>
				</span>
				<span style="font-family: 宋体;">乐观锁</span>
		</p>
		<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal">
				<span style="font-family: 宋体;">乐观锁，指认为冲突很少发生，所以只是在数据修改的时候比较修改的基础数据和数据库中的数据是否相同，相同则修改，否则提示用户重新装入数据库中已经变化的数据。</span>
		</p>
		<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal">
				<span style="font-family: 宋体;">实现方法</span>
				<span lang="EN-US">1</span>
				<span style="font-family: 宋体;">：在进行</span>
				<span lang="EN-US">update</span>
				<span style="font-family: 宋体;">的时候使用</span>
				<span lang="EN-US">where</span>
				<span style="font-family: 宋体;">条件，在</span>
				<span lang="EN-US">Where</span>
				<span style="font-family: 宋体;">标间中比较所有上一步中查询得到的数据。如果数据库中的数据没有变化，则</span>
				<span lang="EN-US">update</span>
				<span style="font-family: 宋体;">可以更新到内容，否则</span>
				<span lang="EN-US">update</span>
				<span style="font-family: 宋体;">语句不能更新到内容，可以根据</span>
				<span lang="EN-US">update</span>
				<span style="font-family: 宋体;">的返回值确定更新是否成功。</span>
		</p>
		<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal">
				<span style="font-family: 宋体;">实现方法</span>
				<span lang="EN-US">2</span>
				<span style="font-family: 宋体;">：在每一个表中追加一个特殊字段，类型为</span>
				<span lang="EN-US">timestamp</span>
				<span style="font-family: 宋体;">，每次更新的时候比较这个字段的值是否一致，如果一致，则更新，同时将这个字段更新为当前时间，否则，说明数据已经变更。这也可以使用</span>
				<span lang="EN-US">update</span>
				<span style="font-family: 宋体;">加上</span>
				<span lang="EN-US">where</span>
				<span style="font-family: 宋体;">实现。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>
				</span>
				<span style="font-family: 宋体;">悲观锁</span>
		</p>
		<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal">
				<span style="font-family: 宋体;">悲观锁指，需要修改的数据，在读取的时候就对数据加锁，其他用户在准备修改，读取数据的阶段判断数据是否上锁，以此来决定是否进行修改前的读操作。</span>
		</p>
		<p class="MsoNormal">
				<span lang="EN-US">
						<span style="">         </span>
						<span style="">         </span>
				</span>
				<span style="font-family: 宋体;">实现方法：</span>
		</p>
		<p style="margin-left: 21pt;" class="MsoNormal">
				<span lang="EN-US">
						<span style="">                   </span>
				</span>
				<span style="font-family: 宋体;">通常在数据库中建立一张</span>
				<span lang="EN-US">lock</span>
				<span style="font-family: 宋体;">表，该表的字段包括，表明，唯一索引，时间，用户信息等。</span>
		</p>
		<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal">
				<span style="font-family: 宋体;">在用户读取数据准备修改的时候，首先判断</span>
				<span lang="EN-US">lock</span>
				<span style="font-family: 宋体;">表中是否存在自己将要读取的数据。</span>
		</p>
		<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal">
				<span style="font-family: 宋体;">如果不存在，则在</span>
				<span lang="EN-US">lock</span>
				<span style="font-family: 宋体;">表中添加一条记录，记录对那张表的哪行数据进行修改；如果存在，在判断时间字段是否超时。</span>
		</p>
		<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal">
				<span style="font-family: 宋体;">如果超时，则更新</span>
				<span lang="EN-US">lock</span>
				<span style="font-family: 宋体;">表中本条记录的时间字段。<strong style="">（防止死锁的必要手段）</strong></span>
		</p>
		<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal">
				<span style="font-family: 宋体;">如果存在，也不超时，说明本条记录正在被其他用户修改，则返回并发信息。</span>
		</p>
		<p style="margin-left: 21pt; text-indent: 21pt;" class="MsoNormal">
				<span style="font-family: 宋体;">出处:http://blog.csdn.net/struts2/archive/2007/08/14/1742686.aspx<br /></span>
		</p>
<img src ="http://www.blogjava.net/leekiang/aggbug/235252.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2008-10-19 00:51 <a href="http://www.blogjava.net/leekiang/archive/2008/10/19/235252.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>p6spy的配置</title><link>http://www.blogjava.net/leekiang/archive/2008/09/26/231385.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Fri, 26 Sep 2008 14:32:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2008/09/26/231385.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/231385.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2008/09/26/231385.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/231385.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/231385.html</trackback:ping><description><![CDATA[tomcat里配p6spy,如果tomcat在program files下，会报找不到驱动的错误，看来目录名不能有空格<br /><img src ="http://www.blogjava.net/leekiang/aggbug/231385.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2008-09-26 22:32 <a href="http://www.blogjava.net/leekiang/archive/2008/09/26/231385.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个事务的问题</title><link>http://www.blogjava.net/leekiang/archive/2008/06/26/210773.html</link><dc:creator>leekiang</dc:creator><author>leekiang</author><pubDate>Thu, 26 Jun 2008 03:24:00 GMT</pubDate><guid>http://www.blogjava.net/leekiang/archive/2008/06/26/210773.html</guid><wfw:comment>http://www.blogjava.net/leekiang/comments/210773.html</wfw:comment><comments>http://www.blogjava.net/leekiang/archive/2008/06/26/210773.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/leekiang/comments/commentRss/210773.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/leekiang/services/trackbacks/210773.html</trackback:ping><description><![CDATA[我单位物资系统：库存表kcb，库存明细kcmx  <br /><br />当发生一笔动态的时候，先查询库存表中的库存数量，然后加上增减数量，得到新库存，update，commit；  <br /><br />接着把库存数量，增减数量，更改时间分别插入到库存明细：前次数量，增减数量，更改时间。  <br /><br />问
题：现在有两条数据更改时间很接近  a  10:51:47:01b  10:51:46:25 
.也就是说两条数据先后更新，而且更新的是同样一笔物资。于是，a 
条记录得到的前存数量和b条记录得到的前存数量一样，（好像叫读脏数？）于是记录b的更新就被当作不存在了！  <br /><br />系统在随后的更新中查到的是记录a更新候的数据，一切正常，唯有记录b  被忽略了；（于是库存错了，领导批了）  <br /><br />  <br /><br />还有一个奇怪的问题，就是库存明细的查询是用存储过程作的，为什么select到pb的数据窗口之后别的数据都是按时间顺序排列，唯有上面两条，a在b之前！时间也会错？相差太近？  <br /><br />我以后怎么办？高人教我 <br /><br />http://blog.csdn.net/qiume/archive/2009/02/26/3938382.aspx<br />对数据库中的数据修改都是在内存中完成的，这些修改的结果可能已经写到硬盘也可能没有写到硬盘，如果在操作过程中，发生断电或系统错误等故障，数据库可以
保证未结束的事务对数据库的数据修改结果即使已经写入磁盘，在下次数据库启动后也会被全部撤销；而对于结束的事务，即使其修改的结果还未写入磁盘，在数据
库下次启动后会通过事务日志中的记录进行“重做”，即把丢失的数据修改结果重新生成，并写入磁盘，从而保证结束事务对数据修改的永久化。这样也保证了事务
中的操作要么全部完成，要么全部撤销。<br /><img src ="http://www.blogjava.net/leekiang/aggbug/210773.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/leekiang/" target="_blank">leekiang</a> 2008-06-26 11:24 <a href="http://www.blogjava.net/leekiang/archive/2008/06/26/210773.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>