﻿<?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-kevin-随笔分类-java</title><link>http://www.blogjava.net/kevinfriend/category/12776.html</link><description /><language>zh-cn</language><lastBuildDate>Fri, 02 Mar 2007 05:49:58 GMT</lastBuildDate><pubDate>Fri, 02 Mar 2007 05:49:58 GMT</pubDate><ttl>60</ttl><item><title>jdbc-batch processing</title><link>http://www.blogjava.net/kevinfriend/archive/2006/10/11/74550.html</link><dc:creator>康文</dc:creator><author>康文</author><pubDate>Wed, 11 Oct 2006 06:40:00 GMT</pubDate><guid>http://www.blogjava.net/kevinfriend/archive/2006/10/11/74550.html</guid><wfw:comment>http://www.blogjava.net/kevinfriend/comments/74550.html</wfw:comment><comments>http://www.blogjava.net/kevinfriend/archive/2006/10/11/74550.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kevinfriend/comments/commentRss/74550.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kevinfriend/services/trackbacks/74550.html</trackback:ping><description><![CDATA[
		<p>the addBatch() method is basically nothing more than a tool fro assigning a bunch of sql statements to a jdbc statement object for execution together</p>
		<p>PreparedStatement stmt=conn.prepareStatement(<br />      "update account set balance=? where acct_id=?");<br />int[] rows;<br />for(int i=0;i&lt;accts.length;i++){<br />    stmt.setInt(1,i);<br />    stmt.setLong(2,i);<br />    stmt.addBatch();<br />  }<br />rows=stemt.executeBatch();</p>
<img src ="http://www.blogjava.net/kevinfriend/aggbug/74550.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kevinfriend/" target="_blank">康文</a> 2006-10-11 14:40 <a href="http://www.blogjava.net/kevinfriend/archive/2006/10/11/74550.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>翻页的实现</title><link>http://www.blogjava.net/kevinfriend/archive/2006/10/11/74549.html</link><dc:creator>康文</dc:creator><author>康文</author><pubDate>Wed, 11 Oct 2006 06:39:00 GMT</pubDate><guid>http://www.blogjava.net/kevinfriend/archive/2006/10/11/74549.html</guid><wfw:comment>http://www.blogjava.net/kevinfriend/comments/74549.html</wfw:comment><comments>http://www.blogjava.net/kevinfriend/archive/2006/10/11/74549.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kevinfriend/comments/commentRss/74549.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kevinfriend/services/trackbacks/74549.html</trackback:ping><description><![CDATA[
		<p>1 oracle 的实现<br /> 语句一<br />SELECT ID, [FIELD_NAME,...] FROM TABLE_NAME WHERE ID IN ( SELECT ID FROM (SELECT ROWNUM AS NUMROW, ID FROM TABLE_NAME WHERE 条件1 ORDER BY 条件2) WHERE NUMROW &gt; 80 AND NUMROW &lt; 100 ) ORDER BY 条件3; <br />语句二：<br />SELECT * FROM (( SELECT ROWNUM AS NUMROW, c.* from (select [FIELD_NAME,...] FROM TABLE_NAME WHERE 条件1 ORDER BY 条件2) c) WHERE NUMROW &gt; 80 AND NUMROW &lt; 100 ) ORDER BY 条件3;</p>
		<p>select * from (select rownum as numrow from table_name where numrow&gt;80 and numrow&lt;100 )<br />不能直接使用 select * from rownum&gt;100 and rownum&lt;200; <br />in oracle return null;<br />2 sql server 的实现<br />3 mysql 的实现</p>
		<p>select id from table_name where id in<br />                                   select * from (select rownum as numrow ,id from tabl_name) <br />                                             where numrow&gt;80 and num&lt;100;                                            <br />                                                 </p>
