﻿<?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-网摘-文章分类-SQL Server</title><link>http://www.blogjava.net/jvict/category/33915.html</link><description /><language>zh-cn</language><lastBuildDate>Mon, 19 Jan 2009 23:22:51 GMT</lastBuildDate><pubDate>Mon, 19 Jan 2009 23:22:51 GMT</pubDate><ttl>60</ttl><item><title>引用 asp.net session的应用</title><link>http://www.blogjava.net/jvict/articles/251985.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Mon, 19 Jan 2009 15:55:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/251985.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/251985.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/251985.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/251985.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/251985.html</trackback:ping><description><![CDATA[<p><em><a href="http://blog.163.com/hanjz/blog/static/41028272200861051732741/">原文: http://blog.163.com/hanjz/blog/static/41028272200861051732741/</a><br />
<br />
引用</em></p>
<blockquote><a href="http://blog.163.com/lingfang_yan/" target="_blank">lingfang_yan</a> 的 <a href="http://blog.163.com/lingfang_yan/blog/static/374706862007926113498" target="_blank">asp.net session的应用</a><br />
<br />
<br />
<p style="text-indent: 21.25pt; line-height: 15.7pt">Session又称为会话状态，是Web系统中最常用的状态，用于维护和当前浏览器实例相关的一些信息。举个例子来说，我们可以把已登录用户的用户名放在Session中，这样就能通过判断Session中的某个Key来判断用户是否登录，如果登录的话用户名又是多少。</p>
<p style="text-indent: 21pt; line-height: 15.7pt">我们知 道，Session对于每一个客户端（或者说浏览器实例）是&#8220;人手一份&#8221;，用户首次与Web服务器建立连接的时候，服务器会给用户分发一个 SessionID作为标识。SessionID是一个由24个字符组成的随机字符串。用户每次提交页面，浏览器都会把这个SessionID包含在 HTTP头中提交给Web服务器，这样Web服务器就能区分当前请求页面的是哪一个客户端。那么，ASP.NET 2.0提供了哪些存储SessionID的模式呢：</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Cookie（默认）。如果客户端禁止了Cookie的使用，Session也将失效。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URL。Cookie是否开启不影响Session使用，缺点是不能再使用绝对链接了。</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">前面说了SessionID可以存储在客户端的Cookie或者URL中，那么Session真正的内容存储在哪里呢？ASP.NET 2.0对于Session内容的存储也提供了多种模式。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; InProc（默认）。Session存储在IIS进程中（Web服务器内存）。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; StateServer。Session存储在独立的Windows服务进程中（可以不是Web服务器）。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SqlServer。Session存储在SqlServer数据库的表中（SqlServer服务器）。</p>
<p style="text-indent: 21pt; line-height: 15.7pt">虽然 InProc模式的Session直接存储在Web服务器IIS进程中，速度比较快，但是每次重新启动IIS都会导致Session丢失。利用后两种模式，我们就完全可以把Session从Web服务器中独立出来，从而减轻Web服务器的压力，同时减少Session丢失的概率。</p>
<p style="text-indent: 21pt; line-height: 15.7pt">因此，SessionID存储在客户端（可以是Cookie或者URL），其他都存储在服务端（可以是IIS进程、独立的Windows服务进程或者SQL Server数据库中）。</p>
<h3>12.3.2 &nbsp;Session的使用</h3>
<p style="text-indent: 21pt; line-height: 15.7pt">让我们先来实践一下如何使用Session，进而回答第二个问题：Session存储的类型限制。Session不需要进行任何配置就可以使用（默认是InProc模式并且依赖Cookie）。首先，在页面上建立两个按钮。</p>
<p>&lt;asp:Button ID="btn_WriteSession" runat="server"Text="写入Session" /&gt;</p>
<p>&lt;asp:Button ID="btn_ReadSession" runat="server" Text="读取Session" /&gt;</p>
<p style="text-indent: 21pt; line-height: 15.7pt">在btn_WriteSession按钮的Click事件处理方法中，写入两个Session，一个是简单的字符串，另外一个是自定义的类。</p>
<p style="line-height: 13pt">protected void btn_WriteSession_Click(object sender, EventArgs e)</p>
<p style="line-height: 13pt">{</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; Session["SimpleString"] = "编程快乐";</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; MyUser user = new MyUser();</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; user.sUserName = "小朱";</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; user.iAage = 24;</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; Session["CustomClass"] = user;</p>
<p style="line-height: 13pt">}</p>
<p style="text-indent: 21pt; line-height: 15.7pt">Session的使用非常简单，直接对某个Key的Session进行赋值即可。自定义类MyUser如下：</p>
<p>class MyUser</p>
<p>{</p>
<p>&nbsp;&nbsp;&nbsp; public string sUserName;</p>
<p>&nbsp;&nbsp;&nbsp; public int iAage;</p>
<p>&nbsp;&nbsp;&nbsp; public override string ToString()</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return string.Format("姓名：{0}，年龄：{1}", sUserName, iAage);</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>}</p>
<p style="text-indent: 21pt; line-height: 15.7pt">在这里，我们覆写了ToString()方法直接返回实例的一些信息。然后，双击btn_ReadSession按钮来实现从Session中读取数据的代码：</p>
<p>protected void btn_ReadSession_Click(object sender, EventArgs e)</p>
<p>{</p>
<p>&nbsp;&nbsp;&nbsp; if (Session["SimpleString"]==null)</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Write("读取简单字符串失败&lt;br/&gt;");</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; else</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; string s=Session["SimpleString"].ToString();</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Write(s + "&lt;br/&gt;");</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; if (Session["CustomClass"]==null)</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Write("读取简单自定义类失败&lt;br/&gt;");</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp; else</p>
<p>&nbsp;&nbsp;&nbsp; {</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; MyUser user=Session["CustomClass"] as MyUser;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Response.Write(user.ToString()+"&lt;br/&gt;");</p>
<p>&nbsp;&nbsp;&nbsp; }</p>
<p>}</p>
<p style="text-indent: 21pt; line-height: 15.7pt">在每次读取Session的值以前请务必先判断Session是否为空，否则很有可能出现&#8220;未将对象引用设置到对象的实例&#8221;的异常。我们看到，从Session 中读出的数据都是object类型的，我们需要进行类型转化后才能使用。打开页面，先单击写入Session按钮，再单击读取Session按钮，页面输出如&nbsp;&nbsp;&nbsp; 图12-1所示。</p>
<p align="center"><img height="118" alt="文本框:图12-1  从Session中读取字符串和自定义类" hspace="12" src="http://book.csdn.net/BookFiles/406/img/image002.gif" width="242" align="left" /></p>
<h3>12.3.3 &nbsp;把Session存储在独立的进程中</h3>
<p style="text-indent: 21.25pt; line-height: 15.7pt">由此看来，Session能存储任意对象，是这样吗？现在得出这个结论还太早了一点，因为我们并没有实践过StateServer和SqlServer模式的Session。要把Session存储在Windows服务进程中需要进行以下几个步骤。</p>
<p>n&nbsp; 第1步是打开状态服务。依次打开&#8220;控制面板&#8221;&#8594;&#8220;管理工具&#8221;&#8594;&#8220;服务&#8221;命令，找到ASP.NET状态服务一项，右键单击服务选择启动，如图12-2所示。</p>
<p align="center"><img height="132" alt="" src="http://book.csdn.net/BookFiles/406/img/image003.jpg" width="416" /></p>
<p align="center">图12-2 &nbsp;启动ASP.NET状态服务</p>
<p>n&nbsp; 如果你正式决定使用状态服务存储Session前，别忘记修改服务为自启动（在操作系统重启后服务能自己启动）以免忘记启动服务而造成网站Session不能使用，如图12-3所示，双击服务把服务的启动类型设置为自动。</p>
<p style="margin-top: 12.55pt" align="center"><img height="327" alt="" src="http://book.csdn.net/BookFiles/406/img/image004.jpg" width="303" /></p>
<p style="line-height: 220%" align="center">图12-3 &nbsp;修改服务启动类型为自动</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">服务正常启动后可以观察任务管理器的进程页，其中的aspnet_state.exe进程就是状态服务进程，如图12-4所示。</p>
<p style="margin-top: 12.55pt" align="center"><img height="47" alt="" src="http://book.csdn.net/BookFiles/406/img/image005.jpg" width="302" /></p>
<p style="line-height: 220%" align="center">图12-4 &nbsp;观察任务管理器的进程页</p>
<p>n&nbsp; 第2步，在system.web节点中加入：</p>
<p>&lt;sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424" </p>
<p>stateNetworkTimeout="20"&gt;&lt;/sessionState&gt;</p>
<p>n&nbsp; stateConnectionString表示状态服务器的通信地址（IP：服务端口号）。由于我们现在在本机进行测试，这里设置成本机地址127.0.0.1。状态服务默认的监听端口为42422。当然，您也可以通过修改注册表来修改状态服务的端口号。</p>
<p>n&nbsp; 1．在运行中输入regedit启动注册表编辑器。</p>
<p>n&nbsp; 2．依次打开HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\aspnet_state\Parameters节点，双击Port选项，如图12-5所示。</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">选择基数为十进制，然后输入一个端口号即可。stateNetworkTimeout属性表示从状态服务器请求Session数据最长的时间，默认为10秒，如果网络连接不是很好，请把这个数字适当设置得大一点。</p>
<p>n&nbsp; 第3步打开页面，单击&#8220;写入Session&#8221;按钮，系统会报错，如图12-6所示。</p>
<p align="center"><img height="120" alt="" src="http://book.csdn.net/BookFiles/406/img/image006.jpg" width="215" />&nbsp;&nbsp;&nbsp; <img height="122" alt="" src="http://book.csdn.net/BookFiles/406/img/image007.jpg" width="351" /></p>
<p style="text-align: justify" align="center">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 图12-5 &nbsp;修改状态服务端口号&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 图12-6 &nbsp;向StateServer默认的Session中写入自定义类出错</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">提示已经说得很清楚了，只有把对象标注为可序列化后才能在服务中进行存储。什么是序列化呢？序列化是指将对象实例的状态存储到存储媒体的过程。在此过程中，先将对象的公共字段和私有字段以及类的名称转换为字节流，然后再把字节流写入数据流。在随后对对象进行反序列化时，将创建出与原对象完全相同的副本。要使一个类可序列化，最简单的方法是使用 Serializable 属性对它进行标记。</p>
<p style="line-height: 13pt">[Serializable]</p>
<p style="line-height: 13pt">class MyUser</p>
<p style="line-height: 13pt">{</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; public string sUserName;</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; public int iAage;</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; public override string ToString()</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; {</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return string.Format("姓名：{0}，年龄：{1}", sUserName, iAage);</p>
<p style="line-height: 13pt">&nbsp;&nbsp;&nbsp; }</p>
<p style="line-height: 13pt">}</p>
<p>n&nbsp; 第4步现在重新打开页面进行测试，得到的结果和使用InProc模式是一样的。</p>
<h3>12.3.4 &nbsp;把Session存储在数据库中</h3>
<p style="text-indent: 21.25pt; line-height: 15.7pt">要把Session存储在SqlServer中，基本上也是这么几个步骤。</p>
<p>n&nbsp; 1．在命令行窗口输入cmd并在命令行中运行如下命令。</p>
<p>C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_regsql.exe -S .\SqlExpress -E &#8211;ssadd</p>
<p style="text-indent: 21pt; line-height: 15.7pt">其中 C:\Windows用你自己Windows的目录代替，v2.0.50727用你安装的2.0框架的版本号代替。-S指定SqlServer服务器地址，-E表示采用信任连接，-ssadd表示为SqlServer服务器添加状态服务的支持。操作结束后，你可以使用IDE的服务器资源管理器连接 SqlExpress数据库，可以看到多了一个ASPState数据库，但是奇怪的是数据库中没有任何表却有很多存储过程，如图12-7所示。</p>
<p style="text-indent: 21pt; line-height: 15.7pt">其实，所有Session的数据都存放在了tempdb数据库内，如图12-8所示。</p>
<p align="center"><img height="240" alt="" src="http://book.csdn.net/BookFiles/406/img/image008.jpg" width="209" />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <img height="127" alt="" src="http://book.csdn.net/BookFiles/406/img/image009.jpg" width="190" /></p>
<p style="text-align: justify" align="center">&nbsp;&nbsp;&nbsp; 图12-7 &nbsp;使用服务器资源管理器浏览ASPState数据库&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 图12-8 &nbsp;存放Session数据的tempdb数据库</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">其实，aspnet_regsql.exe有一个-sstype参数可以用来指定Session的内容和操作的存储过程存放的表。由于篇幅关系，在这里就不详细介绍了，读者可以使用aspnet_regsql.exe/?来浏览程序详细的使用方式。</p>
<p>n&nbsp; 2．打开Web.config文件，修改前面建立的sessionState节点。</p>
<p>&lt;sessionState mode="SQLServer" sqlConnectionString="server=(local)\SQLEXPRESS; </p>
<p>Trusted_Connection=True" sqlCommandTimeout="60"&gt;&lt;/sessionState&gt;</p>
<p style="text-indent: 21pt; line-height: 15.7pt">为sqlConnectionString 属性指定以前一直用的连接字符串，唯一不同的是不需要再指定数据表的名字了。sqlCommandTimeout属性表示允许执行Sql命令最长的时间，默认为30秒，可以根据自己的需要适当调整这个数字。最后，重新打开页面进行测试，得到的结果和使用InProc模式是一样的（同样你需要确保在自定义类前标注了[Serializable]），不过我们能感到速度有些慢了，毕竟数据是从数据库中进行读取或保存的，而且在使用前还需要经过序列化和反序列化操作。</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">因此Session能存储的类型为： 对于InProc模式是一切类型，而对于StateServer和SqlServer模式是一切可以序列化的类型。</p>
<h3>12.3.5 &nbsp;Session的使用范围与大小限制</h3>
<p style="text-indent: 21pt; line-height: 15.7pt">那么， 会话状态使用的范围和大小限制又是怎么样的呢？我们可以分析一下图12-8，系统使用两个表来存储Session的状态。其中有一个 ASPStateTempApplication表，用来存储Session所在的应用程序，一定程度上反映了Session是不能跨应用程序的。举例来说，我们在计算机上建立了两个网站，同时都使用Session[&#8220;UserName&#8221;]来保存登录的用户名，一个网站的用户登录后，另一个网站直接访问 Session[&#8220;UserName&#8221;]是取不到任何值的。那么，Session是否可以跨用户呢？通过前面的分析我们知道，肯定是不行的， Session通过SessionID来区分用户，一般来说SessionID是不可能出现重复的现象，也就是说Session一般是不会&#8220;串号&#8221;的。既然页面每次提交的时候都会附加上当前用户的SessionID，那么Session应该是可以跨页面的，也就是说一个网站中所有的页面都使用同一份 Session。你可以自己来做个试验，请读者打开刚才那个页面，然后按Ctrl+N组合键再打开第二个同样的页面，单击第一个页面中的&#8220;写入 Session&#8221;按钮，单击第二个页面中的&#8220;读取Session&#8221;按钮，可以发现Session的值被正确读出了。第三个问题的答案有了。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Session状态使用的范围：使用同一个客户端（浏览器实例）访问同一个应用程序的所有页面。</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">我们再来做一个试验，看看Session的容量有多大，在测试以前请修改Web.config，把Session设置为StateServer模式。然后，把写入Session的代码修改成如下（别忘记using System.Data.SqlCient）：</p>
<p>DataSet ds = new DataSet();</p>
<p>using (SqlConnection conn = new SqlConnection(@"server=(local)\SQLEXPRESS;database=Forum; </p>
<p>Trusted_Connection=True"))</p>
<p>{</p>
<p>&nbsp;&nbsp;&nbsp; SqlDataAdapter da = new SqlDataAdapter("select <sub>*</sub> from tbUser;select <sub>*</sub> from tbBoard;</p>
<p>&nbsp;&nbsp;&nbsp; select <sub>*</sub> from tbTopic;", conn);</p>
<p>&nbsp;&nbsp;&nbsp; da.Fill(ds);</p>
<p>}</p>
<p>ArrayList al = new ArrayList();</p>
<p>for(int i = 0;i&lt;10000000;i++)</p>
<p>&nbsp;&nbsp;&nbsp; al.Add(ds);</p>
<p>Session["LargeData"] = al;</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">我们把包含三个表的DataSet重复加入ArrayList中1000万次。由于这些表几乎每个表只有几条记录，这样可以模拟大数据量的情况。启动页面，单击&#8220;写入Session&#8221;按钮后可以发现，Windows服务进程一下子占用了多达70MB的内存，如图12-9所示。</p>
<p align="center"><img height="78" alt="" src="http://book.csdn.net/BookFiles/406/img/image010.jpg" width="301" /></p>
<p align="center">图12-9 &nbsp;把大量数据存放到Session中</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">Session 对于网站和用户是独立的，试想一下，如果服务器上有两个网站，每个网站的在线人数是100人，那么占用内存就要14G。是不是很恐怖的数字？因此，虽然 Session的大小没有限制，但是我们千万不能滥用Session。笔者推荐你在Session中存储少于100K的数据。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果你使用InProc模式的Session，存储过多的数据会导致IIS进程被回收，引发Session不断丢失。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果你使用StateServer存储Session，那么数据在存入Session以前需要进行序列化，序列化会消耗大量的CPU资源。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果你使用SqlServer模式的Session，数据不但要序列化而且还是存储在磁盘上，更不适合存储大量数据。</p>
<h3>12.3.6 &nbsp;Session的生命周期</h3>
<p style="text-indent: 21.25pt; line-height: 15.7pt">在了解了Session中存储的数据无大小限制后，我们可能要更多地关心Session的生命周期了。我们已经知道，Session是在用户第一次访问网站的时候创建的，那么Session是什么时候销毁的呢？Session使用一种平滑超时的技术来控制何时销毁Session。默认情况下，Session 的超时时间（Timeout）是20分钟，用户保持连续20分钟不访问网站，则Session被收回，如果在这20分钟内用户又访问了一次页面，那么20 分钟就重新计时了，也就是说，这个超时是连续不访问的超时时间，而不是第一次访问后20分钟必过时。这个超时时间同样也可以通过调整Web.config 文件进行修改：</p>
<p>&lt;sessionState timeout="30"&gt;&lt;/sessionState&gt;</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">当然你也可以在程序中进行设置：</p>
<p>Session.Timeout = "30";</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">一旦Session超时，Session中的数据将被回收，如果再使用Session系统，将给你分配一个新的SessionID。本节一开始我们就介绍了可以在URL中存储SessionID，现在请你配置Web.config文件，设置Session超时时间为1分钟，SessionID在URl中存放。打开页面后单击&#8220;写入Session&#8221;按钮，过1分钟再次单击按钮并观察SessionID是否变化。</p>
<p>&lt;sessionState timeout="1" cookieless="true"&gt;&lt;/sessionState&gt;</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">如图12-10所示，SessionID的确发生了变化。</p>
<p align="center"><img height="29" alt="" src="http://book.csdn.net/BookFiles/406/img/image011.jpg" width="416" /></p>
<p align="center"><img height="26" alt="" src="http://book.csdn.net/BookFiles/406/img/image012.jpg" width="416" /></p>
<p align="center">图12-10 &nbsp;超时后SessionID发生变化</p>
<p style="text-indent: 21.25pt; line-height: 15.7pt">不过，你可别太相信Session的Timeout属性，如果你把它设置为24小时，则很难相信24小时之后用户的Session还在。Session是否存在，不仅仅依赖于Timeout属性，以下的情况都可能引起Session丢失（所谓丢失就是在超时以前原来的Session无效）。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bin目录中的文件被改写。asp.net有一种机制，为了保证dll重新编译之后，系统正常运行，它会重新启动一次网站进程，这时就会导致 Session丢失，所以如果有access数据库位于bin目录，或者有其他文件被系统改写，就会导致Session丢失。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; SessionID丢失或者无效。如果你在URL中存储SessionID，但是使用了绝对地址重定向网站导致URL中的SessionID丢失，那么原来的Session将失效。如果你在Cookie中存储SessionID，那么客户端禁用Cookie或者Cookie达到了IE中Cookie数量的限制（每个域20个），那么Session将无效。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果使用InProc的Session，那么IIS重启将会丢失Session。同理，如果使用StateServer的Session，服务器重新启动Session也会丢失。</p>
<p style="text-indent: 21pt; line-height: 15.7pt">一般来说，如果在IIS中存储Session而且Session的Timeout设置得比较长，再加上Session中存储大量的数据，非常容易发生Session丢失的问题。</p>
<p style="text-indent: 21pt; line-height: 15.7pt">最后， Session的安全性怎么样呢？我们知道，Session中只有SessionID是存储在客户端的，并且在页面每次提交的过程中加入HTTP头发送给服务器。SessionID只是一个识别符，没有任何内容，真正的内容是存储在服务器上的。总的来说安全性还是可以的，不过笔者建议你不要使用 cookieless和SqlServer模式的Session。把SessionID暴露在URL中，把内容存储在数据库中可能会发生攻击隐患。</p>
<h3>12.3.7 &nbsp;遍历与销毁Session</h3>
<p style="text-indent: 21pt; line-height: 15.7pt">Session虽然很方便，但是要用好Session还需要自己不断实践，根据自己网站的特点灵活使用各种模式的Session。关于使用程序访问Session，笔者还想补充两点。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如何遍历当前的Session集合。</p>
<p style="line-height: 15.3pt">System.Collections.IEnumerator SessionEnum = Session.Keys.GetEnumerator();</p>
<p style="line-height: 15.3pt">while (SessionEnum.MoveNext())</p>
<p style="line-height: 15.3pt">{</p>
<p style="line-height: 15.3pt">&nbsp;&nbsp;&nbsp; Response.Write(Session[SessionEnum.Current.ToString()].ToString() + "&lt;br/&gt;");</p>
<p style="line-height: 15.3pt">}</p>
<p style="text-indent: 21pt; line-height: 15.7pt">对于我们这个例子，输出和图12-1一样。如果你仅仅为了监视Session，也可以通过trace来获得详细信息。在Web.config的system.Web节点中添加：</p>
<p style="line-height: 14.3pt">&lt;trace enabled="true"&nbsp; pageOutput="true"/&gt;</p>
<p style="text-indent: 21pt; line-height: 15.7pt">打开页面后单击&#8220;写入Session&#8221;按钮，页面显示如图12-11所示。</p>
<p style="margin-top: 15.7pt" align="center"><img height="57" alt="" src="http://book.csdn.net/BookFiles/406/img/image013.jpg" width="553" /></p>
<p align="center">图12-11 &nbsp;使用trace观察会话状态</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如何立刻让Session失效。比如用户退出系统后，Session中保存的所有数据全部失效，可以使用以下代码来让Session失效。</p>
<p>Session.Abandon();</p>
<h3 style="line-height: 320%">12.3.8&nbsp; Session的常见问题与总结</h3>
<p style="text-indent: 21pt; line-height: 16.3pt">Session的基本知识就介绍到这里，现在再回头看第一节中的几个问题，你是否都能回答了呢？为了强化大家的概念，笔者就三种模式的Session进行了一个比较（假设都使用Cookie来存储SessionID）。</p>
<p>表12.1&nbsp; 三种模式的Session比较</p>
<div align="center">
<table style="border-right: medium none; border-top: medium none; margin-left: -37.4pt; border-left: medium none; border-bottom: medium none; border-collapse: collapse" cellspacing="0" cellpadding="0" border="1">
    <tbody>
        <tr>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="107"><br />
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 116.9pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="156">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">InProc</p>
            </td>
            <td style="border-right: windowtext 1pt solid; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 130.15pt; padding-top: 0cm; border-bottom: windowtext 1pt solid" valign="top" width="174">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">StateServer</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: windowtext 1pt solid; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 135.95pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="181">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">SQLServer</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">存储物理位置</p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 116.9pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="156">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">IIS进程（内存）</p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 130.15pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="174">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">Windows服务进程（内存）</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 135.95pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="181">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">SQLServer数据库（磁盘）</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">存储类型限制</p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 116.9pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="156">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">无限制</p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 130.15pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="174">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">可以序列化的类型</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 135.95pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="181">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">可以序列化的类型</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">存储大小限制</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 383pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="511" colspan="3">
            <p style="border-right: medium none; border-top: medium none; margin-bottom: 1pt; border-left: medium none; line-height: 12.5pt; border-bottom: medium none">无限制</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">使用范围</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 383pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="511" colspan="3">
            <p style="border-right: medium none; border-top: medium none; margin-bottom: 1pt; border-left: medium none; line-height: 12.5pt; border-bottom: medium none">当前请求上下文，对于每个用户独立</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">生命周期</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 383pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="511" colspan="3">
            <p style="margin-bottom: 1pt; line-height: 12.5pt; text-align: center" align="center">第一次访问网站的时候创建Session超时后销毁</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">优点</p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 116.9pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="156">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">性能比较高</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 266.1pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="355" colspan="2">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">Session不依赖Web服务器，不容易丢失</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">缺点</p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 116.9pt; padding-top: 0cm; border-bottom: 1pt solid" width="156">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">容易丢失</p>
            </td>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 130.15pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="174">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">序列化与反序列化消耗CPU资源</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 135.95pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="181">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">序列化与反序列化消耗CPU资源，从磁盘读取Session比较慢</p>
            </td>
        </tr>
        <tr>
            <td style="border-right: 1pt solid; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 80.5pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="107">
            <p style="margin-bottom: 1pt; line-height: 12.5pt">使用原则</p>
            </td>
            <td style="border-right: medium none; padding-right: 5.4pt; border-top: medium none; padding-left: 5.4pt; padding-bottom: 0cm; border-left: medium none; width: 383pt; padding-top: 0cm; border-bottom: 1pt solid" valign="top" width="511" colspan="3">
            <p style="margin-bottom: 1pt; line-height: 12.5pt; text-align: center" align="center">不要存放大量数据</p>
            </td>
        </tr>
    </tbody>
</table>
</div>
<p style="text-indent: 21pt; line-height: 15.9pt">在使用Session的过程中你可能还会遇到很多奇怪的问题，结束本节之前笔者列出了几条常见的FAQ，供大家参考：</p>
<p style="line-height: 15.9pt">&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为什么每次请求的SessionID都不相同？</p>
<p style="line-height: 15.9pt">n&nbsp; 可能是没有在Session里面保存任何信息引起的，即程序中任何地方都没有使用Session。只有在Session中保存了内容后，Session才会和浏览器进行关联，此时的SessionID将不会再变化。</p>
<p style="line-height: 15.9pt">&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 为什么当我设置cookieless为true后，在重定向的时候会丢失Session？</p>
<p style="line-height: 15.9pt">n&nbsp; 当使用cookieless时，你必须使用相对路径替换程序中的绝对路径，如果使用绝对路径，ASP.NET将无法在URL中保存SessionID。</p>
<p style="line-height: 15.9pt">&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有办法知道应用程序的Session在运行时占用了多少内存吗？</p>
<p style="line-height: 15.9pt">n&nbsp; 没有办法，你可以通过观察IIS进程（InProc模式）或者aspnet_state进程（StateServer模式）大致估计。</p>
<p>&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 有没有可能知道整个网站使用Session的用户列表？</p>
<p>n&nbsp; 对于InProc模式和StateServer模式很难，对于SqlServer模式你可以查询存储Session的表进行尝试。</p>
<p style="line-height: 15.9pt">&#183;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 当页面中设了frameset，发现在每个frame中显示页面的SessionID在第一次请求时都不相同，为什么？</p>
<p style="line-height: 15.9pt">n&nbsp; 原因是你的frameset是放在一个HTML页面上而不是ASPX页面。在一般情况下，如果frameset是aspx页面，当你请求页面时，它首先将请求发送到Web服务器，此时已经获得了SessionID，接着浏览器会分别请求Frame中的其他页面，这样所有页面的SessionID就是一样的，就是FrameSet页面的SessionID。然而如果你使用HTML页面做FrameSet页面，第一个请求将是HTML页面，当该页面从服务器上返回时并没有任何Session产生，接着浏览器会请求Frame里面的页面，这样，这些页面都会产生自己的SessionID，所以在这种情况下就可能出现这种问题。当你重新刷新页面时，SessionID就会一样，并且是最后一个请求页面的SessionID。</p>
</blockquote>
<img src ="http://www.blogjava.net/jvict/aggbug/251985.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2009-01-19 23:55 <a href="http://www.blogjava.net/jvict/articles/251985.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>从Excel导入数据到SQL Server</title><link>http://www.blogjava.net/jvict/articles/250892.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Sun, 11 Jan 2009 14:44:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/250892.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/250892.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/250892.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/250892.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/250892.html</trackback:ping><description><![CDATA[<p>insert into TTEST(id,Name)<br />
select id,Name from <br />
OPENROWSET('MICROSOFT.JET.OLEDB.4.0'<br />
,'Excel 5.0;HDR=YES;DATABASE=c:\test.xls',sheet1$)</p>
<p><br />
exec sp_configure 'show advanced options',1<br />
reconfigure<br />
exec sp_configure 'Ad Hoc Distributed Queries',1<br />
reconfigure</p>
<img src ="http://www.blogjava.net/jvict/aggbug/250892.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2009-01-11 22:44 <a href="http://www.blogjava.net/jvict/articles/250892.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL Server 2005 备份脚本</title><link>http://www.blogjava.net/jvict/articles/247553.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Sat, 20 Dec 2008 14:57:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/247553.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/247553.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/247553.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/247553.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/247553.html</trackback:ping><description><![CDATA[DECLARE @strPath NVARCHAR(200)<br />
set @strPath = replace(replace(replace(CONVERT(varchar, getdate(), 120 ),'-',''),' ',''),':','')<br />
set @strPath = REPLACE(@strPath, ':' , '.')<br />
set @strPath = 'E:\Backup\Mis.Backup\Mis_' + @strPath + '.bak'<br />
BACKUP DATABASE Mis TO DISK = @strPath WITH NOINIT , NOUNLOAD , NOSKIP , STATS = 10, NOFORMAT
<img src ="http://www.blogjava.net/jvict/aggbug/247553.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-12-20 22:57 <a href="http://www.blogjava.net/jvict/articles/247553.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>热门数据库JDBC驱动试用心得</title><link>http://www.blogjava.net/jvict/articles/223934.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Sat, 23 Aug 2008 18:54:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/223934.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/223934.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/223934.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/223934.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/223934.html</trackback:ping><description><![CDATA[<p><a href="http://database.ctocio.com.cn/analysis/46/7697546.shtml">原文: http://database.ctocio.com.cn/analysis/46/7697546.shtml</a><br />
<br />
　本文通过介绍试用Java DB，Oracle，My SQL，MS SQL Server，MS Access等几款当下热门的数据库平台，来向读者介绍如何简单地使用各类JDBC驱动的方法模式，并结合作者实际运用的经验对上述各类数据库平台的应用进行了深入浅出的分析。其中穿插了很多使用经验和技巧，希望给各层次的开发人员都起到一定的参考作用&#8230;&#8230; </p>
<div id="content">
<div class="guanggao"><span id="contentAdv"><br />
<script language="Javascript">
</script></span></div>
<p>　　<strong>一、引言</strong></p>
<p>　　无论是初级还是中高级技术人员，面对着各式各样的数据库平台层出不穷和众多的操作系统功能不断升级，难免会眼花缭乱。特别是当系统面临升级，无论操作平台还是数据库平台，甚至架构都可能需要更替的时候，如何才能抵住众说纷纭，把握好你的选择。幸运的是，利用Java技术可以将这些不同种别的数据库平台和操作系统无缝地连接起来，真正地做到&#8220;集百家之长而为我所用&#8221;。</p>
<p>　　本文将通过一组真实的案例来向读者介绍如何做到简单地使用JDBC驱动来实现在不同的操作系统下存取几款较为热门的数据库平台。</p>
<p>　　特别是对JavaDB这款支持嵌入式模式的纯Java数据库的开发过程进行了详细分析和展望。希望读者能做到举一反三，引入更多的数据库平台的应用。</p>
<p>　　<strong>二、评测框架</strong></p>
<p>　　<strong>1.操作系统平台和数据库平台</strong></p>
<p>　　实例涉及到的操作系统是MS Windows XP + SP2和SUN Solaris 8，数据库平台有：MS Access 2000(以下简称Access)，MS SQL Server 2000(以下简称SQL Server)，My SQL，Oracle和Java DB(J2SE 1.6.0中绑定)。</p>
<p>　　对于XP平台，可以安装以上5种数据库平台。而对于Solaris，只可以安装My SQL和Java DB两种。</p>
<p>　　<strong>2.使用平台搭建</strong></p>
<p>　　(1)安装支持对应操作系统的JDK(http://java.sun.com/javase/downloads/index.jsp)。注意：如果是Solaris操作系统还必须选择对应的CPU类型，本案例中选用的是支持SPARC的JDK版本(jdk-6-solaris-sparc.sh)。在XP系统中安装的JDK Update3版本的JDK(jdk-6u3-windows-i586-p.exe)，保证该版本中已经绑定Java DB。</p>
<p>　　(2)设置JAVA_HOME，PATH和CLASSPATH等环境变量。以便正常编译和运行Java代码。</p>
<p>　　(3)下载My SQL Connector/J驱动，并将其中的mysql-connector-java-5.1.0-bin.jar文件(其中5.1.0为驱动版本号)添加到CLASSPATH变量中。需要说明的是，该驱动文件中包含两种JDBC驱动，一种是mm.mysql，一种是mysql普通JDBC驱动。两者都可以使用。</p>
<p>　　(4)将包含Java DB和Oracle的驱动文件加入到CLASSPATH中。分别为derby.jar和classes12.jar。都可以在相应的产品安装目录中找到。</p>
<p>　　通过上述的配置之后，我们就可以开始在XP系统和Solaris系统中对各类数据库平台进行使用了。</p>
<p>　　<strong>三、试用准备</strong></p>
<p>　　<strong>1.简化JDBC函数</strong></p>
<p>　　为了方便开发人员的使用，作者提炼出以下简化后的常用JDBC函数：</p>
<p>　　<img height="285" alt="" src="http://image.it168.com/cms/2007-11-2/Image/20071128463.gif" width="565" /></p>
</div>
这些函数基本上已经满足大部分的使用，初级开发人员按照函数的调用步骤就可以实现通过JDBC驱动与各种数据库平台进行交互了。
<p>　　如果用户对数据库操作的效率比较关注，那么还有3组比较重要的，也是常用的JDBC函数，分别是：</p>
<p>　　(1)事务处理函数：setAutoCommit/commit/rollback</p>
<p>　　(2)批处理函数：addBatch/execBatch</p>
<p>　　(3)语句预处理函数：prepareStatement</p>
<p>　　对于大多数开发人员，只需要知道其用法含义即可，深层次的探索和分析可能需要另外的篇幅来说明，因此作者在此不再赘述。</p>
<p>　　实际上，上述基本函数的定义，大部分都是对JDK中JDBC函数的封装，读者也可以通过JDBC的文档进行相关的查阅。关键代码参见全文末尾附录部分。</p>
<p>　　<strong>2.数据库表定义</strong></p>
<p>　　作为试用，作者并没有定义很复杂的数据库表，以下是测试用数据表结构：</p>
<p>
<table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
    <tbody>
        <tr>
            <td style="word-wrap: break-word" bgcolor="#f3f3f3">　　create&nbsp;table&nbsp;user_info( <br />
            　　ui_id&nbsp;varchar(64), <br />
            　　ui_passwd&nbsp;varchar(64), <br />
            　　ui_real_name&nbsp;varchar(64),&nbsp;primary&nbsp;key(ui_id));</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　<strong>3.试用思路</strong></p>
<p>　　比较简单，就是通过上述不同类型的JDBC驱动来连接各种数据库平台，然后向已经初始化的数据表插入10000条记录，再逐条读取，并记录其各个步骤的执行耗费。</p>
<p>　　<strong>四、试用过程</strong></p>
<p>　　<strong>1.平台选择</strong></p>
<p>　　作者选择了MS Windows XP和Solaris两种平台。其中只有MySQL，JavaDB和Oracle(连接远程服务器)既可在Windows平台进行了测试，也可在Solaris平台下进行了测试。两个系统下的测试代码和框架完全相同。</p>
<p>　　<strong>2.使用JDBC驱动连接数据库</strong></p>
<p>　　<strong>(1)Access数据库</strong></p>
<p>　　通过JDBC驱动连接Access数据库最常用的是采用建立ODBC数据源(DSN)的方式进行，但是本测试中采用的是通过数据库连接字符串避开了手工建立DSN的部分。以下是关键代码：</p>
<p>　
<table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
    <tbody>
        <tr>
            <td style="word-wrap: break-word" bgcolor="#f3f3f3">　final&nbsp;String&nbsp;connectStr&nbsp;= <br />
            　　&#8220;jdbc:odbc:driver={Microsoft&nbsp;Access&nbsp;Driver&nbsp;(*.mdb)};DBQ=./TestDB.mdb&#8221;; <br />
            　　&#8230;&#8230; <br />
            　　if(&nbsp;(conn&nbsp;=&nbsp;FoolDB.openDB(connectStr,&nbsp;null,&nbsp;null))&nbsp;==&nbsp;null)</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　用过ADO的读者可能一眼就看出来了，上述的连接字符串中的内容和ADO很相似。事实上，作者就是为了避开建立DNS而尝试套用了ADO的连接字符串，结果尝试通过了!</p>
<p>　　<strong>(2)SQL Server数据库</strong></p>
<p>　　需要说明的，对于SQL Server的测试没有采用Microsoft提供的SQL Server专用的JDBC驱动，还是通过借鉴ADO的连接字符串形式，沿用了JDK自带的JdbcOdbc驱动。</p>
<p>
<table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
    <tbody>
        <tr>
            <td style="word-wrap: break-word" bgcolor="#f3f3f3">　　final&nbsp;String&nbsp;connectStr&nbsp;= <br />
            　　&#8220;jdbc:odbc:Driver={SQL&nbsp;Server};Server=.;Database=master;UID=sa;PWD=121fs&#8221;; <br />
            　　&#8230;&#8230; <br />
            　　if(&nbsp;(conn&nbsp;=&nbsp;FoolDB.openDB(connectStr,&nbsp;null,&nbsp;null))&nbsp;==&nbsp;null)</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　注意：用户名和密码已经包含到连接字符串中。</p>
SUN公司提供的SQL Server的JDBC驱动的版本应该比较陈旧，所以可能导致在操作数据库功能支持和效率方面比当前新的JDBC驱动要差一些。Microsoft提供的SQL Server JDBC驱动类名为：&#8220;com.microsoft.jdbc.sqlserver.SQLServerDriver&#8221;，连接字符串形如：&#8220;jdbc:microsoft:sqlserver://hostname:port;DataBaseName=dbname&#8221;。
<p>　　<strong>(3)MySQL数据库</strong></p>
<p>　　众所周知，MySQL数据库既可以在Windows可以在Solaris平台运行，而且执行效率也深得业界的好评。本试例中连接MySQL使用的是MySQL专用驱动(在第一部分已经详述，在MySQL官方网页有很多的支持文档)，以下是关键代码：</p>
<p>
<table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
    <tbody>
        <tr>
            <td style="word-wrap: break-word" bgcolor="#f3f3f3">　　final&nbsp;String&nbsp;connectStr&nbsp;=&nbsp;&#8220;jdbc:mysql://localhost/phome&#8221;; <br />
            　　final&nbsp;String&nbsp;userName&nbsp;=&nbsp;&#8220;root&#8221;;&nbsp;// <br />
            　　final&nbsp;String&nbsp;passwd&nbsp;=&nbsp;&#8220;&#8220;; <br />
            　　&#8230;&#8230; <br />
            　　if(&nbsp;(conn&nbsp;=&nbsp;FoolDB.openDB(connectStr,&nbsp;userName,&nbsp;passwd))&nbsp;==&nbsp;null)</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　在本地连接时，主机名可以使用&#8220;localhost&#8221;，但如果连接远程主机时，必须换成该远程主机的IP，而phome是MySQL数据库名称。</p>
<p>　　<strong>(4)Oracle数据库</strong></p>
<p>　　Oracle提供了thin和oci两种类型的驱动，本测试中使用thin类型JDBC驱动。</p>
<p>
<table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
    <tbody>
        <tr>
            <td style="word-wrap: break-word" bgcolor="#f3f3f3">　　final&nbsp;String&nbsp;connectStr&nbsp;=&nbsp;&#8220;jdbc:oracle:thin:@WBS:1521/oracle088&#8221;; <br />
            　　final&nbsp;String&nbsp;userName&nbsp;=&nbsp;&#8220;test&#8221;; <br />
            　　final&nbsp;String&nbsp;passwd&nbsp;=&nbsp;&#8220;test&#8221;;</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　其中&#8220;WBS:1521/oracle088&#8221;为Oracle服务器的SID。</p>
<p>　　<strong>(5)Java DB</strong></p>
<p>　　值得一提的，Java DB是由Apache Software Foundation主要参与开发的一个数据库(DB)项目，SUN在JDK1.6.0中将其进行了绑定，它是一款名副其实的纯Java代码开发的数据库平台。可以支持Server/Client也可以支持嵌入式运行模式，本实例中主要采用了嵌入式模式(Embedded)进行操作：</p>
<p>
<table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
    <tbody>
        <tr>
            <td style="word-wrap: break-word" bgcolor="#f3f3f3">　　final&nbsp;String&nbsp;connectStr&nbsp;=&nbsp;&#8220;jdbc:derby:FoolDB&#8221;; <br />
            　　&#8230;&#8230; <br />
            　　if(&nbsp;(conn&nbsp;=&nbsp;FoolDB.openDB(connectStr,&nbsp;null,&nbsp;null))&nbsp;==&nbsp;null)</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　其中FoolDB是在初始化过程中，使用连接字符串&#8220;jdbc:derby:FoolDB;create=true&#8221;进行创建的。创建的结果是：在当前目录中创建一个名为FoolDB的目录，该目录又中包含log，seg0和tmp这3个文件夹，而数据库内容以多文件的方式存放于seg0目录中。</p>
<p>　　注意：数据库一旦创建之后，就无需再次创建了。</p>
<p>　　<strong>3.设置数据库事务方式</strong></p>
<p>　　当数据库连接成功之后，需要设定连接的事务方式(前提是该数据库平台支持事务处理)为非自动提交，因为JDBC函数默认为自动提交。</p>
<p>　　提交过于频繁，就会使数据库操作的效率较低。特别是对于Oracle这种绝对支持事务处理的数据平台而言，设置是否自动提交对系统的效率将有很大的影响。</p>
<strong>4.采用批处理方式插入记录</strong>
<p>　　同样一个考虑效率的操作，循环地执行操作语句(Insert，Update)也会增加很多不必要地开销。试例中采用了批量处理的方式，通过这种方式将要进行的操作先进行汇总，再批量提交执行。这样就可以获得较高的执行效率。</p>
<p>
<table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
    <tbody>
        <tr>
            <td style="word-wrap: break-word" bgcolor="#f3f3f3">　　//Insert&nbsp;records <br />
            　　for(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;RECORD_COUNT;&nbsp;++i) <br />
            　　{ <br />
            　　//Add&nbsp;each&nbsp;operation&nbsp;to&nbsp;batch <br />
            　　if(FoolDB.addBatch(execStat,&nbsp;&#8220;insert&nbsp;into&nbsp;user_info&nbsp;values('guest&#8221; <br />
            　　+&nbsp;Integer.toString(i&nbsp;+&nbsp;1) <br />
            　　+&nbsp;&#8220;',&nbsp;'666666',&nbsp;'我是中国人')&#8221;)&nbsp;==&nbsp;false) <br />
            　　&#8230;&#8230; <br />
            　　FoolDB.execBatch(execStat);&nbsp;//Execute&nbsp;batch&nbsp;operations <br />
            　　FoolDB.commit(conn); <br />
            　　FoolDB.setAutoCommit(conn,&nbsp;true);</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　这种批处理的方式，可以视同预处理，通过统合批量的操作来减少与数据库的交互频率，也减少数据库访问IO设备的频率，从而也可获得较高的效率。</p>
<p>　　<strong>5.使用行游标读取记录字段</strong></p>
<p>　　记录插入完毕之后，通过执行查询语句来获取数据集。然后再通过简化函数moveNext来逐行读取结果集的记录行：</p>
<p>
<table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
    <tbody>
        <tr>
            <td style="word-wrap: break-word" bgcolor="#f3f3f3">　　//Select&nbsp;from&nbsp;table <br />
            　　String&nbsp;sql&nbsp;=&nbsp;"select&nbsp;*&nbsp;from&nbsp;user_info"; <br />
            　　if(&nbsp;(queryRS&nbsp;=&nbsp;FoolDB.openQuery(queryStat,&nbsp;sql))&nbsp;==&nbsp;null) <br />
            　　{ <br />
            　　&#8230; <br />
            　　} <br />
            　　&#8230; <br />
            　　while(FoolDB.moveNext(queryRS)&nbsp;==&nbsp;true) <br />
            　　{ <br />
            　　//Field&nbsp;ui_id,&nbsp;text(64)&nbsp;type <br />
            　　FoolDB.getFieldByName(queryRS,&nbsp;&#8220;ui_id&#8221;); <br />
            　　//Field&nbsp;ui_passwd,&nbsp;text(64)&nbsp;type <br />
            　　FoolDB.getFieldByName(queryRS,&nbsp;&#8220;ui_passwd&#8221;); <br />
            　　//Field&nbsp;ui_real_name,&nbsp;text(64)&nbsp;type <br />
            　　FoolDB.getFieldByName(queryRS,&nbsp;&#8220;ui_real_name&#8221;); <br />
            　　}</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　实际上，moveNext的函数名也来源于ADO(在作者看来，JDBC和ADO的应用方式是相同的)。</p>
<p>　　<strong>6.关闭数据库</strong></p>
<p>　　这里主要对以嵌入式模式运行的JavaDB的关闭进行说明，其他数据库的关闭，直接采用简化后的关闭函数(closeDB)即可。</p>
<p>　　在嵌入式模式，应用程序退出时就必须关闭数据库。但是如果应用程序关闭数据库失败，当JVM退出时不会对该未被关闭的连接进行检查，这样就占用了数据库的连接资源，就会影响后续的连接执行效率。所以Apache Derby的建议是采用URL的方式显示地关闭数据库。以下是关键代码：</p>
<p>
<table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
    <tbody>
        <tr>
            <td style="word-wrap: break-word" bgcolor="#f3f3f3">　　FoolDB.closeDB(conn);&nbsp;//Close&nbsp;connection <br />
            　　if(framework.equals("embedded")&nbsp;==&nbsp;true)&nbsp;//If&nbsp;in&nbsp;embedded&nbsp;mode <br />
            　　{ <br />
            　　//Use&nbsp;URL&nbsp;to&nbsp;shutdown&nbsp;Derby <br />
            　　if(FoolDB.openDB("jdbc:derby:;shutdown=true",&nbsp;null,&nbsp;null)&nbsp;==&nbsp;null) <br />
            　　{ <br />
            　　//If&nbsp;shutdown&nbsp;failure&nbsp;means&nbsp;that&nbsp;Derby&nbsp;already&nbsp;shutdown <br />
            　　isShutdownOk&nbsp;=&nbsp;true; <br />
            　　} <br />
            　　if&nbsp;(isShutdownOk&nbsp;==&nbsp;false)&nbsp;//Not&nbsp;shutdown&nbsp;normally <br />
            　　{ <br />
            　　System.out.println("Derby&nbsp;shutdown&nbsp;NG."); <br />
            　　} <br />
            　　}</td>
        </tr>
    </tbody>
</table>
</p>
<p>　　注意：关闭和判断Derby数据库是否正常关闭的连接字符串中是不包含数据库名的。</p>
<strong>7.记录各步骤操作的时间戳</strong>
<p>　　以上的操作中，在各个步骤之间添加了时间戳，以此来记录各个数据库平台的执行耗费。</p>
<p>　　<strong>五、结果及分析</strong></p>
<p>　　<img height="281" alt="" src="http://image.it168.com/cms/2007-11-2/Image/200711285149.gif" width="578" /></p>
<p>　　在对试用结果进行评价之前，读者需要考虑各款数据库平台的特点，而不能简单地从执行时间的长短来进行判断，以下是笔者根据开发经验总结出的需要注意的地方：</p>
<p>　　(1)要保证JDBC驱动和数据库平台的连接是无缝的。例如Oracle和JavaDB数据库本身就是由Java开发，其JDBC驱动和数据库平台的连接可以做到完全无缝，这样可以充分体现出该款数据库平台的特性。反之，Access和SQL Server与对应的JdbcOdbc驱动之间的耦合可能就不如与ADO驱动那么吻合，那么这些数据平台的很多特性就无法通过这些JDBC驱动得以体现。之前我们也提到，Microsoft专门有提供MS SQL Server的JDBC驱动，数据库与这种&#8220;对口&#8221;的JDBC驱动的耦合肯定要超过JdbcOdbc这种通用型的驱动。</p>
<p>　　(2)数据库平台要有良好的可移植性。换句话说就是数据库跨操作系统的性能。在这些方面Oracle，MySQL和JavaDB就要比Access和SQL Server有明显优势，它们不仅可以支持Windows平台而且也支持Solaris和Linux平台。而且数据库平台的可移植很大程度也决定了应用系统的可移植性。</p>
<p>　　(3)数据库平台要支持应用的多样化(需求弹性)。数据库平台应该不仅可以对应传统的C/S，B/S模式，而且还可以扩展为三层的，甚至是多层的模式，或者支持嵌入式系统的应用。显而易见，本身使用Java开发的Oracle和JavaDB在这些方面就具有得天独厚的优势。而且JavaDB还支持嵌入式应用，这样以来数据库的应用空间就更为广阔了。</p>
<p>　　所以基于以上几点的考虑，我们就可以得出初步的意向：</p>
<p>　　(1)对于一般的中小型的C/S和B/S架构，MySQL可以说是我们当前首选。它在跨平台和执行效率方面表现得相当的出色。</p>
<p>　　(2)对于那些对系统构架弹性要求比较高的系统，可以选择Oracle平台，并结合EJB规范进行搭建系统构架无疑将是很好的选择。</p>
<p>　　(3)选用JavaDB进行嵌入式平台开发似乎是不错的主意。由于现在很多嵌入式设备中都嵌入了Java内核，JavaDB也就可以得以应用了，嵌入式设备与其他系统共享数据的接口就变得及其简单。</p>
<p>　　(4)如果只在Windows平台进行开发的中小型系统，用Access或者SQL Server平台也不妨是一种简单快捷的途径。</p>
<p>　　<strong>六、结束语</strong></p>
<p>　　通过前两部分的说明，相信大家对JDBC的使用应该有相当部分的了解和收获。即使作为初学者，通过简化后的JDBC函数和固定的试用方式，就可以实现通过JSP页面，Java Applet或者是Java Application等程序来访问各种类型的数据库平台了。即使是在本文中没有提到的其他数据库平台，例如：IBM的DB2，Solaris 10中绑定的PostgreSQL数据库。</p>
<p>　　尤其的，对于中高级技术人员而言，也可以通过这几种热门的数据库平台在不同操作系统下的使用案例得到一定的参考。</p>
<p>　　其中，特别是介绍了对嵌入式数据库的使用，相信也一定开阔了大家的视野和应用范围，毕竟嵌入式系统的应用在目前也是如火如荼。在后续的实际开发中笔者会将更多的心得体会和大家一起分享。</p>
<strong>七、附录：</strong>
<p>　　<strong>1.主要FoolDB函数参考</strong><strong></p>
<p>
<table style="border-right: #cccccc 1px dotted; table-layout: fixed; border-top: #cccccc 1px dotted; border-left: #cccccc 1px dotted; border-bottom: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0">
    <tbody>
        <tr>
            <td style="word-wrap: break-word" bgcolor="#f3f3f3">　　//Get&nbsp;a&nbsp;conn&nbsp;to&nbsp;special&nbsp;database. <br />
            　　public&nbsp;static&nbsp;Connection&nbsp;openDB(final&nbsp;String&nbsp;url,&nbsp;final&nbsp;String&nbsp;user,&nbsp;final&nbsp;String&nbsp;passwd) <br />
            　　{ <br />
            　　try <br />
            　　{ <br />
            　　return&nbsp;(DriverManager.getConnection(url,&nbsp;user,&nbsp;passwd)&nbsp;); <br />
            　　} <br />
            　　catch&nbsp;(SQLException&nbsp;CONNECT_FAILURE) <br />
            　　{ <br />
            　　&#8230; <br />
            　　} <br />
            　　} <br />
            　　//Get&nbsp;a&nbsp;statement&nbsp;object&nbsp;that&nbsp;can&nbsp;be&nbsp;used&nbsp;for&nbsp;query&nbsp;(read&nbsp;only) <br />
            　　public&nbsp;static&nbsp;Statement&nbsp;getQueryStat(final&nbsp;Connection&nbsp;conn) <br />
            　　{ <br />
            　　try <br />
            　　{ <br />
            　　return&nbsp;(conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, <br />
            　　ResultSet.CONCUR_READ_ONLY)&nbsp;); <br />
            　　} <br />
            　　catch(SQLException&nbsp;CREATE_QUERY_STATEMENT) <br />
            　　{ <br />
            　　&#8230; <br />
            　　} <br />
            　　} <br />
            　　//Get&nbsp;a&nbsp;statement&nbsp;object&nbsp;that&nbsp;can&nbsp;be&nbsp;used&nbsp;for&nbsp;update&nbsp;(can&nbsp;write) <br />
            　　public&nbsp;static&nbsp;Statement&nbsp;getExecStat(final&nbsp;Connection&nbsp;conn) <br />
            　　{ <br />
            　　try <br />
            　　{ <br />
            　　return&nbsp;(conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, <br />
            　　ResultSet.CONCUR_UPDATABLE)&nbsp;); <br />
            　　} <br />
            　　catch(SQLException&nbsp;CREATE_EXEC_STATEMENT) <br />
            　　{ <br />
            　　&#8230; <br />
            　　} <br />
            　　} <br />
            　　//Execute&nbsp;SQL&nbsp;statement,&nbsp;and&nbsp;get&nbsp;the&nbsp;result&nbsp;set. <br />
            　　public&nbsp;static&nbsp;ResultSet&nbsp;openQuery(final&nbsp;Statement&nbsp;stat,&nbsp;final&nbsp;String&nbsp;sql) <br />
            　　{ <br />
            　　try <br />
            　　{ <br />
            　　return&nbsp;(stat.executeQuery(sql)&nbsp;); <br />
            　　} <br />
            　　catch(SQLException&nbsp;OPEN_QUERY) <br />
            　　{ <br />
            　　&#8230; <br />
            　　} <br />
            　　} <br />
            　　//Get&nbsp;the&nbsp;rows&nbsp;cout&nbsp;of&nbsp;result&nbsp;set. <br />
            　　//The&nbsp;result&nbsp;set&nbsp;type&nbsp;should&nbsp;be&nbsp;ResultSet&nbsp;type&nbsp;is&nbsp;TYPE_SCROLL_SENSITIVE. <br />
            　　public&nbsp;static&nbsp;int&nbsp;getRowsCount(ResultSet&nbsp;rs) <br />
            　　{ <br />
            　　try <br />
            　　{ <br />
            　　int&nbsp;rowsCount&nbsp;=&nbsp;0; <br />
            　　//Backup&nbsp;current&nbsp;row&nbsp;no. <br />
            　　int&nbsp;rowNo&nbsp;=&nbsp;rs.getRow(); <br />
            　　//Locate&nbsp;last&nbsp;row <br />
            　　rs.last(); <br />
            　　//Get&nbsp;the&nbsp;rows&nbsp;count <br />
            　　rowsCount&nbsp;=&nbsp;rs.getRow(); <br />
            　　//Return&nbsp;back&nbsp;original&nbsp;row <br />
            　　if(rowNo&nbsp;&lt;&nbsp;1)&nbsp;//before&nbsp;first&nbsp;row <br />
            　　{ <br />
            　　rs.beforeFirst(); <br />
            　　} <br />
            　　else&nbsp;// <br />
            　　{ <br />
            　　rs.absolute(rowNo); <br />
            　　} <br />
            　　return&nbsp;(rowsCount); <br />
            　　} <br />
            　　catch(SQLException&nbsp;GET_ROWS_COUNT_FAILURE) <br />
            　　{ <br />
            　　&#8230; <br />
            　　} <br />
            　　} <br />
            　　//Get&nbsp;the&nbsp;columns&nbsp;count&nbsp;of&nbsp;resut&nbsp;set. <br />
            　　public&nbsp;static&nbsp;int&nbsp;getColsCount(final&nbsp;ResultSet&nbsp;rs) <br />
            　　{ <br />
            　　try <br />
            　　{ <br />
            　　ResultSetMetaData&nbsp;rsmd&nbsp;=&nbsp;rs.getMetaData(); <br />
            　　return&nbsp;(rsmd.getColumnCount()&nbsp;); <br />
            　　} <br />
            　　catch(SQLException&nbsp;GET_COLS_COUNT_FAILURE) <br />
            　　{ <br />
            　　&#8230; <br />
            　　} <br />
            　　} <br />
            　　//Get&nbsp;special&nbsp;column&nbsp;name. <br />
            　　//Note:&nbsp;The&nbsp;index&nbsp;of&nbsp;column&nbsp;base&nbsp;1,&nbsp;but&nbsp;not&nbsp;0. <br />
            　　public&nbsp;static&nbsp;String&nbsp;getColName(final&nbsp;ResultSet&nbsp;rs,&nbsp;final&nbsp;int&nbsp;colIndex) <br />
            　　{ <br />
            　　try <br />
            　　{ <br />
            　　ResultSetMetaData&nbsp;rsmd&nbsp;=&nbsp;rs.getMetaData(); <br />
            　　return&nbsp;(rsmd.getColumnName(colIndex)&nbsp;); <br />
            　　} <br />
            　　catch(SQLException&nbsp;GET_COL_NAME_FAILURE) <br />
            　　{ <br />
            　　&#8230; <br />
            　　} <br />
            　　} <br />
            　　//Move&nbsp;the&nbsp;cursor&nbsp;of&nbsp;result&nbsp;set&nbsp;to&nbsp;next&nbsp;row <br />
            　　public&nbsp;static&nbsp;boolean&nbsp;moveNext(ResultSet&nbsp;rs) <br />
            　　{ <br />
            　　try <br />
            　　{ <br />
            　　return&nbsp;(rs.next()&nbsp;); <br />
            　　} <br />
            　　catch(SQLException&nbsp;MOVE_NEXT_FAILURE) <br />
            　　{ <br />
            　　&#8230; <br />
            　　} <br />
            　　} <br />
            　　//Get&nbsp;the&nbsp;retValue&nbsp;of&nbsp;cell&nbsp;by&nbsp;special&nbsp;row&nbsp;number&nbsp;and&nbsp;column&nbsp;number <br />
            　　//The&nbsp;result&nbsp;set&nbsp;type&nbsp;should&nbsp;be&nbsp;ResultSet&nbsp;type&nbsp;is&nbsp;TYPE_SCROLL_SENSITIVE. <br />
            　　//Note:&nbsp;The&nbsp;index&nbsp;of&nbsp;row&nbsp;and&nbsp;column&nbsp;all&nbsp;base&nbsp;1,&nbsp;but&nbsp;no&nbsp;0. <br />
            　　public&nbsp;static&nbsp;Object&nbsp;getValueAt(ResultSet&nbsp;rs,&nbsp;final&nbsp;int&nbsp;rowIndex,&nbsp;final&nbsp;int&nbsp;colIndex) <br />
            　　{ <br />
            　　if(&nbsp;(rowIndex&nbsp;&lt;&nbsp;1)&nbsp;||&nbsp;(colIndex&nbsp;&lt;&nbsp;1)&nbsp;) <br />
            　　{ <br />
            　　return&nbsp;(null); <br />
            　　} <br />
            　　try <br />
            　　{ <br />
            　　//Backup&nbsp;current&nbsp;row&nbsp;no. <br />
            　　int&nbsp;rowNo&nbsp;=&nbsp;rs.getRow(); <br />
            　　Object&nbsp;retValue&nbsp;=&nbsp;null; <br />
            　　//Locate&nbsp;to&nbsp;special&nbsp;row <br />
            　　rs.absolute(rowIndex); <br />
            　　//Get&nbsp;retValue <br />
            　　retValue&nbsp;=&nbsp;rs.getObject(colIndex); <br />
            　　//Return&nbsp;back&nbsp;origianl&nbsp;row <br />
            　　rs.absolute(rowNo); <br />
            　　return&nbsp;(retValue); <br />
            　　} <br />
            　　catch(SQLException&nbsp;GET_VALUE_FAILURE) <br />
            　　{ <br />
            　　&#8230; <br />
            　　} <br />
            　　} <br />
            　　//Get&nbsp;the&nbsp;retValue&nbsp;of&nbsp;cell&nbsp;by&nbsp;special&nbsp;row&nbsp;number&nbsp;and&nbsp;field&nbsp;name <br />
            　　//The&nbsp;result&nbsp;set&nbsp;type&nbsp;should&nbsp;be&nbsp;ResultSet&nbsp;type&nbsp;is&nbsp;TYPE_SCROLL_SENSITIVE. <br />
            　　//Note:&nbsp;The&nbsp;index&nbsp;of&nbsp;row&nbsp;and&nbsp;column&nbsp;all&nbsp;base&nbsp;1,&nbsp;but&nbsp;no&nbsp;0. <br />
            　　public&nbsp;static&nbsp;Object&nbsp;getFieldByName(ResultSet&nbsp;rs,&nbsp;final&nbsp;int&nbsp;rowIndex,&nbsp;final&nbsp;String&nbsp;fieldName) <br />
            　　{ <br />
            　　if(&nbsp;(rowIndex&nbsp;&lt;&nbsp;1)&nbsp;||&nbsp;(fieldName.equals("")&nbsp;==&nbsp;true)&nbsp;) <br />
            　　{ <br />
            　　return&nbsp;(null); <br />
            　　} <br />
            　　try <br />
            　　{ <br />
            　　//Backup&nbsp;current&nbsp;row&nbsp;no. <br />
            　　int&nbsp;rowNo&nbsp;=&nbsp;rs.getRow(); <br />
            　　Object&nbsp;retValue&nbsp;=&nbsp;null; <br />
            　　//Locate&nbsp;to&nbsp;special&nbsp;row <br />
            　　rs.absolute(rowNo); <br />
            　　//Get&nbsp;retValue <br />
            　　retValue&nbsp;=&nbsp;rs.getObject(fieldName); <br />
            　　//Return&nbsp;back&nbsp;origianl&nbsp;row&nbsp;no. <br />
            　　rs.absolute(rowNo); <br />
            　　return&nbsp;(retValue); <br />
            　　} <br />
            　　catch(SQLException&nbsp;GET_FIELD_BY_NAME_FAILURE) <br />
            　　{ <br />
            　　&#8230; <br />
            　　} <br />
            　　} <br />
            　　//Get&nbsp;the&nbsp;retValue&nbsp;of&nbsp;cell&nbsp;within&nbsp;current&nbsp;row&nbsp;by&nbsp;special&nbsp;field&nbsp;name <br />
            　　//The&nbsp;result&nbsp;set&nbsp;type&nbsp;should&nbsp;be&nbsp;ResultSet&nbsp;type&nbsp;is&nbsp;TYPE_SCROLL_SENSITIVE. <br />
            　　//Note:&nbsp;The&nbsp;index&nbsp;of&nbsp;row&nbsp;and&nbsp;column&nbsp;all&nbsp;base&nbsp;1,&nbsp;but&nbsp;no&nbsp;0. <br />
            　　public&nbsp;static&nbsp;Object&nbsp;getFieldByName(final&nbsp;ResultSet&nbsp;rs,&nbsp;final&nbsp;String&nbsp;fieldName) <br />
            　　{ <br />
            　　if(&nbsp;(isBOF(rs)&nbsp;==&nbsp;true)&nbsp;||&nbsp;(isEOF(rs)&nbsp;==&nbsp;true)&nbsp;) <br />
            　　{ <br />
            　　return&nbsp;(null); <br />
            　　} <br />
            　　try <br />
            　　{ <br />
            　　return&nbsp;(rs.getObject(fieldName)&nbsp;); <br />
            　　} <br />
            　　catch(SQLException&nbsp;GET_FIELD_BY_NAME_FAILURE) <br />
            　　{ <br />
            　　&#8230; <br />
            　　} <br />
            　　} <br />
            　　//Get&nbsp;the&nbsp;retValue&nbsp;of&nbsp;cell&nbsp;within&nbsp;current&nbsp;row&nbsp;by&nbsp;special&nbsp;column&nbsp;index <br />
            　　//The&nbsp;result&nbsp;set&nbsp;type&nbsp;should&nbsp;be&nbsp;ResultSet&nbsp;type&nbsp;is&nbsp;TYPE_SCROLL_SENSITIVE. <br />
            　　//Note:&nbsp;The&nbsp;index&nbsp;of&nbsp;row&nbsp;and&nbsp;column&nbsp;all&nbsp;base&nbsp;1,&nbsp;but&nbsp;no&nbsp;0. <br />
            　　public&nbsp;static&nbsp;Object&nbsp;getFieldByIndex(final&nbsp;ResultSet&nbsp;rs,&nbsp;final&nbsp;int&nbsp;columnIndex) <br />
            　　{ <br />
            　　if(&nbsp;(columnIndex&nbsp;&lt;&nbsp;1)&nbsp;||&nbsp;(isBOF(rs)&nbsp;==&nbsp;true)&nbsp;||&nbsp;(isEOF(rs)&nbsp;==&nbsp;true)&nbsp;) <br />
            　　{ <br />
            　　return&nbsp;(null); <br />
            　　} <br />
            　　try <br />
            　　{ <br />
            　　return&nbsp;(rs.getObject(columnIndex)&nbsp;); <br />
            　　} <br />
            　　catch(SQLException&nbsp;GET_FIELD_BY_INDEX_FAILURE) <br />
            　　{ <br />
            　　&#8230; <br />
            　　} <br />
            　　}</td>
        </tr>
    </tbody>
</table>
</strong></p>
<img src ="http://www.blogjava.net/jvict/aggbug/223934.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-08-24 02:54 <a href="http://www.blogjava.net/jvict/articles/223934.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用hibernate 连接SQLServer2005</title><link>http://www.blogjava.net/jvict/articles/223920.html</link><dc:creator>Documents</dc:creator><author>Documents</author><pubDate>Sat, 23 Aug 2008 16:17:00 GMT</pubDate><guid>http://www.blogjava.net/jvict/articles/223920.html</guid><wfw:comment>http://www.blogjava.net/jvict/comments/223920.html</wfw:comment><comments>http://www.blogjava.net/jvict/articles/223920.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/jvict/comments/commentRss/223920.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/jvict/services/trackbacks/223920.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 原文: http://blog.csdn.net/sonicluo3/archive/2007/06/24/1664367.aspx最近一段时间都在学习hibernate和SQLServer .发现SQLServer有个问题就是默认安装的时候1433端口是不会打开的所以必需在连接前手动去打开.首先看看数据库表的创建use&nbsp;demo;CREATE&nbsp;TA...&nbsp;&nbsp;<a href='http://www.blogjava.net/jvict/articles/223920.html'>阅读全文</a><img src ="http://www.blogjava.net/jvict/aggbug/223920.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/jvict/" target="_blank">Documents</a> 2008-08-24 00:17 <a href="http://www.blogjava.net/jvict/articles/223920.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>