<img src ="http://www.blogjava.net/kevinfriend/aggbug/74549.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kevinfriend/" target="_blank">康文</a> 2006-10-11 14:39 <a href="http://www.blogjava.net/kevinfriend/archive/2006/10/11/74549.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jdbc-prepare sql</title><link>http://www.blogjava.net/kevinfriend/archive/2006/10/11/74548.html</link><dc:creator>康文</dc:creator><author>康文</author><pubDate>Wed, 11 Oct 2006 06:38:00 GMT</pubDate><guid>http://www.blogjava.net/kevinfriend/archive/2006/10/11/74548.html</guid><wfw:comment>http://www.blogjava.net/kevinfriend/comments/74548.html</wfw:comment><comments>http://www.blogjava.net/kevinfriend/archive/2006/10/11/74548.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kevinfriend/comments/commentRss/74548.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kevinfriend/services/trackbacks/74548.html</trackback:ping><description><![CDATA[1 prepared sql<br />oracle provide two kinds of prepared SQL prepared statements and store procedures.Prepared SQL provide an advantage over the simple sql statements you have convered so far.if you execute the same prepared sql more than once,the database remains ready for your sql without having to rebuild the query plan.<br /> 1) Prepared Statements<br /> PreparedStatement statement=conn.preparedStatement(<br />     "update account set balance=? where id=?");<br /> for(int i=0;i&lt;accounts.length;i++){<br />    statement.setFloat(1,accounts[i].getBalance());<br />    statement.setInt(2,i);<br />    statement.execut();<br />    stateement.clearParameters();<br /> }<br /> commit();<br /> statement.close;<br /> 2) Stored Procedure<br /> try { <br />    CallableStatement statement; <br />    int i; <br /> <br />    statement = c.prepareCall("{call sp_interest[(?,?)]}"); <br /> <br />    statement.registerOutParameter(2, java.sql.Types.FLOAT); <br />    for(i=1; i&lt;accounts.length; i++) { <br />        statement.setInt(1, accounts[i].getId( )); <br />        statement.execute( ); <br />        System.out.println("New balance: " + statement.getFloat(2)); <br />    } <br />    c.commit( ); <br />    statement.close( ); <br />    c.close( ); <br />} <img src ="http://www.blogjava.net/kevinfriend/aggbug/74548.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kevinfriend/" target="_blank">康文</a> 2006-10-11 14:38 <a href="http://www.blogjava.net/kevinfriend/archive/2006/10/11/74548.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java 调用存储过程 转载</title><link>http://www.blogjava.net/kevinfriend/archive/2006/10/11/74547.html</link><dc:creator>康文</dc:creator><author>康文</author><pubDate>Wed, 11 Oct 2006 06:37:00 GMT</pubDate><guid>http://www.blogjava.net/kevinfriend/archive/2006/10/11/74547.html</guid><wfw:comment>http://www.blogjava.net/kevinfriend/comments/74547.html</wfw:comment><comments>http://www.blogjava.net/kevinfriend/archive/2006/10/11/74547.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kevinfriend/comments/commentRss/74547.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kevinfriend/services/trackbacks/74547.html</trackback:ping><description><![CDATA[
		<p>本文阐述了怎么使用DBMS存储过程。我阐述了使用存储过程的基本的和高级特性，比如返回ResultSet。本文假设你对DBMS和JDBC已经非常熟悉，也假设你能够毫无障碍地阅读其它语言写成的代码（即不是Java的语言），但是，并不要求你有任何存储过程的编程经历。 <br />存储过程是指保存在数据库并在数据库端执行的程序。你可以使用特殊的语法在Java类中调用存储过程。在调用时，存储过程的名称及指定的参数通过JDBC连接发送给DBMS，执行存储过程并通过连接（如果有）返回结果。 <br />使用存储过程拥有和使用基于EJB或CORBA这样的应用服务器一样的好处。区别是存储过程可以从很多流行的DBMS中免费使用，而应用服务器大都非常昂贵。这并不只是许可证费用的问题。使用应用服务器所需要花费的管理、编写代码的费用，以及客户程序所增加的复杂性，都可以通过DBMS中的存储过程所整个地替代。 <br />你可以使用Java，Python，Perl或C编写存储过程，但是通常使用你的DBMS所指定的特定语言。Oracle使用PL/SQL，PostgreSQL使用pl/pgsql，DB2使用Procedural SQL。这些语言都非常相似。在它们之间移植存储过程并不比在Sun的EJB规范不同实现版本之间移植Session Bean困难。并且，存储过程是为嵌入SQL所设计，这使得它们比Java或C等语言更加友好地方式表达数据库的机制。 <br />因为存储过程运行在DBMS自身，这可以帮助减少应用程序中的等待时间。不是在Java代码中执行4个或5个SQL语句，而只需要在服务器端执行1个存储过程。网络上的数据往返次数的减少可以戏剧性地优化性能。 </p>
		<p>使用存储过程 </p>
		<p>简单的老的JDBC通过CallableStatement类支持存储过程的调用。该类实际上是PreparedStatement的一个子类。假设我们有一个poets数据库。数据库中有一个设置诗人逝世年龄的存储过程。下面是对老酒鬼Dylan Thomas（old soak Dylan Thomas，不指定是否有关典故、文化，请批评指正。译注）进行调用的详细代码： </p>
		<p>try{ <br />int age = 39; </p>
		<p>String poetName = "dylan thomas"; </p>
		<p>CallableStatement proc = connection.prepareCall("{ call set_death_age(?, ?) }"); </p>
		<p>proc.setString(1, poetName); </p>
		<p>proc.setInt(2, age); </p>
		<p>cs.execute(); </p>
		<p>}catch (SQLException e){ // ....} </p>
		<p>传给prepareCall方法的字串是存储过程调用的书写规范。它指定了存储过程的名称，？代表了你需要指定的参数。 <br />和JDBC集成是存储过程的一个很大的便利：为了从应用中调用存储过程，不需要存根（stub）类或者配置文件，除了你的DBMS的JDBC驱动程序外什么也不需要。 <br />当这段代码执行时，数据库的存储过程就被调用。我们没有去获取结果，因为该存储过程并不返回结果。执行成功或失败将通过例外得知。失败可能意味着调用存储过程时的失败（比如提供的一个参数的类型不正确），或者一个应用程序的失败（比如抛出一个例外指示在poets数据库中并不存在“Dylan Thomas”） </p>
		<p>结合SQL操作与存储过程 </p>
		<p>映射Java对象到SQL表中的行相当简单，但是通常需要执行几个SQL语句；可能是一个SELECT查找ID，然后一个INSERT插入指定ID的数据。在高度规格化（符合更高的范式，译注）的数据库模式中，可能需要多个表的更新，因此需要更多的语句。Java代码会很快地膨胀，每一个语句的网络开销也迅速增加。 <br />将这些SQL语句转移到一个存储过程中将大大简化代码，仅涉及一次网络调用。所有关联的SQL操作都可以在数据库内部发生。并且，存储过程语言，例如PL/SQL，允许使用SQL语法，这比Java代码更加自然。下面是我们早期的存储过程，使用Oracle的PL/SQL语言编写： </p>
		<p>create procedure set_death_age(poet VARCHAR2, poet_age NUMBER) </p>
		<p>poet_id NUMBER; </p>
		<p>begin SELECT id INTO poet_id FROM poets WHERE name = poet; </p>
		<p>INSERT INTO deaths (mort_id, age) VALUES (poet_id, poet_age); </p>
		<p>end set_death_age; </p>
		<p>很独特？不。我打赌你一定期待看到一个poets表上的UPDATE。这也暗示了使用存储过程实现是多么容易的一件事情。set_death_age几乎可以肯定是一个很烂的实现。我们应该在poets表中添加一列来存储逝世年龄。Java代码中并不关心数据库模式是怎么实现的，因为它仅调用存储过程。我们以后可以改变数据库模式以提高性能，但是我们不必修改我们代码。 <br />下面是调用上面存储过程的Java代码： </p>
		<p>public static void setDeathAge(Poet dyingBard, int age) throws SQLException{ </p>
		<p>Connection con = null; </p>
		<p>CallableStatement proc = null; </p>
		<p>try { </p>
		<p>con = connectionPool.getConnection(); </p>
		<p>proc = con.prepareCall("{ call set_death_age(?, ?) }"); </p>
		<p>proc.setString(1, dyingBard.getName()); </p>
		<p>proc.setInt(2, age); </p>
		<p>proc.execute(); </p>
		<p>}  </p>
		<p>finally { </p>
		<p>try { proc.close(); } </p>
		<p>catch (SQLException e) {} </p>
		<p>con.close(); </p>
		<p>} </p>
		<p>} </p>
		<p>为了确保可维护性，建议使用像这儿这样的static方法。这也使得调用存储过程的代码集中在一个简单的模版代码中。如果你用到许多存储过程，就会发现仅需要拷贝、粘贴就可以创建新的方法。因为代码的模版化，甚至也可以通过脚本自动生产调用存储过程的代码。 </p>
		<p>Functions </p>
		<p>存储过程可以有返回值，所以CallableStatement类有类似getResultSet这样的方法来获取返回值。当存储过程返回一个值时，你必须使用registerOutParameter方法告诉JDBC驱动器该值的SQL类型是什么。你也必须调整存储过程调用来指示该过程返回一个值。 <br />下面接着上面的例子。这次我们查询Dylan Thomas逝世时的年龄。这次的存储过程使用PostgreSQL的pl/pgsql： </p>
		<p>create function snuffed_it_when (VARCHAR) returns integer ''declare </p>
		<p>poet_id NUMBER; </p>
		<p>poet_age NUMBER; </p>
		<p>begin </p>
		<p>--first get the id associated with the poet. </p>
		<p>SELECT id INTO poet_id FROM poets WHERE name = $1; </p>
		<p>--get and return the age. </p>
		<p>SELECT age INTO poet_age FROM deaths WHERE mort_id = poet_id; </p>
		<p>return age; </p>
		<p>end;'' language ''pl/pgsql''; </p>
		<p>另外，注意pl/pgsql参数名通过Unix和DOS脚本的$n语法引用。同时，也注意嵌入的注释，这是和Java代码相比的另一个优越性。在Java中写这样的注释当然是可以的，但是看起来很凌乱，并且和SQL语句脱节，必须嵌入到Java String中。 <br />下面是调用这个存储过程的Java代码： </p>
		<p>connection.setAutoCommit(false); </p>
		<p>CallableStatement proc = connection.prepareCall("{ ? = call snuffed_it_when(?) }"); </p>
		<p>proc.registerOutParameter(1, Types.INTEGER); </p>
		<p>proc.setString(2, poetName); </p>
		<p>cs.execute(); </p>
		<p>int age = proc.getInt(2); </p>
		<p>如果指定了错误的返回值类型会怎样？那么，当调用存储过程时将抛出一个RuntimeException，正如你在ResultSet操作中使用了一个错误的类型所碰到的一样。 </p>
		<p>复杂的返回值 </p>
		<p>关于存储过程的知识，很多人好像就熟悉我们所讨论的这些。如果这是存储过程的全部功能，那么存储过程就不是其它远程执行机制的替换方案了。存储过程的功能比这强大得多。 <br />当你执行一个SQL查询时，DBMS创建一个叫做cursor（游标）的数据库对象，用于在返回结果中迭代每一行。ResultSet是当前时间点的游标的一个表示。这就是为什么没有缓存或者特定数据库的支持，你只能在ResultSet中向前移动。 <br />某些DBMS允许从存储过程中返回游标的一个引用。JDBC并不支持这个功能，但是Oracle、PostgreSQL和DB2的JDBC驱动器都支持在ResultSet上打开到游标的指针（pointer）。 <br />设想列出所有没有活到退休年龄的诗人，下面是完成这个功能的存储过程，返回一个打开的游标，同样也使用PostgreSQL的pl/pgsql语言： </p>
		<p>create procedure list_early_deaths () return refcursor as ''declare </p>
		<p>toesup refcursor; </p>
		<p>begin </p>
		<p>open toesup for SELECT poets.name, deaths.age FROM poets, deaths -- all entries in deaths are for poets. -- but the table might become generic. </p>
		<p>WHERE poets.id = deaths.mort_id AND deaths.age &lt; 60; </p>
		<p>return toesup; </p>
		<p>end;'' language ''plpgsql''; </p>
		<p>下面是调用该存储过程的Java方法，将结果输出到PrintWriter： <br />PrintWriter: </p>
		<p>static void sendEarlyDeaths(PrintWriter out){ </p>
		<p>Connection con = null; </p>
		<p>CallableStatement toesUp = null; </p>
		<p>try { </p>
		<p>con = ConnectionPool.getConnection(); </p>
		<p>// PostgreSQL needs a transaction to do this... con. </p>
		<p>setAutoCommit(false); // Setup the call. </p>
		<p>CallableStatement toesUp = connection.prepareCall("{ ? = call list_early_deaths () }"); </p>
		<p>toesUp.registerOutParameter(1, Types.OTHER); </p>
		<p>toesUp.execute(); </p>
		<p>ResultSet rs = (ResultSet) toesUp.getObject(1); </p>
		<p>while (rs.next()) { </p>
		<p>String name = rs.getString(1); </p>
		<p>int age = rs.getInt(2); </p>
		<p>out.println(name + " was " + age + " years old."); </p>
		<p>} </p>
		<p>rs.close(); </p>
		<p>} </p>
		<p>catch (SQLException e) { // We should protect these calls. toesUp.close(); con.close(); </p>
		<p>} </p>
		<p>} </p>
		<p>因为JDBC并不直接支持从存储过程中返回游标，我们使用Types.OTHER来指示存储过程的返回类型，然后调用getObject()方法并对返回值进行强制类型转换。 <br />这个调用存储过程的Java方法是mapping的一个好例子。Mapping是对一个集上的操作进行抽象的方法。不是在这个过程上返回一个集，我们可以把操作传送进去执行。本例中，操作就是把ResultSet打印到一个输出流。这是一个值得举例的很常用的例子，下面是调用同一个存储过程的另外一个方法实现： </p>
		<p>public class ProcessPoetDeaths{ </p>
		<p>public abstract void sendDeath(String name, int age); </p>
		<p>} </p>
		<p>static void mapEarlyDeaths(ProcessPoetDeaths mapper){ </p>
		<p>Connection con = null; </p>
		<p>CallableStatement toesUp = null; </p>
		<p>try { </p>
		<p>con = ConnectionPool.getConnection(); </p>
		<p>con.setAutoCommit(false); </p>
		<p>CallableStatement toesUp = connection.prepareCall("{ ? = call list_early_deaths () }"); </p>
		<p>toesUp.registerOutParameter(1, Types.OTHER); </p>
		<p>toesUp.execute(); </p>
		<p>ResultSet rs = (ResultSet) toesUp.getObject(1); </p>
		<p>while (rs.next()) { </p>
		<p>String name = rs.getString(1); </p>
		<p>int age = rs.getInt(2); </p>
		<p>mapper.sendDeath(name, age); </p>
		<p>} </p>
		<p>rs.close(); </p>
		<p>} catch (SQLException e) { // We should protect these calls. toesUp.close(); </p>
		<p>con.close(); </p>
		<p>} </p>
		<p>} </p>
		<p>这允许在ResultSet数据上执行任意的处理，而不需要改变或者复制获取ResultSet的方法： </p>
		<p>static void sendEarlyDeaths(final PrintWriter out){ </p>
		<p>ProcessPoetDeaths myMapper = new ProcessPoetDeaths() { </p>
		<p>public void sendDeath(String name, int age) { </p>
		<p>out.println(name + " was " + age + " years old."); </p>
		<p>} </p>
		<p>}; </p>
		<p>mapEarlyDeaths(myMapper); </p>
		<p>} </p>
		<p>这个方法使用ProcessPoetDeaths的一个匿名实例调用mapEarlyDeaths。该实例拥有sendDeath方法的一个实现，和我们上面的例子一样的方式把结果写入到输出流。当然，这个技巧并不是存储过程特有的，但是和存储过程中返回的ResultSet结合使用，是一个非常强大的工具。 </p>
		<p>结论 </p>
		<p>存储过程可以帮助你在代码中分离逻辑，这基本上总是有益的。这个分离的好处有： <br />&amp;#8226; 快速创建应用，使用和应用一起改变和改善的数据库模式。 <br />&amp;#8226; 数据库模式可以在以后改变而不影响Java对象，当我们完成应用后，可以重新设计更好的模式。 <br />&amp;#8226; 存储过程通过更好的SQL嵌入使得复杂的SQL更容易理解。 <br />&amp;#8226; 编写存储过程比在Java中编写嵌入的SQL拥有更好的工具－－大部分编辑器都提供语法高亮！ <br />&amp;#8226; 存储过程可以在任何SQL命令行中测试，这使得调试更加容易。 </p>
		<p>并不是所有的数据库都支持存储过程，但是存在许多很棒的实现，包括免费/开源的和非免费的，所以移植并不是一个问题。Oracle、PostgreSQL和DB2都有类似的存储过程语言，并且有在线的社区很好地支持。 <br />存储过程工具很多，有像TOAD或TORA这样的编辑器、调试器和IDE，提供了编写、维护PL/SQL或pl/pgsql的强大的环境。 <br />存储过程确实增加了你的代码的开销，但是它们和大多数的应用服务器相比，开销小得多。如果你的代码复杂到需要使用DBMS，我建议整个采用存储过程的方式。</p>
<img src ="http://www.blogjava.net/kevinfriend/aggbug/74547.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kevinfriend/" target="_blank">康文</a> 2006-10-11 14:37 <a href="http://www.blogjava.net/kevinfriend/archive/2006/10/11/74547.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> OpenSessionInViewFilter解决Web应用程序的问题 转自：Potain 的BLOG</title><link>http://www.blogjava.net/kevinfriend/archive/2006/09/26/71920.html</link><dc:creator>康文</dc:creator><author>康文</author><pubDate>Tue, 26 Sep 2006 03:01:00 GMT</pubDate><guid>http://www.blogjava.net/kevinfriend/archive/2006/09/26/71920.html</guid><wfw:comment>http://www.blogjava.net/kevinfriend/comments/71920.html</wfw:comment><comments>http://www.blogjava.net/kevinfriend/archive/2006/09/26/71920.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kevinfriend/comments/commentRss/71920.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kevinfriend/services/trackbacks/71920.html</trackback:ping><description><![CDATA[
		<div class="snip-title">
				<h1 class="snip-name">OpenSessionInView </h1>
				<div class="snip-info">Created by <a href="http://www.aspectoriented.org:9080//space/potian"><font color="#4a664d">potian</font></a>. Last edited by <a href="http://www.aspectoriented.org:9080//space/admin"><font color="#4a664d">admin</font></a> 61 days ago. Viewed 181 times.</div>
				<div class="snip-buttons">
						<span class="inactive">[edit]</span>
						<span class="inactive">[attach]</span>
				</div>
		</div>
		<div class="snip-content" id="snip-content">
				<div class="snip-attachments">
				</div>Hibernate的Lazy初始化1:n关系时，你必须保证是在同一个Session内部使用这个关系集合，不然Hiernate将抛出例外。 
<p class="paragraph">另外，你不愿意你的DAO测试代码每次都打开关系Session，因此，我们一般会采用OpenSessionInView模式。 </p><h3 class="heading-1"><a name="0"></a><b style="COLOR: black; BACKGROUND-COLOR: #ffff66">OpenSessionInViewFilter</b>解决Web应用程序的问题 </h3>如果程序是在正常的Web程序中运行，那么Spring的<b style="COLOR: black; BACKGROUND-COLOR: #ffff66">OpenSessionInViewFilter</b>能够解决问题，它： 
<p class="paragraph"></p><div class="code"><pre><span class="java-keyword">protected</span> void doFilterInternal(HttpServletRequest request, 
             HttpServletResponse response,
	     FilterChain filterChain) <span class="java-keyword">throws</span> ServletException, IOException {
	SessionFactory sessionFactory = lookupSessionFactory();
	logger.debug(<span class="java-quote">"Opening Hibernate Session in <b style="COLOR: black; BACKGROUND-COLOR: #ffff66">OpenSessionInViewFilter</b>"</span>);
	Session session = getSession(sessionFactory);
	TransactionSynchronizationManager.bindResource(sessionFactory, 
             <span class="java-keyword">new</span> SessionHolder(session));
	<span class="java-keyword">try</span> {
		filterChain.doFilter(request, response);
	}
	<span class="java-keyword">finally</span> {
		TransactionSynchronizationManager.unbindResource(sessionFactory);
		logger.debug(<span class="java-quote">"Closing Hibernate Session in <b style="COLOR: black; BACKGROUND-COLOR: #ffff66">OpenSessionInViewFilter</b>"</span>);
		closeSession(session, sessionFactory);
	}
}</pre></div>可以看到，这个Filter在request开始之前，把sessionFactory绑定到TransactionSynchronizationManager，和这个SessionHolder相关。这个意味着所有request执行过程中将使用这个session。而在请求结束后，将和这个sessionFactory对应的session解绑，并且关闭Session。 
<p class="paragraph">为什么绑定以后，就可以防止每次不会新开一个Session呢？看看HibernateDaoSupport的情况： </p><div class="code"><pre><span class="java-keyword">public</span><span class="java-keyword">final</span> void setSessionFactory(SessionFactory sessionFactory) {
    <span class="java-keyword">this</span>.hibernateTemplate = <span class="java-keyword">new</span> HibernateTemplate(sessionFactory);
  }
 <span class="java-keyword">protected</span><span class="java-keyword">final</span> HibernateTemplate getHibernateTemplate() {
  <span class="java-keyword">return</span> hibernateTemplate;
 }</pre></div><p class="paragraph">我们的DAO将使用这个template进行操作： </p><div class="code"><pre><span class="java-keyword">public</span><span class="java-keyword">abstract</span> class BaseHibernateObjectDao
	<span class="java-keyword">extends</span> HibernateDaoSupport
	<span class="java-keyword">implements</span> BaseObjectDao {<p class="paragraph"><span class="java-keyword">protected</span> BaseEntityObject getByClassId(<span class="java-keyword">final</span><span class="java-object">long</span> id) {
		BaseEntityObject obj =
			(BaseEntityObject) getHibernateTemplate()
				.execute(<span class="java-keyword">new</span> HibernateCallback() {</p><p class="paragraph"><span class="java-keyword">public</span><span class="java-object">Object</span> doInHibernate(Session session)
				<span class="java-keyword">throws</span> HibernateException {
				<span class="java-keyword">return</span> session.get(getPersistentClass(), 
                                       <span class="java-keyword">new</span><span class="java-object">Long</span>(id));
			}</p><p class="paragraph">		});
		<span class="java-keyword">return</span> obj;
	}</p><p class="paragraph"></p><p class="paragraph"><span class="java-keyword">public</span> void save(BaseEntityObject entity) {
		getHibernateTemplate().saveOrUpdate(entity);
	}</p><p class="paragraph"><span class="java-keyword">public</span> void remove(BaseEntityObject entity) {
		<span class="java-keyword">try</span> {</p><p class="paragraph">			getHibernateTemplate().delete(entity);
		} <span class="java-keyword">catch</span> (Exception e) {
			<span class="java-keyword">throw</span><span class="java-keyword">new</span> FlexEnterpriseDataAccessException(e);
		}
	}</p><p class="paragraph"><span class="java-keyword">public</span> void refresh(<span class="java-keyword">final</span> BaseEntityObject entity) {
		getHibernateTemplate().execute(<span class="java-keyword">new</span> HibernateCallback() {</p><p class="paragraph"><span class="java-keyword">public</span><span class="java-object">Object</span> doInHibernate(Session session)
				<span class="java-keyword">throws</span> HibernateException {
				session.refresh(entity);
				<span class="java-keyword">return</span><span class="java-keyword">null</span>;
			}</p><p class="paragraph">		});
	}</p><p class="paragraph"><span class="java-keyword">public</span> void replicate(<span class="java-keyword">final</span><span class="java-object">Object</span> entity) {
		getHibernateTemplate().execute(<span class="java-keyword">new</span> HibernateCallback() {</p><p class="paragraph"><span class="java-keyword">public</span><span class="java-object">Object</span> doInHibernate(Session session)
				<span class="java-keyword">throws</span> HibernateException {
				session.replicate(entity, 
                                ReplicationMode.OVERWRITE);
				<span class="java-keyword">return</span><span class="java-keyword">null</span>;
			}</p><p class="paragraph">		});
	}</p></pre></div>而HibernateTemplate试图每次在execute之前去获得Session，执行完就力争关闭Session 
<div class="code"><pre><span class="java-keyword">public</span><span class="java-object">Object</span> execute(HibernateCallback action) <span class="java-keyword">throws</span> DataAccessException {
	Session session = (!<span class="java-keyword">this</span>.allowCreate ?
		SessionFactoryUtils.getSession(getSessionFactory(), 
                  <span class="java-keyword">false</span>) :
		SessionFactoryUtils.getSession(getSessionFactory(),
                  getEntityInterceptor(),
                  getJdbcExceptionTranslator()));
	<span class="java-object">boolean</span> existingTransaction =  
          TransactionSynchronizationManager.hasResource(getSessionFactory());
	<span class="java-keyword">if</span> (!existingTransaction &amp;&amp; getFlushMode() == FLUSH_NEVER) {
		session.setFlushMode(FlushMode.NEVER);
	}
	<span class="java-keyword">try</span> {
		<span class="java-object">Object</span> result = action.doInHibernate(session);
		flushIfNecessary(session, existingTransaction);
		<span class="java-keyword">return</span> result;
	}
	<span class="java-keyword">catch</span> (HibernateException ex) {
		<span class="java-keyword">throw</span> convertHibernateAccessException(ex);
	}
	<span class="java-keyword">catch</span> (SQLException ex) {
		<span class="java-keyword">throw</span> convertJdbcAccessException(ex);
	}
	<span class="java-keyword">catch</span> (RuntimeException ex) {
		// callback code threw application exception
		<span class="java-keyword">throw</span> ex;
	}
	<span class="java-keyword">finally</span> {
		SessionFactoryUtils.closeSessionIfNecessary(
                    session, getSessionFactory());
	}
}</pre></div>而这个SessionFactoryUtils能否得到当前的session以及closeSessionIfNecessary是否真正关闭session，端取决于这个session是否用sessionHolder和这个sessionFactory在我们最开始提到的TransactionSynchronizationManager绑定。 
<div class="code"><pre><span class="java-keyword">public</span><span class="java-keyword">static</span> void closeSessionIfNecessary(Session session, 
    SessionFactory sessionFactory)   
    <span class="java-keyword">throws</span> CleanupFailureDataAccessException {
	<span class="java-keyword">if</span> (session == <span class="java-keyword">null</span> || 
	   TransactionSynchronizationManager.hasResource(sessionFactory)) {
		<span class="java-keyword">return</span>;
	}
	logger.debug(<span class="java-quote">"Closing Hibernate session"</span>);
	<span class="java-keyword">try</span> {
		session.close();
	}
	<span class="java-keyword">catch</span> (JDBCException ex) {
		// SQLException underneath
		<span class="java-keyword">throw</span><span class="java-keyword">new</span> CleanupFailureDataAccessException(
		<span class="java-quote">"Cannot close Hibernate session"</span>, ex.getSQLException());
	}
	<span class="java-keyword">catch</span> (HibernateException ex) {
		<span class="java-keyword">throw</span><span class="java-keyword">new</span> CleanupFailureDataAccessException(
		<span class="java-quote">"Cannot close Hibernate session"</span>, ex);
	}
}</pre></div><h3 class="heading-1">HibernateInterceptor和OpenSessionInViewInterceptor的问题 </h3><p class="paragraph">使用同样的方法，这两个Interceptor可以用来解决问题。但是关键的不同之处在于，它们的力度只能定义在DAO或业务方法上，而不是在我们的Test方法上，除非我们把它们应用到TestCase的方法上，但你不大可能为TestCase去定义一个接口，然后把Interceptor应用到这个接口的某些方法上。直接使用HibernateTransactionManager也是一样的。因此，如果我们有这样的测试： </p><div class="code"><pre>Category parentCategory  = <span class="java-keyword">new</span> Category ();
	parentCategory.setName(<span class="java-quote">"parent"</span>);
	dao.save(parentCategory);<p class="paragraph">	Category childCategory  = <span class="java-keyword">new</span> Category();
        childCategory.setName(<span class="java-quote">"child"</span>);</p><p class="paragraph">	parentCategory.addChild(childCategory);
	dao.save(childCategory);</p><p class="paragraph">	Category savedParent = dao.getCategory(<span class="java-quote">"parent"</span>);
	Category savedChild = (Category ) savedParent.getChildren().get(0);
	assertEquals(savedChild, childCategory);</p></pre></div>将意味着两件事情： 
<ul class="minus"><li>每次DAO执行都会启动一个session和关闭一个session 
</li><li>如果我们定义了一个lazy的关系，那么最后的Category savedChild = (Category ) savedParent.getChildren().get(0);将会让hibernate报错。 </li></ul><h3 class="heading-1">解决方案 </h3><p class="paragraph">一种方法是对TestCase应用Interceptor或者TransactionManager，但这个恐怕会造成很多麻烦。除非是使用增强方式的AOP.我前期采用这种方法(Aspectwerkz)，在Eclipse里面也跑得含好。 </p><p class="paragraph">另一种方法是在TestCase的setup和teardown里面实现和Filter完全一样的处理，其他的TestCase都从这个TestCase继承，这种方法是我目前所使用的。 </p><p class="paragraph"><font color="#3333ff">Jolestar补充:openSessionInView的配置方法:</font></p><p class="paragraph">   &lt;filter&gt; <br />        &lt;filter-name&gt;opensession&lt;/filter-name&gt; <br />        &lt;filter-class&gt;org.springframework.orm.hibernate3.support.OpenSessionInViewFilter&lt;/filter-class&gt; <br />        &lt;init-param&gt; <br />            &lt;param-name&gt;singleSession&lt;/param-name&gt; <br />            &lt;param-value&gt;false&lt;/param-value&gt; <br />        &lt;/init-param&gt; <br />    &lt;/filter&gt; </p></div>
<img src ="http://www.blogjava.net/kevinfriend/aggbug/71920.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kevinfriend/" target="_blank">康文</a> 2006-09-26 11:01 <a href="http://www.blogjava.net/kevinfriend/archive/2006/09/26/71920.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Spring -transaction</title><link>http://www.blogjava.net/kevinfriend/archive/2006/09/15/69830.html</link><dc:creator>康文</dc:creator><author>康文</author><pubDate>Fri, 15 Sep 2006 03:00:00 GMT</pubDate><guid>http://www.blogjava.net/kevinfriend/archive/2006/09/15/69830.html</guid><wfw:comment>http://www.blogjava.net/kevinfriend/comments/69830.html</wfw:comment><comments>http://www.blogjava.net/kevinfriend/archive/2006/09/15/69830.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kevinfriend/comments/commentRss/69830.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kevinfriend/services/trackbacks/69830.html</trackback:ping><description><![CDATA[
		<p>1 Understand Transaction<br />  1) Introduce Spring's transaction manager<br />  a  JDBC transactions <br />     &lt;bean id="transactionManager" class="org.springframework.jdbc.<br />      datasource.DataSourceTransactionManager"&gt;<br />     &lt;property name="dataSource"&gt;<br />     &lt;ref bean="dataSource"/&gt;<br />     &lt;/property&gt;<br />     &lt;/bean&gt;<br />   b Hibernate transactions<br />     &lt;bean id="transactionManager" class="org.springframework.<br />       orm.hibernate.HibernateTransactionManager"&gt;<br />     &lt;property name="sessionFactory"&gt;<br />     &lt;ref bean="sessionFactory"/&gt;<br />     &lt;/property&gt;<br />     &lt;/bean&gt;<br />2 Programing transaction in Spring<br />   One approach to adding transaction to your code is to programmly add transactional boundary using transiationTemplate class.<br />   Programming is good when you want complete control over transactional boundary.but you have to use spring specific class.In most case ,your tansactional needs will not require such precise control over transactional boundaries.That is why you will typically choolse to declare transaction support<br />  public void enrollStudentInCourse() {<br />    transactionTemplate.execute(<br />    new TransactionCallback() {<br />      public Object doInTransaction(TransactionStatus ts) {<br />        try {<br />          // do stuff   Runs within doInTransaction()<br />        } catch (Exception e) {<br />          ts.setRollbackOnly(); //Calls setRollbackOnly() to roll Calls setRollbackOnly()                                 //to roll back<br />        }<br />          return null;   //If successful, transaction is committed<br />      }<br />    }<br />   );<br /> }<br /> &lt;bean id="transactionTemplate" class="org.springframework.<br />       transaction.support.TransactionTemplate"&gt;<br />  &lt;property name="transactionManager"&gt;<br />    &lt;ref bean="transactionManager"/&gt;<br />  &lt;/property&gt;<br /> &lt;/bean&gt;<br /> &lt;bean id="courseService"<br />    class="com.springinaction.training.service.CourseServiceImpl"&gt;<br /> &lt;property name=" transactionTemplate"&gt;<br />     &lt;ref bean=" transactionTemplate"/&gt;<br />   &lt;/property&gt;<br /> &lt;/bean&gt;<br />3 Declaring transactions<br />  Spring's support for declarative transaction management is implementedd through Spirng's  AOP framework.<br />  &lt;bean id="courseService" class="org.springframework.transaction.<br />       interceptor.TransactionProxyFactoryBean"&gt;<br />  &lt;property name="proxyInterfaces"&gt;<br />    &lt;list&gt;<br />      &lt;value&gt;<br />        com.springinaction.training.service.CourseService   <br />      &lt;/value&gt;<br />    &lt;/list&gt;<br />  &lt;/property&gt;<br />  &lt;property name="target"&gt;<br />   &lt;ref bean="courseServiceTarget"/&gt;   //Bean being proxied<br />  &lt;/property&gt;<br /> &lt;property name="transactionManager"&gt;<br />   &lt;ref bean="transactionManager"/&gt;   //Transaction manager<br /> &lt;/property&gt;<br /> &lt;property name="transactionAttributeSource"&gt;<br />   &lt;ref bean="attributeSource"/&gt;   //Transaction attribute source<br /> &lt;/property&gt;<br /> &lt;/bean&gt;<br /> 1) Understanding transaction attributes<br />  In Spring transaction attribute is a description of how transaction policies should be<br />applied to a methods<br />   a  Propagation behavior<br />    Propagation behavior                 What it means<br />    PROPAGATION_MANDATORY                indicate that the method must run within a                                                  transaction.If no transaction is in progress<br />                                         an exception will be thrown<br />    PROPAGATION_NESTED<br />    PROPAGATION_NEVER                    indicate that the method can not run withi a                                                transaction. if a transaction exist an exception                                            will be thrown.<br />    PROPAGATIOM_NOT_SUPPORT              Indicates that the method should not run within a                                           transaction. If an existing transaction is                                                  in progress, it will be suspended for the <br />                                         duration of the method.<br />    PROPAGATION_REQUIRED                 indicate that the current method must run within a                                          transaction.if an existing transaction is in                                                progress,the ,method will run with the transaction<br />                                         otherwise a new transaction will be started<br />    PROPAGATION_REQUIRENEW               indicates that the current must run within its own<br />                                         transaction.A new transaction is started and an                                             existing transaction will be suspend<br />    PROPAGATION_SUPPORT                  indicate the current mehtod does not require a                                          transaction.but may run if on is already in progress      <br />    b Isolation levels      <br />    Isolation level                    What it means<br />    ISOLATION_DEFAULT                  Using the defaul isolation level of the underlying                                          database<br />    ISOLATION_READ_UNCOMMITTED         Allows you read change that have not yet been commit<br />                                       May result in dirty read,phantom read,nonrepeatable                                         read<br />    ISOLATION_READ_COMMITTED           Allows reads from concurrent transactions that have<br />                                       bean committed.Dirty read are prevent.but platform                                          and norepeatable reads may still occur.<br />    ISOLATIOM_REPEATABLE_READ          Multiple read the same field will yield the same                                            result ,unless changed by the transaction                                                   itself.Dirty reads ,nonrepeatable are all prevented<br />                                       phantom may still occur<br />    ISOLATION_SERIALIZABLE             This fully ACID-compliant isolation level ensusme                                        that dirty read,unrepeatable read ,phantom read are                                        all prevented.And this is the most slowest isolation<br />                                       since it is typically accomplished by doing full                                        table lock on the tables in the transaction.</p>
		<p>   c Read-Only<br />   If a transaction performs only read operation against the underlying datastore.when a transaction begin ,it only make sense to declare a transaction as read only on mehtods with<br />propagation behavior which start a new transaction.<br />   Furthermore ,if you are Hibernate as persistence mechanism,declaring a transaction as read only will reult in Hibernate flush mode being set to FLUST_NEVER.this tell hibernate to avoid synchroniztion of objects with database.<br />   d Transaction timeout<br />   Suppose that your transaction becomes unexpectedly long-running transaction.Because transaction may invole locks on the underlying database.Instead of waiting it out ,you can delcare a transaction to automaitically roll back.<br />   because timeout clock begin ticking when a transaction start. it only make sense to declare a transaction timeout on methods with propagation behavior that start a new transaction.<br />  2) Declaring a simple transaction policy<br />   &lt;bean id="myTransactionAttribute"<br />    class="org.springframework.transaction.interceptor.<br />            DefaultTransactionAttribute"&gt;<br />  &lt;property name="propagationBehaviorName"&gt;<br />    &lt;value&gt;PROPAGATION_REQUIRES_NEW&lt;/value&gt;<br />  &lt;/property&gt;<br />  &lt;property name="isolationLevelName"&gt;<br />    &lt;value&gt;ISOLATION_REPEATABLE_READ&lt;/value&gt;<br />  &lt;/property&gt;<br /> &lt;/bean&gt;<br /> &lt;bean id="transactionAttributeSource" <br />    class="org.springframework.transaction.interceptor.<br />            MatchAlwaysTransactionAttributeSource"&gt;<br />  &lt;property name="transactionAttribute"&gt;<br />    &lt;ref bean="myTransactionAttribute"/&gt;<br />  &lt;/property&gt;<br /> &lt;/bean&gt;<br />4 Declaring transactions by method name<br />  1) Using NameMatchTransactionAttributeSource<br />  The properties property of NameMatchTransactionAttributeSource maps mehtod to a transaction property descriptor. the property descriptor takes the following form:<br />  Propagation,isolation,readOnly,-Exception,+Exception <br />  <br />  &lt;bean id="transactionAttributeSource"<br />    class="org.springframework.transaction.interceptor.<br />            NameMatchTransactionAttributeSource"&gt;<br />  &lt;property name="properties"&gt;<br />    &lt;props&gt;<br />      &lt;prop key="enrollStudentInCourse"&gt;<br />          PROPAGATION_REQUIRES_NEW<br />      &lt;/prop&gt;<br />    &lt;/props&gt;<br />  &lt;/property&gt;<br /> &lt;/bean&gt;<br /> 2) Specifying the transaction Isolation level<br />  &lt;bean id="transactionAttributeSource"<br />    class="org.springframework.transaction.interceptor.<br />            NameMatchTransactionAttributeSource"&gt;<br />     &lt;property name="properties"&gt;<br />    &lt;props&gt;<br />      &lt;prop key="enrollStudentInCourse"&gt;<br />        PROPAGATION_REQUIRES_NEW,ISOLATION_REPEATABLE_READ<br />      &lt;/prop&gt;<br />    &lt;/props&gt;<br />  &lt;/property&gt;<br /> &lt;/bean&gt;<br /> 3) Using real-only transaction<br />  &lt;bean id="transactionAttributeSource"<br />    class="org.springframework.transaction.interceptor.<br />            NameMatchTransactionAttributeSource"&gt;<br />  &lt;property name="properties"&gt;<br />    &lt;props&gt;<br />      &lt;prop key="getCompletedCourses"&gt;<br />        PROPAGATION_REQUIRED,ISOLATION_REPEATABLE_READ,readOnly<br />      &lt;/prop&gt;<br />    &lt;/props&gt;<br />  &lt;/property&gt;<br />&lt;/bean&gt;<br /> 4)Specifying  rollback rules<br />  You can sepcify that a transaction be rollback on specify checked exception<br />  &lt;bean id="transactionAttributeSource"<br />    class="org.springframework.transaction.interceptor.<br />            NameMatchTransactionAttributeSource"&gt;<br />  &lt;property name="properties"&gt;<br />    &lt;props&gt;<br />      &lt;prop key="enrollStudentInCourse"&gt;<br />        PROPAGATION_REQUIRES_NEW,ISOLATION_REPEATABLE_READ,<br />        -CourseException<br />        &lt;/prop&gt;<br />     &lt;/props&gt;<br />    &lt;/property&gt;<br />  &lt;/bean&gt;<br />  Exception can be marked as negative(-) or postive(+)<br />  Negative exception will trigger the roll back if the exception (or sublclass of it) is thrown.Postive exception on the other hand indicate that the transacton should be commit<br />even if the exception is thrown<br /> 5)Using wildcard matches<br /> &lt;bean id="transactionAttributeSource"<br />    class="org.springframework.transaction.interceptor.<br />            NameMatchTransactionAttributeSource"&gt;<br />  &lt;property name="properties"&gt;<br />    &lt;props&gt;<br />      &lt;prop key="get*"&gt;<br />        PROPAGATION_SUPPORTS<br />      &lt;/prop&gt;<br />    &lt;/props&gt;<br />  &lt;/property&gt;<br />&lt;/bean&gt;<br /> 6 Short-cut name match transaction <br /> &lt;bean id="courseService" class="org.springframework.transaction.<br />       interceptor.TransactionProxyFactoryBean"&gt;<br />   &lt;property name="transactionProperties"&gt;<br />    &lt;props&gt;<br />      &lt;prop key="enrollStudentInCourse"&gt;<br />        PROPAGATION_REQUIRES_NEW<br />      &lt;/prop&gt;<br />    &lt;/props&gt;<br />   &lt;/property&gt;<br /> &lt;/bean&gt;</p>
<img src ="http://www.blogjava.net/kevinfriend/aggbug/69830.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kevinfriend/" target="_blank">康文</a> 2006-09-15 11:00 <a href="http://www.blogjava.net/kevinfriend/archive/2006/09/15/69830.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring -database</title><link>http://www.blogjava.net/kevinfriend/archive/2006/09/14/69598.html</link><dc:creator>康文</dc:creator><author>康文</author><pubDate>Thu, 14 Sep 2006 03:45:00 GMT</pubDate><guid>http://www.blogjava.net/kevinfriend/archive/2006/09/14/69598.html</guid><wfw:comment>http://www.blogjava.net/kevinfriend/comments/69598.html</wfw:comment><comments>http://www.blogjava.net/kevinfriend/archive/2006/09/14/69598.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kevinfriend/comments/commentRss/69598.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kevinfriend/services/trackbacks/69598.html</trackback:ping><description><![CDATA[
		<p>一 Spring DAO philosophy <br /> 1 Understanding Spring's DataAccesssException<br /> Spring's DAO frameworks donot throw teechnology-specific exceptions such as SQLException<br />or HibernateeExcepiton.Instead ,all exceptions thrown are subclasses of DataAccessException<br /> 2 You are not forced to handle DataAccessExceptions<br /> DataAccessException is a RuntimeException,so it si an unchecked exception.Since these are quite often unrecoverable,you are not forced to handle these exception.<br />  Instead ,you can catch the exception if recovery is possible.since DataAccessException is not only a RuntimeException,but it subclasses Spring's NestedRuntimeException. This menas that the root Exception is alwarys via NestedRuntimeException's getCause() method.<br /> 3 Work with DataSources<br />  a getting a Datasource from JNDI<br />   &lt;bean id="dataSource" <br />      class="org.springframework.jndi.JndiObjectFactoryBean"&gt;<br />   &lt;property name="jndiName"&gt;<br />    &lt;value&gt;java:comp/env/jdbc/myDatasource&lt;/value&gt;<br />   &lt;/property&gt;<br />   &lt;/bean&gt;<br />  b Creating a Datasource connection pool<br />   &lt;bean id="dataSource" <br />      class="org.apache.commons.dbcp.BasicDataSource"&gt;<br />  &lt;property name="driver"&gt;<br />    &lt;value&gt;${db.driver}&lt;/value&gt;<br />  &lt;/property&gt;<br />  &lt;property name="url"&gt;<br />    &lt;value&gt;${db.url}&lt;/value&gt;<br />  &lt;/property&gt;<br />  &lt;property name="username"&gt;<br />    &lt;value&gt;${db.username}&lt;/value&gt;<br />  &lt;/property&gt;<br />  &lt;property name="password"&gt;<br />    &lt;value&gt;${db.password}&lt;/value&gt;<br />  &lt;/property&gt;<br />&lt;/bean&gt;<br /> c Using a DataSource while testing<br />  DriverManagerDataSource dataSource = new DriverManagerDataSource();<br />  dataSource.setDriverClassName(driver);<br />  dataSource.setUrl(url);<br />  dataSource.setUsername(username);<br />  dataSource.setPassword(password);<br /> 4 Consistent DAO support<br />  Spring template class handle the invariant part of data access-controling the trancsaction<br />manage resource,handling exception .Implementation of callback interface define what is specific to your application--creating statement,binding parameter and marshalling result set.<br /> Spring separates the fixed an vaiant parts of data access process into tow distince classes:<br />template and callbacks.Template manage the fixed parts of the process while callback are where you fill in the implement details;<br /> one the top of template-callback desing ,spring framework provide a support class which your own data access subclass it. And the support class already have a property for holding a template.<br /> 二 Integerating Hibernate with Spring<br />  1 Managing Hibernate resources<br />   you will keep a single instance of SessionFactory throughtout your application<br />   &lt;bean id="sessionFactory"class="org.springframework.<br />           orm.hibernate.LocalSessionFactoryBean"&gt;<br />     &lt;bean id="sessionFactory" class="org.springframework. <br />       orm.hibernate.LocalSessionFactoryBean"&gt;<br />     &lt;property name="dataSource"&gt;<br />       &lt;ref bean="dataSource"/&gt;<br />     &lt;/property&gt;<br />  &lt;/bean&gt;<br />  you also want to manager how hibernate is configured<br />  &lt;bean id="sessionFactory" class="org.springframework.<br />       orm.hibernate.LocalSessionFactoryBean"&gt;<br />  &lt;property name="hibernateProperties"&gt;<br />    &lt;props&gt;<br />      &lt;prop key="hibernate.dialect"&gt;net.sf.hibernate.<br />           dialect.MySQLDialect&lt;/prop&gt;</p>
		<p>    &lt;/props&gt;<br />  &lt;/property&gt;<br />  …<br /> &lt;/bean&gt;<br /> and the last thing is whick map files is read<br />  &lt;bean id="sessionFactory" class="org.springframework.<br />       orm.hibernate.LocalSessionFactoryBean"&gt;<br />  &lt;property name="mappingResources"&gt;<br />     &lt;list&gt;<br />     &lt;value&gt;Student.hbm.xml&lt;/value&gt;<br />     &lt;value&gt;Course.hbm.xml&lt;/value&gt;<br />     …<br />   &lt;/list&gt;<br />  &lt;/property&gt;<br />     …<br />  &lt;/bean&gt;</p>
		<p> Now  you have fully configured your sessionfactory ,so we need do create an object which we<br />will access hibernate. As we know, we will use a template class<br />  &lt;bean id="hibernateTemplate" <br />      class="org.springframework.orm.hibernate.HibernateTemplate"&gt;<br />  &lt;property name="sessionFactory"&gt;<br />    &lt;ref bean="sessionFactory"/&gt;<br />  &lt;/property&gt;<br /> &lt;/bean&gt;</p>
		<p>  &lt;bean id="courseDao" class="com.springinaction.<br />       training.dao.hibernate.CourseDaoHibernate"&gt; <br />  &lt;property name="hibernateTemplate"&gt;<br />    &lt;ref bean="hibernateTemplate"/&gt;<br />  &lt;/property&gt;<br /> &lt;/bean&gt;</p>
		<p> 2 Accessing Hibernate through HibernatTemplate<br />  The template-callback mechanism in Hibernatee is pretty simple.There is the HibernatTmpplate and one callback interface<br />  public Student getStudent(final Integer id) {<br />  return (Student) hibernateTemplate.execute(<br />    new HibernateCallback() {<br />      public Object doInHibernate(Session session)<br />          throws HibernateException {<br />        return session.load(Student.class, id);<br />      }<br />    });<br />  <br />  The HibernateTemplate class provides some convience methods that implicit create a HibernateCallback instance:<br />  (Student) hibernateTemplate.load(Student.class, id);<br />   hibernateTemplate.update(student);<br />  hibernateTemplate.find("from Student student " +<br />                                "where student.lastName = ?",<br />                                lastName, Hibernate.STRING);<br />  3 Subclassing HibernateDaoSupport<br />  public class StudentDaoHibernate extends HibernateDaoSupport <br />    implements StudentDao {<br />  …<br />  }<br />  getHibernateTemplate()<br />  getSession()</p>
<img src ="http://www.blogjava.net/kevinfriend/aggbug/69598.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kevinfriend/" target="_blank">康文</a> 2006-09-14 11:45 <a href="http://www.blogjava.net/kevinfriend/archive/2006/09/14/69598.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate 一级缓存</title><link>http://www.blogjava.net/kevinfriend/archive/2006/09/14/69535.html</link><dc:creator>康文</dc:creator><author>康文</author><pubDate>Thu, 14 Sep 2006 01:22:00 GMT</pubDate><guid>http://www.blogjava.net/kevinfriend/archive/2006/09/14/69535.html</guid><wfw:comment>http://www.blogjava.net/kevinfriend/comments/69535.html</wfw:comment><comments>http://www.blogjava.net/kevinfriend/archive/2006/09/14/69535.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kevinfriend/comments/commentRss/69535.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kevinfriend/services/trackbacks/69535.html</trackback:ping><description><![CDATA[
		<p>1 hibernate 一级缓存<br />Session  <br />  evict(Object o) 从缓存中清除指定的持久化对象<br />  clear()         清除缓存中所有对象<br />2 批量更新于批量删除<br />  1) 批量更新<br />   Iterator customers=session.find("from Customer c where c.age&gt;0");<br />   while(customers.hasNext()){<br />     Customer customer=(Customer)customers.next();<br />     customer.setAge(customer.getAge()+1);<br />   }<br />   tx.commit();<br />   session.close();</p>
		<p>  缺点：内存中加载了大量数据<br />        执行了多次update 语句<br />  <br />   改进<br />   Iterator customers=session.find("from Customer c where c.age&gt;0");<br />   while(customers.hasNext()){<br />     Customer customer=(Customer)customers.next();<br />     customer.setAge(customer.getAge()+1);<br />     session.flush();<br />     session.evict(customer);<br />   }<br />   tx.commit();<br />   session.close();<br />   遗留问题<br />   执行了多次update 语句<br />   <br />   采用jdbc api 进行调用<br />   Connection con=session.connection();<br />   PrepareStatement stmt=con.prepareStatement("update customers set age=age+1 where age&gt;0");<br />   stmt.executeUpdate();<br />   tx.commit();<br />   另外，也可以调用底层的存储过程进行批量更新<br />   create or replace procedure batchUpdateCustomer(p_age,in number) as<br />   begin<br />      update customer set age=age+1 where age&gt;p_age;<br />   end; <br />   <br />   tx=session.beginTransaction();<br />   Connection con=session.connection();<br />   CallableStatement cstmt=con.prepareCall(batchUpdateCustomer);<br />   cstmt.setInt(1,0);<br />   cstmt.eqecuteUpdate();<br />   tx.commit();<br />   2) 批量数据的删除<br />    session.delete("from  Customer c where c.age&gt;0");<br />    实际调用的过程<br />    session * from Customer where age&gt;0;<br />    在把所有数据加载到内存之后执行多条delete 语句<br />    delete from customer where id=i;<br />     .......................<br />   改进办法采用jdbc api 进行批量数据的删除<br />      <br />   tx=session.beginTransaction();<br />   Connection con=session.connection();<br />   con.execute("delete from customers where age&gt;0");<br />   tx.commit();</p>
<img src ="http://www.blogjava.net/kevinfriend/aggbug/69535.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kevinfriend/" target="_blank">康文</a> 2006-09-14 09:22 <a href="http://www.blogjava.net/kevinfriend/archive/2006/09/14/69535.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate -类型</title><link>http://www.blogjava.net/kevinfriend/archive/2006/09/14/69534.html</link><dc:creator>康文</dc:creator><author>康文</author><pubDate>Thu, 14 Sep 2006 01:20:00 GMT</pubDate><guid>http://www.blogjava.net/kevinfriend/archive/2006/09/14/69534.html</guid><wfw:comment>http://www.blogjava.net/kevinfriend/comments/69534.html</wfw:comment><comments>http://www.blogjava.net/kevinfriend/archive/2006/09/14/69534.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kevinfriend/comments/commentRss/69534.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kevinfriend/services/trackbacks/69534.html</trackback:ping><description><![CDATA[
		<p>Hibernate                  java                     sql                    oracle        </p>
		<p>integer or int             int or Integer           INTEGER<br />long                       long or Long             BIGINT<br />short                      short or Short           SMALLINT<br />byte                       byte or Byte             TINYINT<br />float                      float or Float           FLOAT<br />double                     double or Double         DOUBLE<br />big_decimal                java.math.BigDecimal     NUMBERBIC<br />character                  char java.lang.Character CHAR(1)<br />                           String                      <br />string                     String                    VARCHAR<br />boolean                    boolean or Boolean        BIT<br />date                       java.util.Date            DATE<br />                           java.sql.Date <br />time                       Date or java.sql.time     TIME<br />timestamp                  Date or java.sql.Timestamp TIMESTAMP               <br />binary                     byte[]                    blog                   blog<br />text                       String                    clob                   clog<br />serializable                                         blog                   blog             <br />clob                       java.sql.clob            clob                    clob<br />blob                       java.sql.blob             blog                   blob <br /></p>
<img src ="http://www.blogjava.net/kevinfriend/aggbug/69534.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kevinfriend/" target="_blank">康文</a> 2006-09-14 09:20 <a href="http://www.blogjava.net/kevinfriend/archive/2006/09/14/69534.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>spring --wiring binding</title><link>http://www.blogjava.net/kevinfriend/archive/2006/09/04/67531.html</link><dc:creator>康文</dc:creator><author>康文</author><pubDate>Mon, 04 Sep 2006 03:10:00 GMT</pubDate><guid>http://www.blogjava.net/kevinfriend/archive/2006/09/04/67531.html</guid><wfw:comment>http://www.blogjava.net/kevinfriend/comments/67531.html</wfw:comment><comments>http://www.blogjava.net/kevinfriend/archive/2006/09/04/67531.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kevinfriend/comments/commentRss/67531.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kevinfriend/services/trackbacks/67531.html</trackback:ping><description><![CDATA[
		<p>Containing your beans<br />    Tere i sno single Spring container.Spring actually comes with two distince types of containers:Bean factories and Application </p>
		<p>contexts.Beyong there two basic types of contains .Srping come with sereral implementss of BeanFacotory and ApplicationContext.<br />  1 introducing the BeanFactory<br />  There are several implementations of BeanFactory in Spring .But the most userful one is XmlBeanFactory,whick loads<br />its bean based on the definitions contained in an xml file.<br />  Creat a XmlBeanFactory  BeanFactory factory=new XMLBeanFactory(new FileInputStream("beans.xml"));<br /> But at that time ,the BeanFactory does not initialize the bean ,it is loaded lazliy.<br />  Get the Bean :MyBean myBean=(MyBean)factory.getBean("myBean");<br /> When getBean() is called ,the factory will instantiate the bean and being setting the bean using dependency injection.<br />  2 Working with an application context<br /> an ApplicationContextis prefered over a BeanFactory in nearly all application ,the only time you might consider using a BeanFactory </p>
		<p>are in circumtance where resource s are scarce.<br />   Amony the many implements of ApplicationContext are three that are commonly used:<br />      ClassPathXmlApplicationContext,FileSystemXmpApplicationContext,XmlWebApplicationContext.<br />   ApplicationContext context=new ClassPathXmlApplicationContext("foo.xml");<br /> wiring the beans<br />  &lt;beans&gt;<br />    &lt;bean id="foo" class="com.springinaction.Foo" /&gt;<br /> &lt;/beans&gt;<br /> Prototyping vs.singleton<br /> By default ,all Spring beans are singletons.When the container dispenses a bean it will always give the exact same instance of the     </p>
		<p>In this case ,you would want to define a prototype bean .Defining a prototype means that instead of defining a single bean.<br />     &lt;bean id="foo" class="com.springinaction.Foo"  single/&gt;on="false" /&gt;<br />Initialization and destruction<br />   &lt;bean id="foo" class="com.springinaction.Foo" init-method="setup" destory-method="teardown"&gt;<br />Injectiong dependencies via setter method<br />   &lt;bean id="foo" class="com.srpinginaction.Foo" &gt;<br />        &lt;property name="name"&gt;Foo McFoo&lt;/value&gt;<br />   &lt;/bean&gt;<br /> Referencing other beans<br />   &lt;bean id="foo" class="com.springinaction.Foo"&gt;<br />     &lt;property name="bar" &gt;<br />        &lt;ref bean="bar" /&gt;<br />     &lt;/property&gt;<br />    &lt;/bean&gt;<br />    &lt;bean id="bar" colass="com.srpinginaction.Bar" /&gt;<br /> Inner beans<br />   &lt;bean id="courseService"<br />             class="com.CourseWericeImpl"&gt;<br />     &lt;property nanme="studentService"&gt;<br />         &lt;bean <br />              class="com....." /&gt;<br />      &lt;/property&gt;<br />   &lt;/bean&gt;<br />  Wiring collections<br />    1Wiring lists and arrays  java.util.List<br />      &lt;property name="barList"&gt;<br />           &lt;list&gt;<br />                &lt;value&gt;bar1&lt;/value&gt;<br />                &lt;ref bean="bar2"/&gt;<br />           &lt;/lsit&gt;<br />      &lt;/property&gt;<br />   2 Wiring set  java.tuil.Set<br />    &lt;property name="barSet"&gt;<br />          &lt;set&gt;<br />                 &lt;value&gt;bar1&lt;/value&gt;<br />                 &lt;ref bean="bar2" /&gt;<br />          &lt;/set&gt;<br />   &lt;/property&gt;<br />   3 Wiring maps java.util.Map<br />   &lt;property name="barMap"&gt;<br />        &lt;ebtry key="key1"&gt;<br />        &lt;value&gt;bar1&lt;/value&gt;<br />   &lt;/property&gt;<br />  4 Wiring propertyies<br />    &lt;property name="barProps"&gt;<br />         &lt;props&gt;<br />            &lt;prop key="key1"&gt;bar1&lt;/prop&gt;<br />            &lt;prop key="key2"&gt;bar2&lt;/prop&gt;<br />         &lt;/props&gt; <br />    &lt;/property&gt;<br />  5 Setting null values<br />   &lt;property name="foo"&gt;&lt;null/&gt;&lt;property&gt;<br />   injecting dependencies via constructor<br />   &lt;id="foo" class="com.springinaction.Foo"&gt;<br />    &lt;constructor-arg&gt;<br />        &lt;value&gt;42&lt;value&gt;( &lt;ref bean="bar"&gt;)<br />     &lt;/constructor-arg&gt;<br />    &lt;bean id="foo" class="com.springinaction.Foo"&gt;<br />       &lt;constructor-arg&gt;<br />            &lt;value&gt;http://www.manning.com&lt;/value&gt;<br />       &lt;/constructor-arg&gt;<br />  &lt;constructor-arg&gt;<br />            &lt;value&gt;http://www.manning.com&lt;/value&gt;<br />       &lt;/constructor-arg&gt;<br />   &lt;/bean&gt;</p>
<img src ="http://www.blogjava.net/kevinfriend/aggbug/67531.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kevinfriend/" target="_blank">康文</a> 2006-09-04 11:10 <a href="http://www.blogjava.net/kevinfriend/archive/2006/09/04/67531.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hibernate 总结基础</title><link>http://www.blogjava.net/kevinfriend/archive/2006/08/18/64378.html</link><dc:creator>康文</dc:creator><author>康文</author><pubDate>Fri, 18 Aug 2006 08:20:00 GMT</pubDate><guid>http://www.blogjava.net/kevinfriend/archive/2006/08/18/64378.html</guid><wfw:comment>http://www.blogjava.net/kevinfriend/comments/64378.html</wfw:comment><comments>http://www.blogjava.net/kevinfriend/archive/2006/08/18/64378.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/kevinfriend/comments/commentRss/64378.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/kevinfriend/services/trackbacks/64378.html</trackback:ping><description><![CDATA[1 java 类型，             hibernate 类型       sql<br />  java .lang.String       string               varchar<br />  java.lang.String        text                 Text<br />  int                     int                  INT<br />  char                    character             char(1)<br />  boolean                 boolean              bit<br />  byte[]                  binary               blob<br />  java.sql.Date           date                 Date<br />  java.sql.Timestamp      timestamp            Timestamp (载数据库中如果插入为null，数据库系统自动插入为当前值)<br />2 表述层－－》业务逻辑层－》hibernate－》database<br />3 <br />  Configuration config=new Configuration();<br />  config.add(Customer.class);<br />  sessionFactory=conf.buildSessionFactory();<br />  Session session=sessionFactory.openSession();<br />  Transaction tx;<br />  try{<br />   tx=session.beginTransaction();<br />   tx.commit();<br />  }catch(Exception e){<br />    if(tx!=null){<br />      tx.rollback();<br />    } <br />  }finally{<br />    session.close();<br />  }<br />4 数据库存取blob 对象<br /> 1 <br />   InputStream in=this.getClass().getResourceAsStream("photo.gif");<br />   byte[] buffer=new byte[in.available()]'<br />   in.read(buffer);<br />   customer.setImage(buffer);<br /> 2 byte[] buffer=customer.get.getImage();<br />   File OutputStream fout=new fileOutStream("photo.gif");<br />   fout.write(buffer);<br />   fout.close();<img src ="http://www.blogjava.net/kevinfriend/aggbug/64378.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/kevinfriend/" target="_blank">康文</a> 2006-08-18 16:20 <a href="http://www.blogjava.net/kevinfriend/archive/2006/08/18/64378.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>