﻿<?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>IT博客-D盘-随笔分类-数据库访问</title><link>http://www.cnitblog.com/wufajiaru/category/6820.html</link><description>workspace</description><language>zh-cn</language><lastBuildDate>Wed, 28 Sep 2011 07:54:51 GMT</lastBuildDate><pubDate>Wed, 28 Sep 2011 07:54:51 GMT</pubDate><ttl>60</ttl><item><title> 内部泄密[转]</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/28/40244.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Thu, 28 Feb 2008 06:15:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/28/40244.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/40244.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/28/40244.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/40244.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/40244.html</trackback:ping><description><![CDATA[<p class="zhengwen style80"><span class=txttop><span class=style114><strong>【编者按】<br>FBI和CSI对484家公司进行了网络安全专项调查，调查结果显示：超过85%的安全威胁来自公司内部。在损失金额上，由于内部人员泄密导致的损失是黑客造成损失的16倍... </strong></span></span></p>
<p class="zhengwen style80">安全产品和方案是防止信息外泄的必要条件，而不是充分条件。充分条件中还应该包括体系的构建和制度的形成。 </p>
<p class="zhengwen style80">由于网络和计算机系统固有的特性，它在提高数据与设备共享性的同时，带来了信息、数据被非法窃取、复制、使用等弊端，对涉及国家机密及企业内部敏感数据的安全管理形成极大的挑战。 </p>
<p class="zhengwen style80">为防止数据外泄，企业往往不惜花巨资购进防火墙、入侵检测、防病毒、漏洞扫描等网络安全产品，以为可以高枕无忧了。其实，这种想法是错误而且极其危险的。 </p>
<p class="zhengwen style80">FBI和CSI对484家公司进行了网络安全专项调查，调查结果显示：超过85%的安全威胁来自公司内部。在损失金额上，由于内部人员泄密导致了6056.5万美元的损失，是黑客造成损失的16倍，是病毒造成损失的12倍。 </p>
<p class="zhengwen style80">这组数据充分说明了内部人员泄密的严重危害，同时也提醒国内组织应加强网络内部安全建设。 <br></p>
<p class="zhengwen style80">数据从这些渠道丢失 <br>传输渠道 <br>内网大多是将员工的计算机物理连接起来组成的一个网络。只要是物理连接，理论上讲，其中的任意一台计算机都可以访问其他连在这个网络上正在工作的计算机。 </p>
<p class="zhengwen style80">现有的安全系统对桌面终端的日常操作及攻击缺乏有效的监控、防护手段，由于网络可以方便地进行资源共享，信息在网络上传输不受监控，对涉密信息没有采取传输范围和传输前密码授权控制，使得一些涉密信息极有可能通过网络，从一些开放的终端传出去，而不留痕迹。 </p>
<p class="zhengwen style80">流转渠道 <br>科技高度发展的今天，电子产品日新月异，小巧易带的软盘、光盘、U盘、移动硬盘、软盘、笔记本电脑甚至MP3等可移动存储的磁介质越来越小，装载的信息量越来越多。 </p>
<p class="zhengwen style80">在使用中，为防范信息泄露，要求员工用完后，即时将信息或数据删除掉再借出，以为这样他人就无法取得信息，殊不知磁介质有可以被提取还原的特性，他人一样可以取走信息。 </p>
<p class="zhengwen style80">失控出口<br>对涉密信息没有进行加密处理或者保护处理，将涉密信息通过各种出口，如USB口、串口等方式拷出去，出口缺乏必要的监控和审计。 </p>
<p class="zhengwen style80">对于打印文件的管理，很多企业主要是靠管理员督促，员工打印时进行登记，但员工若打印了涉密信息不进行登记，便无从追查，更无法提供违规操作的证据，安全隐患较大。 </p>
<p class="zhengwen style80">&#8220;残疾&#8221;制度<br>有的企业没有配备专门的计算机维护管理人员，或者机房管理不严格，无关人员可以随意进出机房。 </p>
<p class="zhengwen style80">当机器发生故障时，随意叫自己的朋友或者外面非专业公司的人员进入机房维修，或者将发生故障的计算机送修前不做消磁处理，或不安排专人监修，都会丢失涉密数据。</p>
<p class="zhengwen style80">如何给内网&#8220;上锁&#8221; <br>针对各种泄密途径，要防止内网涉密信息外泄，应着重从加强内网安全防范措施。那么，应在内网中构筑一个怎样的内控安全体系或系统呢？ </p>
<p class="zhengwen style80">边界不可小觑 <br>内网安全的威胁不同于网络边界的威胁。网络边界安全技术防范来自Internet上的攻击，主要是防范来自公共的网络服务器如HTTP或SMTP的攻击。网络边界防范减小了资深黑客仅仅只需接入互联网、写程序就可访问企业网的几率。 </p>
<p class="zhengwen style80">内网安全威胁主要源于企业内部。恶性的黑客攻击事件一般都会先控制局域网络内部的一台Server，然后以此为基地，对Internet上其他主机发起恶性攻击。因此，应在边界展开黑客防护措施，同时建立并加强内网防范策略。 </p>
<p class="zhengwen style80">限制VPN <br>VPN用户的访问对内网的安全造成了巨大的威胁。因为它们将弱化的桌面操作系统置于企业防火墙的防护之外。 </p>
<p class="zhengwen style80">很明显VPN用户是可以访问企业内网的。因此要避免给每一位VPN用户访问内网的全部权限。 </p>
<p class="zhengwen style80">这样可以利用登录控制权限列表，限制VPN用户的登录权限的级别。即只需赋予他们所需要的访问权限级别即可，如访问邮件服务器或其他可选择的网络资源的权限。 </p>
<p class="zhengwen style80">小心合作网<br>合作企业网也是造成内网安全问题的一大原因。既然不能控制合作者的网络安全策略和活动，那么就应该为每一个合作企业创建一个DMZ，并将他们所需要访问的资源放置在相应的DMZ中，不允许他们对内网其他资源访问。 </p>
<p class="zhengwen style80">跟踪也要策略<br>智能的自动执行实时跟踪的安全策略是有效地实现网络安全实践的关键,它带来了商业活动中一大改革，极大地超过了手动安全策略的功效。 </p>
<p class="zhengwen style80">商业活动的现状需要企业利用一种自动检测方法来探测商业活动中的各种变更，因此，安全策略也必须与其相适应。例如实时跟踪企业员工的雇佣和解雇,实时跟踪网络利用情况，并记录与该计算机对话的文件服务器。 </p>
<p class="zhengwen style80">总之，要做到确保每天的活动都遵循安全策略。 </p>
<p class="zhengwen style80">有的服务器可以关 <br>大型企业网可能同时支持4～5个服务器传送E-mail，有的企业网还会出现几十个其他服务器监视SMTP端口的情况。这些主机中很可能有潜在的邮件服务器的攻击点。因此要逐个中断网络服务器来进行审查。 </p>
<p class="zhengwen style80">若一个程序（或程序中的逻辑单元）作为一个Window文件服务器在运行，但又不具有文件服务器作用，应关掉该文件的共享协议。 </p>
<p class="zhengwen style80">重要资源重点保护 <br>若一个内网上连了千万台主机，那么要期望保持每一台主机都处于锁定状态和补丁状态是非常不现实的。大型企业网的安全建设一般都存在择优问题。 </p>
<p class="zhengwen style80">首先要对服务器做效益分析评估，然后对内网的每一台网络服务器进行检查、分类、修补和强化工作，找出重要的网络服务器，并对它们进行限制管理。 </p>
<p class="zhengwen style80">无线访问须可靠 <br>审查网络，为实现无线访问建立基础。排除无意义的无线访问点，确保无线网络访问的强制性和可利用性，并提供安全的无线访问接口。 </p>
<p class="zhengwen style80">将访问点置于边界防火墙之外，并允许用户通过VPN技术进行访问。 </p>
<p class="zhengwen style80">严查&#8220;过客&#8221; <br>对于过客不必给予其公开访问内网的权限。许多安全技术人员执行的&#8220;内部无Internet访问&#8221;的策略，使得员工给客户一些非法的访问权限，导致内网实时跟踪的困难。因此，须在边界防火墙之外建立过客访问网络块。 </p>
<p class="zhengwen style80">&#8220;虚拟&#8221;的用处 <br>主机是被攻击的主要对象。与其让所有主机不遭攻击，还不如多考虑一下如何使攻击者无法通过受攻击的主机来攻击内网。 </p>
<p class="zhengwen style80">如果一个市场用户的客户机被侵入了，攻击者也不会由此而进入到公司的R&amp;D（人力资源部）。因此要实现公司R&amp;D与市场之间的访问权限控制，即建立网上不同商业用户群之间的边界防护。 </p>
<p class="zhengwen style80">决策的技巧 <br>网络用户存在着安全隐患。 <br>有的用户或许对网络安全知识非常欠缺，例如不知道RADIUS和TACACS之间的不同，或不知道代理网关和分组过滤防火墙之间的不同等等，但是他们作为公司的合作者，也是网络的使用者。 </p>
<p class="zhengwen style80">因此企业网就要让这些用户也容易使用，这样才能引导他们自动地响应网络安全策略。 </p>
<p class="zhengwen style80">为制度操练 <br>一个完整的内控安全系统应是技术手段和管理制度相结合的体系，所以管理制度是相当必要的，它可以有效地弥补产品无法用技术手段解决的安全漏洞。 </p>
<p class="zhengwen style80">在构建内控安全系统方面，防护网络中最薄弱的环节—桌面终端是重中之重。系统应该结合桌面监控审计技术与企业原有部署的网络安全技术，形成技术的整体防范能力；并在在企业现有的保密制度基础之上，结合监控审计系统，制定相应的管理措施，增强各级人员安全意识，建立健全保密制度；同时，加强信息安全人员的队伍建设，加强培训，将各项保密工作落到实处，确保各项管理措施得到贯彻执行。 </p>
<p class="zhengwen style80">通过以上各方面的工作，最终形成&#8220;制度保障、组织管理、技术防范&#8221;的整体合力，建立内控安全的整体防范体系，从而构建一个安全、可信赖的内部网络工作环境。<br><br><br>转自：<a href="http://www.activenet.cn/bbs/showpost.asp?menu=Previous&amp;ForumID=7&amp;ThreadID=161">http://www.activenet.cn/bbs/showpost.asp?menu=Previous&amp;ForumID=7&amp;ThreadID=161</a></p>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/40244.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-28 14:15 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/28/40244.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>高级：JDO技术及如何进入企业应用示例</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39931.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Tue, 19 Feb 2008 06:39:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39931.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39931.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39931.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39931.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39931.html</trackback:ping><description><![CDATA[<table style="MARGIN-BOTTOM: 20px; WIDTH: 968px; HEIGHT: 25px" cellSpacing=0 cellPadding=0 width=968 border=0>
    <tbody>
        <tr>
            <td align=middle><span class=content01></span><span class=b>发布时间：2008.02.03 04:41</span>&nbsp;&nbsp;&nbsp;&nbsp;<span class=b> 来源：赛迪网</span>&nbsp;&nbsp;&nbsp;&nbsp;<span class=b>作者：xuyy_cn</span></td>
        </tr>
    </tbody>
</table>
<table class=p11 style="WIDTH: 970px; HEIGHT: 14034px" cellSpacing=0 cellPadding=0 width=970 border=0>
    <tbody>
        <tr>
            <td style="WORD-WRAP: break-word" align=left>
            <p class=a14c style="TEXT-INDENT: 2em"><span class=a14c id=zoom>
            <p style="TEXT-INDENT: 2em">JDO（Java&nbsp;Data&nbsp;Object）是JCP中较早开发出来并形成规范的JSR12，该规范对数据的持久化存储进行了一系列规范，并已有众多的商业产品和开源项目是基于该规范。作为一种需要引起重视的技术，研究并探讨其企业应用可行性是十分重要的。&nbsp;<br><br>前言&nbsp;<br><br>在企业级的应用开发中，常需要有良好的持久化技术来支持数据存储。通过良好的规范或API，将企业的领域业务对象进行持久化存储，大多采用O/R映射技术来进行模式化的数据转换及自动映射工作。&nbsp;<br><br>JDO（Java&nbsp;Data&nbsp;Object）是JCP中较早开发出来并形成规范的JSR12，该规范对数据的持久化存储进行了一系列规范，并已有众多的商业产品和开源项目是基于该规范。作为一种需要引起重视的技术，研究并探讨其企业应用可行性是十分重要的。&nbsp;<br><br>以下主要对JDO（JDO&nbsp;1.0规范）的应用开发技术作扼要介绍，通过该文，可以由浅入深、并较为全面地了解JDO，掌握主要的技术细节及过程，理解其运行机制，并对企业级应用有个总体的把握，这将有助于企业应用软件的技术选型、体系架构及分析设计活动。&nbsp;<br><br>该文适合企业应用架构师、及关心数据持久层设计开发人员。&nbsp;<br><br>JDO基本思想及特点&nbsp;<br><br>企业信息系统的一个重要问题是解决数据的存储，即持久化。在软件开发过程中，分析员分析领域业务，提取出领域业务模型，并对应设计出数据库中需要进行存储业务数据的数据库表及相应字段。&nbsp;<br><br>并根据业务流程，设计业务处理逻辑单元，进行数据的加工、处理及存储、查询等业务。其中一个较为繁烦、枯燥的工作，就是处理大量的数据持久化代码。&nbsp;<br><br>为了解决数据从业务对象层向数据存储层之间的转换工作，JDO提供了相应的开发规范及API，解决了由Java对象直接存储为数据库相应表的底层处理过程，有助于设计人员更加专注于面向业务流程、面向业务对象等较高层次的应用。&nbsp;<br><br>由于采用JDO的映射机制，能降低了业务系统与数据存储系统的耦合，使得业务系统相对于关系数据库或对象型数据库，具有可移植性，同时，由于采用面向对象（而非传统的面向记录）的持久化技术，系统更为轻便、简洁，增强了可维护性。&nbsp;<br><br>JDO应用示例及分析&nbsp;<br><br>以下将通过一些示例，由浅及深地讲解JDO技术。&nbsp;<br><br>临时对象与持久对象&nbsp;<br><br>这是一个普通的业务对象的代码。&nbsp;<br><br><br><br><br><br><br><br><br><br><br>package&nbsp;business.model;&nbsp;<br>public&nbsp;class&nbsp;Book&nbsp;<br>{&nbsp;<br>private&nbsp;String&nbsp;isbn;&nbsp;<br>private&nbsp;String&nbsp;name;&nbsp;<br>private&nbsp;Date&nbsp;publishDate;&nbsp;<br>public&nbsp;void&nbsp;setISBN(String&nbsp;isbn)&nbsp;<br>{&nbsp;<br>this.isbn&nbsp;=&nbsp;isbn;&nbsp;<br>}&nbsp;<br>public&nbsp;String&nbsp;getISBN()&nbsp;<br>{&nbsp;<br>return&nbsp;this.isbn;&nbsp;<br>}&nbsp;<br>public&nbsp;void&nbsp;setName(String&nbsp;name)&nbsp;<br>{&nbsp;<br>this.name&nbsp;=&nbsp;name;&nbsp;<br>}&nbsp;<br>public&nbsp;String&nbsp;getName()&nbsp;<br>{&nbsp;<br>return&nbsp;this.name;&nbsp;<br>}&nbsp;<br>public&nbsp;void&nbsp;<br>setPublishDate(Date&nbsp;pubDate)&nbsp;<br>{&nbsp;<br>this.publishDate&nbsp;=&nbsp;pubDate;&nbsp;<br>}&nbsp;<br>public&nbsp;Date&nbsp;getPublishDate()&nbsp;<br>{&nbsp;<br>return&nbsp;this.publishDate;&nbsp;<br>}&nbsp;<br>}&nbsp;<br><br><br><br><br>现在将它作为一个JDO中对象保存到数据库中。代码如下：&nbsp;<br><br><br>Book&nbsp;book&nbsp;=&nbsp;new&nbsp;Book();&nbsp;<br>book.setISBN(&#8220;isbn-1234567&#8221;);&nbsp;<br>book.setName(&#8220;Java设计模式&#8221;);&nbsp;<br><br>PersistenceManager&nbsp;<br>manager&nbsp;=&nbsp;persistenceManagerFactory.&nbsp;<br>getPersistenceManager();&nbsp;<br>manager.currentTransaction().begin();&nbsp;<br>manager.makePersistence(book);&nbsp;<br>manager.currentTransaction().commit();&nbsp;<br><br><br><br><br>Book类的实例book对JDO的API而言，就是一个持久对象。类Book是可持久类。那任何一个普通java类都是JDO的可持久类吗？不是的。只有具备以下的条件，一个对象才可以被JDO持久到数据库中。&nbsp;<br><br>它所属类应标记为可持久的类，有以下两种方法：&nbsp;<br><br>显式：实现接口，javax.jdo.PersistenceCapable即可；&nbsp;<br><br>隐式：以Sun的JDO参考实现为例，Book.java类的相同路径下还须有Book.jdo文件。&nbsp;<br><br><br>encoding&nbsp;=&nbsp;&#8220;UTF-8&#8221;?&gt;&nbsp;<br><br><br><br><br><br><br><br><br><br><br>并通过字节码增强工具（本例采用Sun的字节码增强工具）处理:&nbsp;<br><br><br>javac&nbsp;Book.java&nbsp;<br>java&nbsp;com.sun.jdori.enhancer.Main&nbsp;<br>Book.class&nbsp;Book.jdo&nbsp;<br><br><br><br><br>通过上述两种方法，获得的Book.class才是一个可持久的类。&nbsp;<br><br>字节码增强的有如下功能：当应用程序通过set方法修改某个字段1时，由于通过增强过程，在其内部插入了某些代码，JDO会获得数据状态变化的信息，从而在持久过程中，进行有选择性的处理。&nbsp;<br><br>按照JDO规范，增强后的类可以在不同的JDO实现上使用，而无需重新编译或增强。&nbsp;<br><br>并不是所有Book对象都是持久对象，只有当makePersistence后，该对象才是持久对象，并会通过JDO实现存储到数据库中。通过JDO的供应商扩展标记符（vendor-extension），可详细描述Book类的存储特性，如为该可持久类指定数据库表和对应字段。&nbsp;<br><br>持久对象查询&nbsp;<br><br>JDO查询主要有以下两种方式。&nbsp;<br><br>使用Extend查询&nbsp;<br><br>Extend可以查询指定类及子类的持久对象。&nbsp;<br><br><br>PersistenceManager&nbsp;<br>manager&nbsp;=&nbsp;persistenceManagerFactory.&nbsp;<br>getPersistenceManager();&nbsp;<br>manager.currentTransaction().begin();&nbsp;<br>Extend&nbsp;extend&nbsp;=&nbsp;<br>manager.getExtend(Book.class,true);&nbsp;<br>//true表明同时查询子类&nbsp;<br>Iterator&nbsp;it&nbsp;=&nbsp;extend.iterator();&nbsp;<br>while(it.hasNext())&nbsp;<br>{&nbsp;<br>Book&nbsp;book&nbsp;=&nbsp;(Book)it.next();&nbsp;<br>System.out.println(book.getISBN());&nbsp;<br>}&nbsp;<br>extend.closeAll();&nbsp;<br>manager.currentTransaction().commit();&nbsp;<br><br><br><br><br>Extend查询方法，提供了一种基于类的查询途径，它可以与下面的Query构成更为强大的查询。&nbsp;<br><br>使用Query查询&nbsp;<br><br>Query可以指定过滤条件，是一种常用的查询方式。&nbsp;<br><br>下例是查找条件为&#8220;书名以&#8216;Java设计模式&#8217;开头且出版日期小于今天&#8221;的书籍。&nbsp;<br><br><br>String&nbsp;filter&nbsp;=&nbsp;<br>&#8220;((String)name).startsWith(\&#8221;Java设计模式\&#8221;)&nbsp;<br>&amp;&amp;&nbsp;publishDate&nbsp;&lt;&nbsp;today&#8221;;&nbsp;<br>Query&nbsp;query&nbsp;=&nbsp;<br>pm.getQuery(Book.class,filter);&nbsp;<br>query.declareImports(&#8220;import&nbsp;java.util.Date&#8221;);&nbsp;<br>query.declareParameters(&#8220;Date&nbsp;today);&nbsp;<br><br>Date&nbsp;today&nbsp;=&nbsp;new&nbsp;Date();&nbsp;<br>results&nbsp;=&nbsp;(Collection)&nbsp;<br>query.execute(today);&nbsp;<br>//传入参数值today&nbsp;<br>if&nbsp;(results.isEmpty())&nbsp;<br>{&nbsp;<br>System.out.println(&#8220;No&nbsp;data!&#8221;);&nbsp;<br>}else{&nbsp;<br>Iterator&nbsp;it&nbsp;=&nbsp;results.iterator();&nbsp;<br>while(it.hasNext())&nbsp;<br>{&nbsp;<br>Book&nbsp;book&nbsp;=&nbsp;(Book)it.next();&nbsp;<br>System.out.println&nbsp;<br>(&#8220;Book&nbsp;Name:&#8221;&nbsp;+&nbsp;book.getName()&nbsp;<br>+&nbsp;&#8220;,&nbsp;ISBN:&#8221;&nbsp;+&nbsp;book.getISBN());&nbsp;<br>}&nbsp;<br>}&nbsp;<br><br><br><br><br>注：该条件使用了一个变元&#8216;today&#8217;，通过&#8220;declareParameters&#8221;来声明该变量，并在&#8220;execute&#8221;方法中传入该变量的实例。这种带参数的查询，很类似于我们以前采用JDBC的带?的查询方式。&nbsp;<br><br>其中startsWith(String&nbsp;s)是JDO提供的标准字符方法，类似的方法还有endsWith(String&nbsp;s)。&nbsp;<br><br>JDOQL：上述使用的就是一个JDOQL样例，JDOQL是JDO规范一个组成部分。使用JDOQL可以使用应用在不同的JDO实现上运行。为了解决JDOQL的某些不足，JDO规范提供了支持特定JDO供应商查询语句接口。&nbsp;<br><br>查询排序&nbsp;<br><br>下例是将查询结果按&#8220;出版日期降序、书名升序&#8221;进行排序。&nbsp;<br><br><br>Query&nbsp;query&nbsp;=&nbsp;<br>pm.newQuery(Book.class,&nbsp;filter);&nbsp;<br><br>String&nbsp;orderStr&nbsp;=&nbsp;<br>&#8220;publishDate&nbsp;decending,&nbsp;name&nbsp;ascending&#8221;;&nbsp;<br>query.setOrdering(orderStr);&nbsp;<br><br>results&nbsp;=&nbsp;query.execute(today);&nbsp;<br><br><br>对象更新&nbsp;<br><br>当客户端对业务数据进行了更新后，需要通过业务过程将其更新到持久层中。这有两个过程，首先根据主键找到该实例，接着更新字段及提交。如下例，将指定书目编号的书本的出版日期进行更改。&nbsp;<br><br><br><br><br><br><br><br><br><br><br><br><br>public&nbsp;void&nbsp;updateBookPublishDate&nbsp;<br>(String&nbsp;isbn,&nbsp;Date&nbsp;newDate)&nbsp;<br>{&nbsp;<br>PersistenceManager&nbsp;pm&nbsp;=&nbsp;null;&nbsp;<br>try{&nbsp;<br>pm&nbsp;=&nbsp;pmf.getPersistenceManager();&nbsp;<br>Object&nbsp;obj&nbsp;=&nbsp;<br>pm.newObjectIdInstance(Book.class,isbn);&nbsp;<br>Book&nbsp;book&nbsp;=&nbsp;<br>(Book)pm.getObjectById(obj,true);&nbsp;<br>book.setPublishDate(newDate);&nbsp;<br>}catch(Exception&nbsp;e)&nbsp;<br>{&nbsp;<br>xxxContext.setRollbackOnly();&nbsp;<br>throw&nbsp;new&nbsp;Exception(e);&nbsp;<br>}finally{&nbsp;<br>try{&nbsp;<br>if&nbsp;(pm&nbsp;!=&nbsp;null&nbsp;&amp;&amp;&nbsp;!pm.isClosed())&nbsp;<br>{&nbsp;<br>pm.close();&nbsp;<br>}&nbsp;<br>}catch(Exception&nbsp;ex)&nbsp;<br>{&nbsp;<br>System.out.println(ex);&nbsp;<br>}&nbsp;<br>}&nbsp;<br><br><br><br><br>注，在PersistenceManager使用newObjectIdInstance（）方法时，JDO是如何知道通过书目编号ISBN来找到该对象呢？其实在本可持久类Book的jdo描述文件中，还需提供如下信息：&nbsp;<br><br><br>encoding&nbsp;=&nbsp;&#8220;UTF-8&#8221;?&gt;&nbsp;<br><br><br><br>identity-type=&#8220;application&#8221;&nbsp;<br>objectid-class=&#8220;BookKey&#8221;&nbsp;&gt;&nbsp;<br>primary-key=&#8220;true&#8221;/&gt;&nbsp;<br><br><br><br><br><br><br><br>其中&#8220;identity-type=&#8220;application&#8221;&#8221;声明可持久类Book采用程序标识方式，即应用程序传入ID（字段isbn为&#8220;primary-key&#8221;）信息，JDO实现构造出指定的&#8220;objectid-class&#8221;的实例（即newObjectIdInstance过程），并由JDO来检索出指定的持久化对象（即getObjectById）。&nbsp;<br><br>BookKey类源码如下：&nbsp;<br><br><br>package&nbsp;businesss.model;&nbsp;<br>public&nbsp;class&nbsp;BookKey&nbsp;implements&nbsp;<br>java.io.Serializable&nbsp;<br>{&nbsp;<br>public&nbsp;String&nbsp;isbn;&nbsp;<br>public&nbsp;BookKey()&nbsp;<br>{&nbsp;<br>}&nbsp;<br>public&nbsp;BookKey(String&nbsp;oid)&nbsp;<br>{&nbsp;<br>isbn&nbsp;=&nbsp;oid;&nbsp;<br>}&nbsp;<br>public&nbsp;String&nbsp;toString()&nbsp;<br>{&nbsp;<br>return&nbsp;isbn;&nbsp;<br>}&nbsp;<br>public&nbsp;Boolean&nbsp;equals(Object&nbsp;obj)&nbsp;<br>{&nbsp;<br>return&nbsp;isbn.equals&nbsp;<br>((BookKey)obj).isbn);&nbsp;<br>}&nbsp;<br>public&nbsp;int&nbsp;hashCode()&nbsp;<br>{&nbsp;<br>return&nbsp;isbn.hashCode();&nbsp;<br>}&nbsp;<br>}&nbsp;<br><br><br><br><br>符合&nbsp;JDO&nbsp;的&#8220;objectid-class&#8221;类，如&#8220;BookKey&#8221;，须具备以下条件：&nbsp;<br><br>类声明为&nbsp;public，并实现&nbsp;java.io.Serializable；&nbsp;<br><br>带有一个公有且不带参数的构造方法；&nbsp;<br><br>当字段作为主键时，须有公有的，且名称和类型与持久类的字段一致，如：public&nbsp;String&nbsp;isbn；&nbsp;<br><br>equals&nbsp;和&nbsp;hashCode&nbsp;须使用全部（特指多字段的联合主键）的主键字段值；&nbsp;<br><br>类必须有一个构造方法，与&nbsp;toString&nbsp;方法的处理过程是逆向过程；即将&nbsp;toString&nbsp;的输出值，作为该构造方法的输入值，又可以重新生成该实例（如构造方法&#8220;public&nbsp;BookKey(String&nbsp;oid)&#8221;）。&nbsp;<br><br>综上所述，如果Book由两个字段作为主键，如isbn和name，则可能的代码是pm.newObjectIdInstance(Book.class,isbn+&#8220;#&#8221;+name)，且BookKey的构造方法作相应更改，并有两个公有字段&#8220;isbn&#8221;和&#8220;name&#8221;。&nbsp;<br><br>对象删除&nbsp;<br><br>对象删除采用方法deletePersistence。示例如下：&nbsp;<br><br><br><br><br><br><br><br><br>pm.currentTransaction().begin();&nbsp;<br>Object&nbsp;obj&nbsp;=&nbsp;<br>pm.newObjectIdInstance&nbsp;<br>(Book.class,isbn);&nbsp;<br>Book&nbsp;book&nbsp;=&nbsp;<br>(Book)pm.getObjectById(obj,true);&nbsp;<br>pm.deletePersistence(book);&nbsp;<br>pm.currentTransaction().commit();&nbsp;<br><br><br><br><br>获得PersistenceManager实例&nbsp;<br><br>上述的所有操作与需要PersistenceManager实例，它可以在两种环境方法下获得：非受管环境和受管环境。&nbsp;<br><br>非受管环境&nbsp;<br><br>非受管环境是多指两层开发模式，应用程序直接获得资源对象，进行业务操作。一般事务管理、安全管理或资源管理都需要应用程序自行维护。&nbsp;<br><br><br>Properties&nbsp;properties&nbsp;=&nbsp;<br>new&nbsp;Properties();&nbsp;<br>properties.put(&#8220;javax.jdo.&nbsp;<br>PersistenceManagerFactoryClass&#8221;,&nbsp;<br>&#8220;com.xxx.jdo.xxxPMFClass&#8221;);&nbsp;<br>properties.put(&#8220;javax.jdo.&nbsp;<br>option.ConnectionURL&#8221;,&nbsp;&#8220;xxx&#8221;);&nbsp;<br>properties.put(&#8220;javax.jdo.&nbsp;<br>option.ConnectionUserName&#8221;,&nbsp;&#8220;xxx&#8221;);&nbsp;<br>properties.put(&#8220;javax.jdo.&nbsp;<br>option.ConnectionPassword&#8221;,&nbsp;&#8220;xxx&#8221;);&nbsp;<br>PersistenceManagerFactory&nbsp;pmf&nbsp;=&nbsp;<br>JDOHelper.getPersistence&nbsp;<br>ManagerFactory(properties);&nbsp;<br>PersistenceManager&nbsp;pm&nbsp;=&nbsp;<br>pmf.getPersistenceManager();&nbsp;<br><br><br><br><br>与JDBC获取类似。&nbsp;<br><br>受管环境&nbsp;<br><br>受管环境一般是多层开发模式，尤其是处于J2EE应用环境中，程序通过容器获得资源对象，进行业务操作，由于在容器环境下，事务、安全及资源管理都由容器进行统一集中管理，从而简化了代码结构。&nbsp;<br><br>以下是EJB（EntityBean、SessionBean、MessageDrivenBean）中的setXXXContext中的代码示例。&nbsp;<br><br><br>private&nbsp;PersistenceManagerFactory&nbsp;pmf;&nbsp;<br>public&nbsp;void&nbsp;setXXXContext&nbsp;<br>(XXXContext&nbsp;context)&nbsp;<br>{&nbsp;<br>try{&nbsp;<br>InitialContext&nbsp;ctx&nbsp;=&nbsp;<br>new&nbsp;InitialContext();&nbsp;<br>Object&nbsp;obj&nbsp;=&nbsp;ctx.lookup&nbsp;<br>(&#8220;java:compenvjdofactory&#8221;);&nbsp;<br>pmf&nbsp;=&nbsp;(PersistenceManagerFactory)&nbsp;<br>PortableRemoteObject.narrow&nbsp;<br>(o,PersistenceManagerFactory.class);&nbsp;<br>}catch(NamingException&nbsp;e)&nbsp;<br>{&nbsp;<br>throw&nbsp;new&nbsp;Exception(e);&nbsp;<br>}&nbsp;<br>}&nbsp;<br><br><br><br><br>PMF是如何绑定到J2EE环境下的JNDI上，有兴趣可参考JCA相关的技术文档。&nbsp;<br><br>事务管理&nbsp;<br><br>事务管理及使用，主要有以下三种情形。&nbsp;<br><br>使用JDO事务的Bean管理情形&nbsp;<br><br>一般在非J2EE环境下，使用该事务管理模式。&nbsp;<br><br><br>PersistenceManager&nbsp;pm&nbsp;=&nbsp;<br>pmf.getPersistenceManager();&nbsp;<br>pm.currentTransaction().begin();&nbsp;<br>//do&nbsp;some&nbsp;business&nbsp;with&nbsp;jdo&nbsp;<br>pm.currentTransaction().commit();&nbsp;<br>pm.close();&nbsp;<br><br><br><br><br>使用JTA事务的Bean管理情形&nbsp;<br><br>一般在J2EE环境下，采用Bean管理的事务情形下，使用以下方式。&nbsp;<br><br>该方式可用在EJB的事务环境下。&nbsp;<br><br><br>xxxContext.getUser&nbsp;<br>Transaction().begin();&nbsp;<br>PersistenceManager&nbsp;pm&nbsp;=&nbsp;<br>pmf.getPersistenceManager();&nbsp;<br>//do&nbsp;some&nbsp;business&nbsp;with&nbsp;jdo&nbsp;<br>xxxContext.getUserTransaction().commit();&nbsp;<br>pm.close();&nbsp;<br><br><br>使用JTA事务的容器管理情形&nbsp;<br><br>一般在J2EE环境下，采用容器管理的事务情形下，使用如下方式。&nbsp;<br><br>如下是某个会话Bean的业务方法。&nbsp;<br><br><br><br><br><br><br><br><br><br><br>public&nbsp;void&nbsp;doBusiness(){&nbsp;<br>PersistenceManager&nbsp;pm&nbsp;;&nbsp;<br>try{&nbsp;<br>pm&nbsp;=&nbsp;pmf.getPersistenceManager();&nbsp;<br>//do&nbsp;some&nbsp;business&nbsp;with&nbsp;jdo&nbsp;<br>}catch(Exception&nbsp;e){&nbsp;<br>xxxContext.setRollbackOnly();&nbsp;<br>System.out.println(e);&nbsp;<br>}finally{&nbsp;<br>try{&nbsp;<br>if&nbsp;(pm&nbsp;!=&nbsp;null&nbsp;&amp;&amp;&nbsp;!pm.isClosed())&nbsp;<br>pm.close();&nbsp;<br>}catch(Exception&nbsp;ex){&nbsp;<br>System.out.println(ex);&nbsp;<br>}&nbsp;<br>}&nbsp;<br>}&nbsp;<br><br><br><br><br>综上，可以得出结论，JDO的操作完全与JDBC的操作相差无几。&nbsp;<br><br>JDO高级应用&nbsp;<br><br>复杂对象的持久化&nbsp;<br><br>在实际的应用中，一个可持久化类要远比Book类复杂很多。它可能会引用其它的Java类型、类、集合或数组，及可能复杂的继承关系。当这些对象的状态发生变化时，JDO是如何感知及跟踪状态变化？&nbsp;<br><br>JDO提供了相应的API及规范来实现该功能。&nbsp;<br><br>基本类型及引用&nbsp;<br><br>可持久化类的字段能被JDO实现进行持久化的原则。原始类型、java.util.Date等被支持（其它较为复杂或可选特性，详见JDO规范）；如果引用是一个可持久类，则JDO进行持久化处理；通过元数据(如jdo文件)声明的字段，一般是非可持久化类的引用，JDO进行持久化；&nbsp;<br><br>前面两种情形，当状态发生变化时，JDO会自动感知，但如果引用是非可持久化类，则需要代码进行显式通知，否则JDO不会将变化进行存储。如下例：&nbsp;<br><br><br>public&nbsp;class&nbsp;Book&nbsp;<br>{&nbsp;<br>&#8230;&#8230;&nbsp;<br>private&nbsp;Object&nbsp;picture;&nbsp;<br>public&nbsp;void&nbsp;setPicture(Object&nbsp;pic)&nbsp;<br>{&nbsp;<br>picture&nbsp;=&nbsp;pic;&nbsp;<br>}&nbsp;<br>public&nbsp;Object&nbsp;getPicture()&nbsp;<br>{&nbsp;<br>Return&nbsp;picture;&nbsp;<br>}&nbsp;<br>}&nbsp;<br><br><br><br><br>该类字段picture需要持久化，但java.lang.Object不是一个可持久类，故声明如下：&nbsp;<br><br><br><br><br><br><br><br>persistence-modifier=&#8220;persistent&#8221;/&gt;&nbsp;<br><br><br><br><br><br><br><br>如果其它模块通过getPicture获得对象，并在JDO不可感知的外部，修改对象，则变化不会存储，较好的办法是修改setPicture方法，如下：&nbsp;<br><br><br>public&nbsp;void&nbsp;setPicture(Object&nbsp;pic)&nbsp;<br>{&nbsp;<br>JDOHelper.makeDirty(this,&nbsp;&#8220;picture&#8221;);&nbsp;<br>picture&nbsp;=&nbsp;pic;&nbsp;<br>}&nbsp;<br><br><br><br><br>并通过setPicture方法来更新数据。JDO的&#8220;makeDirty&#8221;方法，主要负责通知JDO实现，可持久化类Book某个实例（this）的&#8220;picture&#8221;字段发生了变化。&nbsp;<br><br>集合&nbsp;<br><br>可持久类的字段引用为集合时，按照JDO规范，强制支持java.util.HashSet，对HashMap、HashTable、TreeMap、TreeSet、LinkedList、ArrayList及Vector的支持对JDO实现而言是可选的，通过PersistenceManagerFactory的supportedOptions方法获得实现特性。&nbsp;<br><br>数组&nbsp;<br><br>如果可持久类的引用是数组类型，当数组单元发生变化时，需要调用&#8220;makeDirty&#8221;来通知JDO实现，该实例的数组引用内容发生了变化。与引用是非可持久类实例不同，不需要进行JDO的元数据声明。&nbsp;<br><br>继承&nbsp;<br><br>如果使用可持久性，一般继承的子类与父类都为可持久类，以减少系统复杂性，这时需要在子类的元数据中指出其可持久超类，如下：&nbsp;<br><br><br>&lt;&nbsp;<br>class&nbsp;name=&#8220;TechBook&#8221;&nbsp;<br>persistence-capable-superclass=&#8220;Book&#8221;/&gt;&nbsp;<br><br><br><br><br>可为非持久类扩展持久类，或可为持久类扩展非可持久类；这两种情形JDO实现都将忽略非&nbsp;<br><br>可持久类的字段部分，而不保存到数据库。&nbsp;<br><br>JDO的一些不足之处&nbsp;<br><br>JDO对数据的持久化技术相比于成熟的SQL，还有不足之处，这些不足在某些情况下将可能会影响数据处理部分的设计实现。以下列举了常用数据访问的必要功能&nbsp;<br><br>查询增强&nbsp;<br><br>如字符串不支持通配符、大小写比较；&nbsp;<br><br>不支持聚合操作，无法实现MIN、MAX、SUM和AVG；&nbsp;<br><br>不支持投影操作，JDO查询返回为对象，而不像SQL那样返回字段；&nbsp;<br><br>不支持联合、交叉（UNION/INTERSECT）；&nbsp;<br><br>不支持JOIN、IN和EXISTS；&nbsp;<br><br>企业应用探究&nbsp;<br><br>由于JDO采用面向对象的持久化处理技术，从而为解决企业业务系统的持久化问题提供了一个新技术解决方案。但是先进的未必就最适用。在某些应用场景下，需要结合各种因素，采取灵活的策略。&nbsp;<br><br>面向对象与面向记录&nbsp;<br><br>现在大多业务系统都采用面向对象分析设计，这就需要每个应用系统都自行实现将对象映射成记录，并存储到数据库中，而有JDO这样的面向对象的持久化技术，在某种程度上解放了这种转化设计的不规范性，进而获得相对更优的系统结构。&nbsp;<br><br>另一方面，一个业务系统的数据持久化，一般都有这样的过程：对象层－＞记录层－＞物理层，JDO无疑使分析设计人员从记录层的苦海中解脱出来，从而更加专注于对象层，这对开发人员无疑是一个令人欢欣鼓舞的技术。&nbsp;<br><br>JDO并不能完全代替JDBC。&nbsp;<br><br>根据经典的&#8220;8-2原理&#8221;，如果用JDO来解决80%的问题，余下的20%由JDBC来实现，这种相互补充，各取所长的策略，是一个很有效的办法。&nbsp;<br><br>这样一方面可以获得较好的结构及提升开发质量，另一方面解决了JDO的某些技术不足，并可根据以后的技术变化，再做适当转化。&nbsp;<br><br>性能问题&nbsp;<br><br>JDO与JDBC究竟谁的性能更优，目前还没有一个权威、且令人满意的答案。但对于一些JDO实现而言，通过采用缓存机制，使得性能有了较大提高。&nbsp;<br><br>跨数据库&nbsp;<br><br>使用JDO的系统能更好地进行数据库移植，甚至可以在对象数据库上运行；当然JDBC处理层如果完全遵循SQL-92标准，也同样具有很好的跨数据库能力。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font face="Times New Roman" size=3>(责任编辑：包春林) </font></p>
            </span></td>
        </tr>
    </tbody>
</table>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39931.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-19 14:39 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/19/39931.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>用ASP连接各种数据库的方法 </title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39887.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Mon, 18 Feb 2008 08:19:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39887.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39887.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39887.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39887.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39887.html</trackback:ping><description><![CDATA[一、ASP的对象存取数据库方法 <br>在ASP中，用来存取数据库的对象统称ADO（Active Data Objects），主要含有三种对象：Connection、Recordset 、Command <br>Connection：负责打开或连接数据 <br>Recordset：负责存取数据表 <br>Command：负责对数据库执行行动查询命令 <br><br>二、连接各数据库的驱动程序 <br>连接各数据库可以使用驱动程序，也可以使用数据源，不过我建议大家使用驱动程序，因为使用驱动程序非常方便、简单，而使用数据源比较麻烦。 <br><br>ODBC链接 <br><br>适合数据库类型 链接方式 <br>access "Driver={microsoft access driver(*.mdb)};dbq=*.mdb;uid=admin;pwd=pass;" <br>dBase "Driver={microsoft dbase driver(*.dbf)};driverid=277;dbq=------------;" <br>Oracle "Driver={microsoft odbc for oracle};server=oraclesever.world;uid=admin;pwd=pass;" <br>MSSQL server "Driver={sql server};server=servername;database=dbname;uid=sa;pwd=pass;" <br>MS text "Driver={microsoft text driver(*.txt; *.csv)};dbq=-----;extensions=asc,csv,tab,txt;Persist SecurityInfo=false;" <br>Visual Foxpro "Driver={microsoft Visual Foxpro driver};sourcetype=DBC;sourceDB=*.dbc;Exclusive=No;" <br>MySQL "Driver={mysql};database=yourdatabase;uid=username;pwd=yourpassword;option=16386;" <br><br><br>OLEDB链接 <br><br>适合的数据库类型 链接方式 <br>access "Provider=microsoft.jet.oledb.4.0;data source=your_database_path;user id=admin;password=pass;" <br>Oracle "Provider=OraOLEDB.Oracle;data source=dbname;user id=admin;password=pass;" <br>MS SQL Server "Provider=SQLOLEDB;data source=machinename;initial catalog=dbname;userid=sa;password=pass;" <br>MS text "Provider=microsof.jet.oledb.4.0;data source=your_path;Extended Properties&#8242;text;FMT=Delimited&#8242;" <br><br><br>而我们在一般情况下使用Access的数据库比较多，在这里我建议大家连接Access数据库使用下面的方法： <br><br>dim conn <br>set conn = server.createobject("adodb.connection") <br>conn.open = "provider=microsoft.jet.oledb.4.0;" &amp; "data source = " &amp; server.mappath("../db/bbs.mdb") <br><br>其中../db/bbs.mdb是你的数据库存放的相对路径！如果你的数据库和ASP文件在同一目录下，你只要这样写就可以了： <br><br>dim conn <br>set conn = server.createobject("adodb.connection") <br>conn.open = "provider=microsoft.jet.oledb.4.0;" &amp; "data source = " &amp; server.mappath("bbs.mdb") <br><br>有许多初学者在遇到数据库连接时总是会出问题，然而使用上面的驱动程序只要你的数据库路径选对了就不会出问题了。</ca>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39887.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-18 16:19 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39887.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>PHP连接数据库的方法  [转] </title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39888.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Mon, 18 Feb 2008 08:19:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39888.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39888.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39888.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39888.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39888.html</trackback:ping><description><![CDATA[<font face=宋体>相信大家对PHP已经很熟悉了。PHP内置了几乎对世界上所有的数据库的支持，而不再需要重新扩充。所以有人说：不会用PHP调用数据库，等于没学PHP。下面是笔者根据本人的操作经验和大侠们的意见而得出的总结，希望能给初学者提供一些益处。&nbsp;&nbsp;<br><br>相信大家对PHP已经很熟悉了。PHP内置了几乎对世界上所有的数据库的支持，而不再需要重新扩充。所以有人说：不会用PHP调用数据库，等于没学PHP。下面是笔者根据本人的操作经验和大侠们的意见而得出的总结，希望能给初学者提供一些益处。<br><br>PHP调用三种数据库的方法<br><br>本文比较详细的介绍PHP调用MySQL、ODBC以及ORACLE数据库。<br><br>MySQL是一个小巧灵珑的数据库服务器软件，对于中、小型应用系统是非常理想的。除了支持标准的ANSI&nbsp;SQL语句外，最重要的是，它还支持多种平台，而在Unix/Linux系统上，MySQL支持多线程运行方式，从而能获得相当好的性能。它和PHP、Apache一样，是属于开放源代码软件。其官方网站是：<img src="http://www.cxfnet.com/skin/skin_1/small/url.gif" align=absMiddle border=0></font><a href="http://www.mysql.com/" target=_blank><u><font face=宋体 color=#0000ff>http://www.mysql.com</font></u></a><font face=宋体>，上面提供Windows,Linux,Unix版本的源代码的下载。<br><br>注意，MySQL访问函数都需要有相应的权限才能运行。常用的相关函数介绍如下：<br><br>(1)integer&nbsp;mysql_connect(主机,用户名,口令);&nbsp;<br><br>此函数开始一个对指定主机上的MySQL数据库的连接。若该数据库位于一个不同地端口，则在主机名后加上冒号和端口号。所有参数均为可选的，缺省情况下分别对应为本地主机、用户正在执行的脚本名和空。主机可以是IP地址或域名。<br><br>在脚本执行结束时，连接被自动关闭，也可以用mysql_close提前关闭。<br><br>(2)boolean&nbsp;mysql_create_db(数据库名);&nbsp;<br><br>创建一个数据库。注意必须用一个带有创建数据库许可权的帐号打开连接。<br><br>(3)boolean&nbsp;mysql_select_db(数据库名,连接号);&nbsp;<br><br>选择缺省数据库。&nbsp;<br><br>(4)integer&nbsp;mysql_query(SQL语句,连接号);&nbsp;<br><br>对指定数据库进行查询。如果SQL语句是select,则返回一个结果号，否则返回的值可以不理会。如果失败，返回false.。<br><br>(5)array&nbsp;mysql_fetch_array(结果号);&nbsp;<br><br>取出下一行,返回一个数组.可以用数字下标访问(第一个字段是下标&nbsp;0)，也可以用字符串下标访问(即使用各字段名)。如已取了最后一行，返回&nbsp;false.。<br><br>(6)mysql_fetch_row(结果号);&nbsp;<br><br>返回一个矩阵代表结果集中一行的所有域。每次调用都会产生下一行，直到没有行剩下时返回false。每个域值都由一个从零开始的偏移量索引。这是从查询中获取结果的最快方法。<br><br>(7)integer&nbsp;mysql_num_rows(结果号);<br><br>返回结果集中行的数目<br><br>(8)integer&nbsp;mysql_num_fields(结果号);&nbsp;<br><br>返回结果集中域的数目。<br><br>(9)integer&nbsp;mysql_list_dbs();<br><br>向服务器查询数据库列表。它返回一个结果指针，该指针可用于mysql_fetch_row函数及类似函数。<br><br>(10)mysql_list_tables(数据库名);&nbsp;<br><br>获取一个指向指定数据库的表单列表的结果指针。该结果指针可用于任何从结果集中获取行的函数。<br><br>(11)mysql_close(连接号);&nbsp;<br><br>关闭对数据库的连接。连接必须是由mysql_connect打开的。该函数的使用不是严格必需的，因为在脚本结束时，所有非永久链路都会被自动关闭。<br><br>(12)mysql_pconnect(主机,用户名,口令);&nbsp;<br><br>与mysql_connect完全相似,但建立一个<em>"</em>永久连接<em>"</em>,该连接一经建立永不关闭,即使使用mysql_close函数或程序执行完毕也不关闭.下一次试图建立永久连接时,系统如发现已存在一个永久连接,则直接返回该连接号而不重新创建。<br><br>下面是一个调用MYSQL数据库并分页显示的例子。<br><br>&lt;?<br><br>$pagesize&nbsp;=&nbsp;5;&nbsp;//每页显示5条记录<br><br>$host=<em>"</em>localhost<em>"</em>;<br><br>$user=<em>"</em>user<em>"</em>;<br><br>$password=<em>"</em>psw<em>"</em>;&nbsp;<br><br>$dbname=<em>"</em>book<em>"</em>;&nbsp;//所查询的库表名；<br><br>//连接MySQL数据库<br><br>mysql_connect(<em>"</em>$host<em>"</em>,<em>"</em>$user<em>"</em>,<em>"</em>$password<em>"</em>)&nbsp;or&nbsp;die(<em>"</em>无法连接MySQL数据库服务器！<em>"</em>);<br><br>$db&nbsp;=&nbsp;mysql_select_db(<em>"</em>$dbname<em>"</em>)&nbsp;or&nbsp;die(<em>"</em>无法连接数据库！<em>"</em>);<br><br>$sql&nbsp;=&nbsp;<em>"</em>select&nbsp;count(*)&nbsp;as&nbsp;total&nbsp;from&nbsp;pagetest<em>"</em>;//生成查询记录数的SQL语句<br><br>$rst&nbsp;=&nbsp;mysql_query($sql)&nbsp;or&nbsp;die(<em>"</em>无法执行SQL语句：$sql&nbsp;！<em>"</em>);&nbsp;//查询记录数<br><br>$row&nbsp;=&nbsp;mysql_fetch_array($rst)&nbsp;or&nbsp;die(<em>"</em>没有更多的记录！<em>"</em>);&nbsp;/取出一条记录<br><br>$rowcount&nbsp;=&nbsp;$row[<em>"</em>total<em>"</em>];//取出记录数<br><br>mysql_free_result($rst)&nbsp;or&nbsp;die(<em>"</em>无法释放result资源！<em>"</em>);&nbsp;//释放result资源<br><br>$pagecount&nbsp;=&nbsp;bcdiv($rowcount+$pagesize-1,$pagesize,0);//算出总共有几页<br><br>if(!isset($pageno))&nbsp;{<br><br>$pageno&nbsp;=&nbsp;1;&nbsp;//在没有设置pageno时，缺省为显示第1页<br><br>}<br><br>if($pageno&lt;1)&nbsp;{<br><br>$pageno&nbsp;=&nbsp;1;&nbsp;//若pageno比1小，则把它设置为1<br><br>}<br><br>if($pageno&gt;$pagecount)&nbsp;{<br><br>$pageno&nbsp;=&nbsp;$pagecount;&nbsp;//若pageno比总共的页数大，则把它设置为最后一页<br><br>}<br><br>if($pageno&gt;0)&nbsp;{<br><br>$href&nbsp;=&nbsp;eregi_replace(<em>"</em>%2f<em>"</em>,<em>"</em>/<em>"</em>,urlencode($PHP_SELF));//把$PHP_SELF转换为可以在URL上使用的字符串，这样的话就可以处理中文目录或中文文件名<br><br>if($pageno&gt;1){//显示上一页的裢接<br><br>echo&nbsp;<em>"</em>&lt;a&nbsp;href=<em>"</em><em>"</em>&nbsp;.&nbsp;$href&nbsp;.&nbsp;<em>"</em>?pageno=<em>"</em>&nbsp;.&nbsp;($pageno-1)&nbsp;.&nbsp;<em>"</em><em>"</em>&gt;上一页&lt;/a&gt;&nbsp;<em>"</em>;<br><br>}<br><br>else{<br><br>echo&nbsp;<em>"</em>上一页<em>"</em>;<br><br>}<br><br>for($i=1;$i&lt;$pageno;$i++){<br><br>echo&nbsp;<em>"</em>&lt;a&nbsp;href=<em>"</em><em>"</em>&nbsp;.&nbsp;$href&nbsp;.&nbsp;<em>"</em>?pageno=<em>"</em>&nbsp;.&nbsp;$i&nbsp;.&nbsp;<em>"</em><em>"</em>&gt;<em>"</em>&nbsp;.&nbsp;$i&nbsp;.&nbsp;<em>"</em>&lt;/a&gt;&nbsp;<em>"</em>;&nbsp;<br><br>}<br><br>echo&nbsp;$pageno&nbsp;.&nbsp;<em>"</em>&nbsp;<em>"</em>;<br><br>for($i++;$i&lt;=$pagecount;$i++){<br><br>echo&nbsp;<em>"</em>&lt;a&nbsp;href=<em>"</em><em>"</em>&nbsp;.&nbsp;$href&nbsp;.&nbsp;<em>"</em>?pageno=<em>"</em>&nbsp;.&nbsp;$i&nbsp;.&nbsp;<em>"</em><em>"</em>&gt;<em>"</em>&nbsp;.&nbsp;$i&nbsp;.&nbsp;<em>"</em>&lt;/a&gt;&nbsp;<em>"</em>;<br><br>}<br><br>if($pageno&lt;$pagecount){//显示下一页的裢接<br><br>echo&nbsp;<em>"</em>&lt;a&nbsp;href=<em>"</em><em>"</em>&nbsp;.&nbsp;$href&nbsp;.&nbsp;<em>"</em>?pageno=<em>"</em>&nbsp;.&nbsp;($pageno+1)&nbsp;.&nbsp;<em>"</em><em>"</em>&gt;下一页&lt;/a&gt;&nbsp;<em>"</em>;<br><br>}<br><br>else{<br><br>echo&nbsp;<em>"</em>下一页&nbsp;<em>"</em>;<br><br>}<br><br>$offset&nbsp;=&nbsp;($pageno-1)&nbsp;*&nbsp;$pagesize;//算出本页第一条记录在整个表中的位置(第一条记录为0)<br><br>$sql&nbsp;=&nbsp;<em>"</em>select&nbsp;*&nbsp;from&nbsp;pagetest&nbsp;LIMIT&nbsp;$offset,$pagesize<em>"</em>;//生成查询本页数据的SQL语句<br><br>$rst&nbsp;=&nbsp;mysql_query($sql);//查询本页数据<br><br>$num_fields&nbsp;=&nbsp;mysql_num_fields($rst);//取得字段总数<br><br>$i&nbsp;=&nbsp;0;<br><br>while($i&lt;$num_fields){//取得所有字段的名字<br><br>$fields[$i]&nbsp;=&nbsp;mysql_field_name($rst,$i);//取得第i+1个字段的名字<br><br>$i++;<br><br>}<br><br>echo&nbsp;<em>"</em>&lt;table&nbsp;border=<em>"</em>1<em>"</em>&nbsp;cellspacing=<em>"</em>0<em>"</em>&nbsp;cellpadding=<em>"</em>0<em>"</em>&gt;<em>"</em>;//开始输出表格<br><br>echo&nbsp;<em>"</em>&lt;tr&gt;<em>"</em>;<br><br>reset($fields);<br><br>while(list(,$field_name)=each($fields)){//显示字段名称<br><br>echo&nbsp;<em>"</em>&lt;th&gt;$field_name&lt;/th&gt;<em>"</em>;<br><br>}<br><br>echo&nbsp;<em>"</em>&lt;/tr&gt;<em>"</em>;<br><br>while($row=mysql_fetch_array($rst)){//显示本页数据<br><br>echo&nbsp;<em>"</em>&lt;tr&gt;<em>"</em>;<br><br>reset($fields);<br><br>while(list(,$field_name)=each($fields)){//显示每个字段的值<br><br>$field_<em>value</em>&nbsp;=&nbsp;$row[$field_name];<br><br>if($field_<em>value</em>==<em>"</em><em>"</em>){<br><br>echo&nbsp;<em>"</em>&lt;td&gt;&nbsp;&lt;/td&gt;<em>"</em>;<br><br>}<br><br>else{<br><br>echo&nbsp;<em>"</em>&lt;td&gt;$field_<em>value</em>&lt;/td&gt;<em>"</em>;<br><br>}<br><br>}<br><br>echo&nbsp;<em>"</em>&lt;/tr&gt;<em>"</em>;<br><br>}<br><br>echo&nbsp;<em>"</em>&lt;/table&gt;<em>"</em>;//表格输出结束<br><br>mysql_free_result($rst)&nbsp;or&nbsp;die(<em>"</em>无法释放result资源！<em>"</em>);//释放result资源<br><br>}<br><br>else{<br><br>echo&nbsp;<em>"</em>目前该表中没有任何数据！<em>"</em>;<br><br>}<br><br>mysql_close($server)&nbsp;or&nbsp;die(<em>"</em>无法与服务器断开连接！<em>"</em>);//断开连接并释放资源<br><br>?&gt;<br><br>开放数据库连接（ODBC）已成为一种与数据库进行通信的工业标准。PHP也提供了标准的接口，使得PHP能调用Access，SQL&nbsp;SERVER等数据库。其相关函数是：<br><br>（1）integer&nbsp;odbc_connect(string&nbsp;dsn,&nbsp;string&nbsp;user,&nbsp;string&nbsp;password)<br><br>连接到一个ODBC数据库源名字上。<br><br>（2）integer&nbsp;odbc_exec(integer&nbsp;connection,&nbsp;string&nbsp;query)或&nbsp;odbc_do(integer&nbsp;connection,&nbsp;string&nbsp;query)<br><br>在一个连接上执行查询。<br><br>（3）boolean&nbsp;odbc_fetch_row(integer&nbsp;result,&nbsp;integer&nbsp;row)<br><br>从一个结果集中获取一行数据。Row参数是可选的，若为空缺，则返回下一个有效行。在结果集中不再剩余行时返回false。<br><br>（4）boolean&nbsp;odbc_close(integer&nbsp;connection)<br><br>关闭一个数据库的连接。若在该连接上有打开的事务，则返回一个错误，而且连接不会被关闭。<br><br>最后，还是看个分页的例子：<br><br>&lt;?<br><br>//设定每页显示条数<br><br>$show_num&nbsp;=&nbsp;10;<br><br>$spages&nbsp;=&nbsp;$pages;//避免$pages后期被改变<br><br>//定义连接<br><br>$dsn&nbsp;=&nbsp;<em>"</em>localhost<em>"</em>;<br><br>$user&nbsp;=&nbsp;<em>"</em>sa<em>"</em>;<br><br>$password&nbsp;=&nbsp;<em>"</em><em>"</em>;<br><br>//计算总记录数<br><br>$rs_num&nbsp;=&nbsp;<em>"</em>select&nbsp;count(*)&nbsp;as&nbsp;id&nbsp;from&nbsp;bbs&nbsp;where&nbsp;zu=<em>'</em>0<em>'</em>&nbsp;and&nbsp;lei=<em>'</em><em>"</em>.$lei.<em>"</em><em>'</em><em>"</em>;<br><br>$conn_id&nbsp;=&nbsp;odbc_connect($dsn,$user,$password);<br><br>$rnum&nbsp;=&nbsp;odbc_exec($conn_id,$rs_num);<br><br>while(odbc_fetch_row($rnum)){<br><br>$total_rs&nbsp;=&nbsp;odbc_result($rnum,<em>"</em>id<em>"</em>);//将总记录数放入$total_rs变量<br><br>}<br><br>//计算与页有关的条数<br><br>$nnn&nbsp;=&nbsp;$total_rs&nbsp;/&nbsp;$show_num;//计算总页数<br><br>$hnnn&nbsp;=&nbsp;intval($nnn);//将总页数取整<br><br>$cnnnn&nbsp;=&nbsp;$nnn&nbsp;-&nbsp;$hnnn;<br><br>//计算所需总页数<br><br>switch&nbsp;($cnnn){<br><br>case&nbsp;<em>"</em>0<em>"</em>:<br><br>$hnnn++;<br><br>$nnn&nbsp;=&nbsp;$hnnn;//总页数<br><br>break;<br><br>default&nbsp;:<br><br>$nnn&nbsp;=&nbsp;$hnnn;//总页数<br><br>break;<br><br>};<br><br>if&nbsp;($nnn&nbsp;==&nbsp;0)$nnn++;<br><br>//计算页面改变所需的条件<br><br>$fore&nbsp;=&nbsp;$pages;<br><br>$next&nbsp;=&nbsp;$pages;<br><br>$fore&nbsp;-=&nbsp;1;<br><br>$next&nbsp;+=&nbsp;1;<br><br>if&nbsp;($fore&nbsp;&gt;&nbsp;0)&nbsp;{<br><br>echo&nbsp;<em>"</em>&lt;a&gt;首页&lt;/a&gt;<em>"</em>;<br><br>echo&nbsp;<em>"</em>&lt;a&gt;前页&lt;/a&gt;<em>"</em>;<br><br>};<br><br>if&nbsp;($pages&nbsp;&lt;&nbsp;$nnn)&nbsp;{<br><br>echo&nbsp;<em>"</em>&lt;a&gt;后页&lt;/a&gt;<em>"</em>;<br><br>echo&nbsp;<em>"</em>&lt;a&gt;尾页&lt;/a&gt;<em>"</em>;<br><br>};<br><br>echo&nbsp;<em>"</em>共<em>"</em>.$nnn.<em>"</em>页<em>"</em>;<br><br>$query_string&nbsp;=&nbsp;<em>"</em>SELECT&nbsp;*&nbsp;FROM&nbsp;table&nbsp;where&nbsp;condition&nbsp;order&nbsp;by&nbsp;you&nbsp;wanted&nbsp;order<em>"</em>;<br><br>$cur&nbsp;=&nbsp;odbc_exec($conn_id,$query_string);<br><br>//取到循环的顶部<br><br>$cnum&nbsp;=&nbsp;($pages-1)&nbsp;*&nbsp;$show_num;//计算当前的记录游标的位置<br><br>//空循环到显示记录游标处&nbsp;<br>if&nbsp;($cnum&nbsp;!=&nbsp;0){<br><br>for&nbsp;($i=0;$i&lt;=$cnum;odbc_fetch_row($cur)){$i++;};<br><br>};<br><br>$i=1;<br><br>//显示记录<br><br>while(odbc_fetch_row($cur)){<br><br>echo&nbsp;<br><br>if&nbsp;($i&nbsp;==&nbsp;$show_num){//在不满页数时跳出程序<br><br>break;&nbsp;<br><br>};<br><br>$i++;<br><br>};&nbsp;<br><br>//关闭连接<br><br>odbc_close($conn_id);<br><br>?&gt;<br><br>Oracle（甲骨文）是世界上最为流行的关系数据库。它是大公司推崇的工业化的强有力的引擎。我们先看看其相关的函数：<br><br>（1）integer&nbsp;ora_logon(string&nbsp;user&nbsp;,&nbsp;string&nbsp;password)<br><br>开始对一个Oracle数据库服务器的连接。<br><br>（2）integer&nbsp;ora_open(integer&nbsp;connection)<br><br>打开给出的连接的游标。<br><br>（3）integer&nbsp;ora_do(integer&nbsp;connection,&nbsp;string&nbsp;query)<br><br>在给出的连接上执行查询。PHP生成一个指示器，解析查询，并执行之。<br><br>（4）integer&nbsp;ora_parse(integer&nbsp;cursor,&nbsp;string&nbsp;query)<br><br>解析一个查询并准备好执行。<br><br>（5）boolean&nbsp;ora_exec(integer&nbsp;cursor)<br><br>执行一个先前由ora_parse函数解析过的查询。<br><br>（6）boolean&nbsp;ora_fetch(integer&nbsp;cursor)<br><br>此函数会使得一个执行过的查询中的行被取到指示器中。这使得您可以调用ora_getcolumn函数。<br><br>（7）string&nbsp;ora_getcolumn(integer&nbsp;cursor,&nbsp;integer&nbsp;column)<br><br>返回当前的值。列由零开始的数字索引。<br><br>（8）boolean&nbsp;ora_logoff(integer&nbsp;connection)<br><br>断开对数据库服务器的链接。<br><br>以下是向ORACLE数据库插入数据的示例程序：&nbsp;<br><br>&lt;html&gt;<br><br>&lt;head&gt;&lt;title&gt;向ORACLE数据库中插入数据&lt;/title&gt;&lt;/head&gt;<br><br>&lt;body&gt;<br><br>&lt;form&nbsp;action=<em>"</em>&lt;?echo&nbsp;$PHP_SELF;?&gt;<em>"</em>&nbsp;method=<em>"</em>post<em>"</em>&gt;<br><br>&lt;table&nbsp;border=<em>"</em>1<em>"</em>&nbsp;cellspacing=<em>"</em>0<em>"</em>&nbsp;cellpadding=<em>"</em>0<em>"</em>&gt;<br><br>&lt;tr&gt;<br><br>&lt;th&gt;ID&lt;/th&gt;<br><br>&lt;th&gt;name&lt;/th&gt;<br><br>&lt;th&gt;De<em>script</em>ion&lt;/th&gt;<br><br>&lt;/tr&gt;<br><br>&lt;tr&gt;<br><br>&lt;td&gt;&lt;input&nbsp;type=<em>"</em>text<em>"</em>&nbsp;name=<em>"</em>name<em>"</em>&nbsp;maxlength=<em>"</em>50<em>"</em>&nbsp;size=<em>"</em>10<em>"</em>&gt;&lt;/td&gt;<br><br>&lt;td&gt;&lt;input&nbsp;type=<em>"</em>text<em>"</em>&nbsp;name=<em>"</em>email<em>"</em>&nbsp;maxlength=<em>"</em>255<em>"</em>&nbsp;size=<em>"</em>30<em>"</em>&gt;&lt;/td&gt;<br><br>&lt;td&gt;&lt;input&nbsp;type=<em>"</em>text<em>"</em>&nbsp;name=<em>"</em>De<em>script</em>ion<em>"</em>&nbsp;maxlength=<em>"</em>255<em>"</em>&nbsp;size=<em>"</em>50<em>"</em>&gt;&lt;/td&gt;<br><br>&lt;/tr&gt;<br><br>&lt;tr&nbsp;align=<em>"</em>center<em>"</em>&gt;<br><br>&lt;td&nbsp;colspan=<em>"</em>3<em>"</em>&gt;&lt;input&nbsp;type=<em>"</em>submit<em>"</em>&nbsp;<em>value</em>=<em>"</em>提交<em>"</em>&gt;&nbsp;&nbsp;&lt;input&nbsp;type=<em>"</em>reset<em>"</em>&nbsp;<em>value</em>=<em>"</em>重写<em>"</em>&gt;&lt;/td&gt;<br><br>&lt;/tr&gt;<br><br>&lt;/table&gt;<br><br>&lt;/form&gt;<br><br>&lt;?<br><br>//先设置两个环境变量ORACLE_HOME，ORACLE_SID<br><br>putenv(<em>"</em>ORACLE_HOME=/oracle/app/oracle/product/8.0.4<em>"</em>);<br><br>putenv(<em>"</em>ORACLE_SID=ora8<em>"</em>);<br><br>//设置网页显示中文<br><br>putenv(<em>"</em>NLS_LANG=Simplified_Chinese.zhs16cgb231280<em>"</em>);<br><br>if($connection=ora_logon(<em>"</em>scott<em>"</em>,<em>"</em>tiger<em>"</em>))&nbsp;{<br><br>//库表test有ID,name,De<em>script</em>ion三项<br><br>$sql&nbsp;=&nbsp;<em>'</em>insert&nbsp;into&nbsp;test(ID,name,De<em>script</em>ion)&nbsp;<em>value</em>s&nbsp;<em>'</em>;&nbsp;<br><br>$sql&nbsp;.=&nbsp;<em>'</em>(<em>'</em><em>'</em>&nbsp;.&nbsp;$ID&nbsp;.&nbsp;<em>'</em><em>'</em>,<em>'</em><em>'</em>&nbsp;.&nbsp;$name&nbsp;.&nbsp;<em>'</em><em>'</em>,<em>'</em><em>'</em>.&nbsp;$De<em>script</em>ion&nbsp;.&nbsp;<em>'</em><em>'</em>)<em>'</em>;<br><br>if($cursor=ora_do($connect,$sql))&nbsp;{<br><br>print(<em>"</em>insert&nbsp;finished!<em>"</em>);<br><br>}<br><br>$query&nbsp;=&nbsp;<em>'</em>select&nbsp;*&nbsp;from&nbsp;test<em>'</em>;<br><br>if($cursor=ora_do($connect,$query))&nbsp;{<br><br>ora_fetch($cursor);<br><br>$content0=ora_getcolumn($cursor,0);<br><br>$content1=ora_getcolumn($cursor,1);<br><br>$content2=ora_getcolumn($cursor,2);<br><br>print(<em>"</em>$content0<em>"</em>);<br><br>print(<em>"</em>$content1<em>"</em>);<br><br>print(<em>"</em>$content2<em>"</em>);<br><br>ora_close($cursor);<br><br>}<br><br>ora_logoff($connection);<br><br>}<br><br>?&gt;<br><br>&lt;/body&gt;<br><br>&lt;/html&gt;&nbsp;</font>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39888.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-18 16:19 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39888.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JSP数据库连接大全</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39885.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Mon, 18 Feb 2008 07:35:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39885.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39885.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39885.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39885.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39885.html</trackback:ping><description><![CDATA[一、jsp连接Oracle8/8i/9i数据库（用thin模式） <br><br><br><br>testoracle.jsp如下： <br>&lt; %@ page contentType="text/html;charset=gb2312"% &gt; <br>&lt; %@ page import="java.sql.*"% &gt; <br>&lt; html &gt; <br>&lt; body &gt; <br>&lt; %Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); <br>String url="jdbc:oracle:thin:@localhost:1521:orcl"; <br>//orcl为你的数据库的SID <br>String user="scott"; <br>String password="tiger"; <br>Connection conn= DriverManager.getConnection(url,user,password); <br>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <br>String sql="select * from test"; <br>ResultSet rs=stmt.executeQuery(sql); <br>while(rs.next()) {% &gt; <br>您的第一个字段内容为：&lt; %=rs.getString(1)% &gt; <br>您的第二个字段内容为：&lt; %=rs.getString(2)% &gt; <br>&lt; %}% &gt; <br>&lt; %out.print("数据库操作成功，恭喜你");% &gt; <br>&lt; %rs.close(); <br>stmt.close(); <br>conn.close(); <br>% &gt; <br>&lt; /body &gt; <br>&lt; /html &gt; <br><br>二、jsp连接Sql Server7.0/2000数据库 <br><br>testsqlserver.jsp如下： <br>&lt; %@ page contentType="text/html;charset=gb2312"% &gt; <br>&lt; %@ page import="java.sql.*"% &gt; <br>&lt; html &gt; <br>&lt; body &gt; <br>&lt; %Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); <br>String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=pubs"; <br>//pubs为你的数据库的 <br>String user="sa"; <br>String password=""; <br>Connection conn= DriverManager.getConnection(url,user,password); <br>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <br>String sql="select * from test"; <br>ResultSet rs=stmt.executeQuery(sql); <br>while(rs.next()) {% &gt; <br>您的第一个字段内容为：&lt; %=rs.getString(1)% &gt; <br>您的第二个字段内容为：&lt; %=rs.getString(2)% &gt; <br>&lt; %}% &gt; <br>&lt; %out.print("数据库操作成功，恭喜你");% &gt; <br>&lt; %rs.close(); <br>stmt.close(); <br>conn.close(); <br>% &gt; <br>&lt; /body &gt; <br>&lt; /html &gt; <br>三、jsp连接DB2数据库 <br><br>testdb2.jsp如下： <br>&lt; %@ page contentType="text/html;charset=gb2312"% &gt; <br>&lt; %@ page import="java.sql.*"% &gt; <br>&lt; html &gt; <br>&lt; body &gt; <br>&lt; %Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance(); <br>String url="jdbc:db2://localhost:5000/sample"; <br>//sample为你的数据库名 <br>String user="admin"; <br>String password=""; <br>Connection conn= DriverManager.getConnection(url,user,password); <br>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <br>String sql="select * from test"; <br>ResultSet rs=stmt.executeQuery(sql); <br>while(rs.next()) {% &gt; <br>您的第一个字段内容为：&lt; %=rs.getString(1)% &gt; <br>您的第二个字段内容为：&lt; %=rs.getString(2)% &gt; <br>&lt; %}% &gt; <br>&lt; %out.print("数据库操作成功，恭喜你");% &gt; <br>&lt; %rs.close(); <br>stmt.close(); <br>conn.close(); <br>% &gt; <br>&lt; /body &gt; <br>&lt; /html &gt; <br><br>四、jsp连接Informix数据库 <br><br>testinformix.jsp如下： <br>&lt; %@ page contentType="text/html;charset=gb2312"% &gt; <br>&lt; %@ page import="java.sql.*"% &gt; <br>&lt; html &gt; <br>&lt; body &gt; <br>&lt; %Class.forName("com.informix.jdbc.IfxDriver").newInstance(); <br>String url = <br>"jdbc:informix-sqli://123.45.67.89:1533/testDB:INFORMIXSERVER=myserver; <br>user=testuser;password=testpassword"; <br>//testDB为你的数据库名 <br>Connection conn= DriverManager.getConnection(url); <br>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <br>String sql="select * from test"; <br>ResultSet rs=stmt.executeQuery(sql); <br>while(rs.next()) {% &gt; <br>您的第一个字段内容为：&lt; %=rs.getString(1)% &gt; <br>您的第二个字段内容为：&lt; %=rs.getString(2)% &gt; <br>&lt; %}% &gt; <br>&lt; %out.print("数据库操作成功，恭喜你");% &gt; <br>&lt; %rs.close(); <br>stmt.close(); <br>conn.close(); <br>% &gt; <br>&lt; /body &gt; <br>&lt; /html &gt; <br><br>五、jsp连接Sybase数据库 <br><br>testmysql.jsp如下： <br>&lt; %@ page contentType="text/html;charset=gb2312"% &gt; <br>&lt; %@ page import="java.sql.*"% &gt; <br>&lt; html &gt; <br>&lt; body &gt; <br>&lt; %Class.forName("com.sybase.jdbc.SybDriver").newInstance(); <br>String url =" jdbc:sybase:Tds:localhost:5007/tsdata"; <br>//tsdata为你的数据库名 <br>Properties sysProps = System.getProperties(); <br>SysProps.put("user","userid"); <br>SysProps.put("password","user_password"); <br>Connection conn= DriverManager.getConnection(url, SysProps); <br>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <br>String sql="select * from test"; <br>ResultSet rs=stmt.executeQuery(sql); <br>while(rs.next()) {% &gt; <br>您的第一个字段内容为：&lt; %=rs.getString(1)% &gt; <br>您的第二个字段内容为：&lt; %=rs.getString(2)% &gt; <br>&lt; %}% &gt; <br>&lt; %out.print("数据库操作成功，恭喜你");% &gt; <br>&lt; %rs.close(); <br>stmt.close(); <br>conn.close(); <br>% &gt; <br>&lt; /body &gt; <br>&lt; /html &gt; <br><br>六、jsp连接MySQL数据库 <br><br>testmysql.jsp如下： <br>&lt; %@ page contentType="text/html;charset=gb2312"% &gt; <br>&lt; %@ page import="java.sql.*"% &gt; <br>&lt; html &gt; <br>&lt; body &gt; <br>&lt; %Class.forName("org.gjt.mm.mysql.Driver").newInstance(); <br>String url ="jdbc:mysql://localhost/softforum?user=soft&amp;password=soft1234&amp;useUnicode=true&amp;characterEncoding=8859_1" <br>//testDB为你的数据库名 <br>Connection conn= DriverManager.getConnection(url); <br>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <br>String sql="select * from test"; <br>ResultSet rs=stmt.executeQuery(sql); <br>while(rs.next()) {% &gt; <br>您的第一个字段内容为：&lt; %=rs.getString(1)% &gt; <br>您的第二个字段内容为：&lt; %=rs.getString(2)% &gt; <br>&lt; %}% &gt; <br>&lt; %out.print("数据库操作成功，恭喜你");% &gt; <br>&lt; %rs.close(); <br>stmt.close(); <br>conn.close(); <br>% &gt; <br>&lt; /body &gt; <br>&lt; /html &gt; <br><br>七、jsp连接PostgreSQL数据库 <br><br>testmysql.jsp如下： <br>&lt; %@ page contentType="text/html;charset=gb2312"% &gt; <br>&lt; %@ page import="java.sql.*"% &gt; <br>&lt; html &gt; <br>&lt; body &gt; <br>&lt; %Class.forName("org.postgresql.Driver").newInstance(); <br>String url ="jdbc:postgresql://localhost/soft" <br>//soft为你的数据库名 <br>String user="myuser"; <br>String password="mypassword"; <br>Connection conn= DriverManager.getConnection(url,user,password); <br>Statement stmt=conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,ResultSet.CONCUR_UPDATABLE); <br>String sql="select * from test"; <br>ResultSet rs=stmt.executeQuery(sql); <br>while(rs.next()) {% &gt; <br>您的第一个字段内容为：&lt; %=rs.getString(1)% &gt; <br>您的第二个字段内容为：&lt; %=rs.getString(2)% &gt; <br>&lt; %}% &gt; <br>&lt; %out.print("数据库操作成功，恭喜你");% &gt; <br>&lt; %rs.close(); <br>stmt.close(); <br>conn.close(); <br>% &gt; <br>&lt; /body &gt; <br>&lt; /html &gt; 
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39885.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-18 15:35 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39885.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>.NET中各种数据库连接大全</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39884.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Mon, 18 Feb 2008 07:25:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39884.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39884.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39884.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39884.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39884.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;SQL Server    &nbsp;ODBC             &nbsp;Standard Security:"Driver={SQL Server};Server=Aron1;Database=pubs;Uid=sa;Pwd=asdasd;"         &nbsp;Trusted connection:"Driver={SQL S...&nbsp;&nbsp;<a href='http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39884.html'>阅读全文</a><img src ="http://www.cnitblog.com/wufajiaru/aggbug/39884.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-18 15:25 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39884.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>java数据库连接大全 </title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39883.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Mon, 18 Feb 2008 07:23:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39883.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39883.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39883.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39883.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39883.html</trackback:ping><description><![CDATA[<br>数据库连接大全下面罗列了各种数据库使用JDBC连接的方式，可以作为一个手册使用。 <br>1、Oracle8/8i/9i数据库（thin模式） Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl为数据库的SID String user="test"; String password="test"; Connection conn= DriverManager.getConnection(url,user,password); <br><br>2、DB2数据库 Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance(); String url="jdbc:db2://localhost:5000/sample"; //sample为你的数据库名 String user="admin"; String password=""; Connection conn= DriverManager.getConnection(url,user,password);<br><br>3、Sql Server7.0/2000数据库 Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance(); String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb"; //mydb为数据库 String user="sa"; String password=""; Connection conn= DriverManager.getConnection(url,user,password); <br><br>4、Sybase数据库 Class.forName("com.sybase.jdbc.SybDriver").newInstance(); String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDB为你的数据库名 Properties sysProps = System.getProperties(); SysProps.put("user","userid"); SysProps.put("password","user_password"); Connection conn= DriverManager.getConnection(url, SysProps); <br><br>5、Informix数据库 Class.forName("com.informix.jdbc.IfxDriver").newInstance(); String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver; user=testuser;password=testpassword"; //myDB为数据库名 Connection conn= DriverManager.getConnection(url); <br><br>6、MySQL数据库 Class.forName("org.gjt.mm.mysql.Driver").newInstance(); String url ="jdbc:mysql://localhost/myDB?user=soft&amp;password=soft1234&amp;useUnicode=true&amp;characterEncoding=8859_1" //myDB为数据库名 Connection conn= DriverManager.getConnection(url); <br><br>7、PostgreSQL数据库 Class.forName("org.postgresql.Driver").newInstance(); String url ="jdbc:postgresql://localhost/myDB" //myDB为数据库名 String user="myuser"; String password="mypassword"; Connection conn= DriverManager.getConnection(url,user,password); <br><br>8、access数据库直连用ODBC的 Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ; String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb"); Connection conn = DriverManager.getConnection(url,"",""); Statement stmtNew=conn.createStatement() ;<br><br><br>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39883.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-18 15:23 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39883.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ado,dao,odbc的定义和关系</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39880.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Mon, 18 Feb 2008 06:30:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39880.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39880.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39880.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39880.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39880.html</trackback:ping><description><![CDATA[<p><br>&nbsp;</p>
<div class=bc0 style="PADDING-RIGHT: 0pt; PADDING-LEFT: 0pt; PADDING-BOTTOM: 5px; PADDING-TOP: 5px">
<div class=wr>
<div class="f14 p90 pl10"><ca>ADO <br>来自ITwiki，开放的中文IT百科 <br>Jump to: navigation, &lt;jumptoSearch&gt; <br>微软公司的ADO (ActiveX Data Objects) 是一个用于存取数据源的COM组件。它提供了编程语言和统一数据访问方式OLE DB的一个中间层。允许开发人员编写访问数据的代码而不用关心数据库是如何实现的，而只用关心到数据库的连接。访问数据库的时候，关于SQL的知识不是必要的，但是特定数据库支持的SQL命令仍可以通过ADO中的命令对象来执行。 <br><br>ADO被设计来继承微软早期的数据访问对象层，包括RDO (Remote Data Objects) 和DAO(Data Access Objects)。ADO在1996年冬被发布。 <br><br>ADO包含一些顶层的对象： <br><br>连接，代表到数据库的连接 <br>记录集，代表数据库记录的一个集合 <br>命令，代表一个SQL命令 <br>记录，代表数据的一个集合 <br>流，代表数据的顺序集合 <br>错误，代表数据库访问中产生的意外 <br>字段，代表一个数据库字段 <br>参数，代表一个SQL参数 <br>属性，保存对象的信息 <br>ADO组件的使用需要利用支持COM的高级语言，例如ASP中的VBScript或者Visual Basic，甚至Delphi,微软的竞争对手Borland的一个产品，现在也支持使用ADO来访问数据库。 <br><br>在新的编程框架.NET Framework中, 微软也提供了一个面向Internet的版本的ADO，称为ADO.NET。其对象模型和传统ADO差别很大。 <br><br><br>DAO <br><br>DAO(Database Access Object)使用Microsoft Jet数据库引擎来访问数据库。Microsoft Jet为象Access和Visual Basic这样的产品提供了数据引擎。 <br><br>与ODBC一样，DAO提供了一组API供编程使用。MFC也提供了一组DAO类，封装了底层的API，从而大大简化了程序的开发。利用MFC的DAO类，用户可以编写独立于DBMS的应用程序。 <br><br>DAO是从Visual C++4.0版开始引入的。一般地讲，DAO类提供了比ODBC类更广泛的支持。一方面，只要有ODBC驱动程序，使用Microsoft Jet的DAO就可以访问ODBC数据源。另一方面，由于DAO是基于Microsoft Jet引擎的，因而在访问Access数据库(即*.MDB文件)时具有很好的性能。 <br><br><br>DAO和ODBC的相似之处 <br><br>DAO类与ODBC类相比具有很多相似之处，这主要有下面几点： <br><br>二者都支持对各种ODBC数据源的访问。虽然二者使用的数据引擎不同，但都可以满足用户编写独立于DBMS的应用程序的要求。 <br><br>DAO提供了与ODBC功能相似的MFC类。例如，DAO的CDaoDatabase类对应ODBC的CDatabase类，CDaoRecordset对应CRecordset，CDaoRecordView对应CRecordView，CDaoException对应CDBException。这些对应的类功能相似，它们的大部分成员函数都是相同的。 <br><br>AppWizard和ClassWizard对使用DAO和ODBC对象的应用程序提供了类似的支持。 <br><br>由于DAO和ODBC类的许多方面都比较相似，因此只要用户掌握了ODBC，就很容易学会使用DAO。实际上，用户可以很轻松地把数据库应用程序从ODBC移植到DAO。 <br><br>Visual C++随盘提供了一个名为DaoEnrol的例子，该例实际上是Enroll的一个DAO版本。读者可以打开DaoEnrol工程看一看，它的源代码与Enroll的极为相似。读者可以按照建立Enroll的步骤来建立DaoEnrol，其中只有若干个地方有差别，这主要有以下几点： <br><br>选取的数据源不同。在用AppWizard创建DaoEnrol时，以及在用ClassWizard创建CDaoRecordset类的派生类时，在Database Options对话框中应该选择DAO而不是ODBC。而且DAO的数据源是通过选择一个.MDB文件来指定的，即点击&#8220;...&#8221;按钮后在文件对话框中选择要访问的.MDB文件。 <br><br>记录集的缺省类型不同。ODBC记录集的缺省类型是快照(Snapshot)，而DAO则是动态集(Dynaset)。 <br><br>参数化的方式不同。DAO记录集的m_strFilter和m_strSort中的参数不是&#8220;?&#8221;号，而是一个有意义的参数名。例如，在下面的过滤器中有一个名为CourseIDParam的参数。 <br>m_pSet-&gt;m_strFilter ="CourseID = CourseIDParam"; <br>在DoFieldExchange函数中，有下面两行： <br>pFX-&gt;SetFieldType(CDaoFieldExchange::param); <br>DFX_Text(pFX, _T("CourseIDParam"), m_strCourseIDParam); <br>DFX函数的第二个参数也是CourseIDParam。 <br><br>处理异常的方式不同。例如，在删除记录时，对异常的处理如下所示： <br><br>try <br><br>{ <br><br>m_pSet-&gt;Delete(); <br><br>} <br><br>catch(CDaoException* e) <br><br>{ <br><br>AfxMessageBox(e-&gt; <br><br>m_pErrorInfo-&gt;m_strDescription); <br><br>e-&gt;Delete(); <br><br>} <br><br>除了上述差别外，AppWizard和ClassWizard也隐藏了一些细微的不同之处，例如，DAO记录集是使用是DFX数据交换机制(DAO record field exchange)而不是RFX，在DAO记录集的DoFieldExchange中使用的是DFX函数而不是RFX函数。 <br><br>10.8.3 DAO的特色 <br><br>DAO可以通过ODBC驱动程序访问ODBC数据源。但DAO是基于Microsoft Jet引擎的，通过该引擎，DAO可以直接访问Access、FoxPro、dBASE、Paradox、Excel和Lotus WK等数据库。CDaoDatabase类可以直接与这些数据库进行连接，而不必在ODBC管理器中注册DSN。例如，下面的代码用来打开一个FoxPro数据库： <br><br>CDaoDatabase daoDb; <br><br>daoDb.Open( &#8220;&#8221;,FALSE,FALSE,"FoxPro 2.5;DATABASE=c:\\zyf"); <br><br>CDaoDatabase::Open函数用来连接某个数据库，该函数的声明为： <br><br>virtual void Open( LPCTSTR lpszName, BOOL bExclusive = FALSE, BOOL bReadOnly = FALSE, LPCTSTR lpszConnect = _T("") ); <br>throw( CDaoException, CMemoryException );</ca><br>参考资料：<a href="http://www.czvc.com/tech/Visual%20C++JC/chap10_8.htm" target=_blank>http://www.czvc.com/tech/Visual%20C++JC/chap10_8.htm</a>裡面都有介紹</div>
</div>
</div>
<p><br>补充：<br><br>
<table width="100%" align=center>
    <tbody>
        <tr>
            <td class=title align=middle>ado和dao的区别 </td>
        </tr>
        <tr>
            <td align=middle><a href="http://www.itisedu.com/"><u><font color=#0000ff>http://www.itisedu.com</font></u></a>&nbsp;&nbsp;&nbsp;2006-4-17 11:08:11&nbsp;&nbsp;&nbsp;<a href="http://www.itisedu.com/"><u><font color=#0000ff>中科永联</font></u></a> </td>
        </tr>
        <tr>
            <td align=left>[关键字]ADO DAO ODBC </td>
        </tr>
        <tr>
            <td>
            <p><font face=Verdana><a href="http://www.itisedu.com/phrase/200604152347055.html" target=_new><u><font color=#0000ff>ADO</font></u></a>：Active数据<a href="http://www.itisedu.com/phrase/200603090845215.html" target=_new><u><font color=#0000ff>对象</font></u></a>(ActiveData<a href="http://www.itisedu.com/phrase/200603090845215.html" target=_new><u><font color=#0000ff>object</font></u></a>s)：ADO实际是一种提供访问各种数据<a href="http://www.itisedu.com/phrase/200603051002565.html" target=_new><u><font color=#0000ff>类型</font></u></a>的连接机制。ADO设计为一种极简单的格式，通过<a href="http://www.itisedu.com/phrase/200604151956245.html" target=_new><u><font color=#0000ff>ODBC</font></u></a>的方法同<a href="http://www.itisedu.com/phrase/200602271218062.html" target=_new><u><font color=#0000ff>数据库</font></u></a>接口。可以使用任何一种O<a href="http://www.itisedu.com/phrase/200602271218062.html" target=_new><u><font color=#0000ff>DB</font></u></a>C数据源，即不止适合于<a href="http://www.itisedu.com/phrase/200604022014515.html" target=_new><u><font color=#0000ff>SQL</font></u></a>Server、<a href="http://www.itisedu.com/phrase/200604040935115.html" target=_new><u><font color=#0000ff>ORACLE</font></u></a>、Acc<a href="http://www.itisedu.com/phrase/200603112246585.html" target=_new><u><font color=#0000ff>ES</font></u></a>s等数据库应用<a href="http://www.itisedu.com/phrase/200602281649395.html" target=_new><u><font color=#0000ff>程序</font></u></a>，也适合于Excel表格、文本<a href="http://www.itisedu.com/phrase/200602282323195.html" target=_new><u><font color=#0000ff>文件</font></u></a>、图形文件和无格式的数据文件。ADO是基于OLE-DB之上的技术，因此ADO通过其内部的属性和方法提供统一的数据访问接口方法。<br>　　<a href="http://www.itisedu.com/phrase/200604162200335.html" target=_new><u><font color=#0000ff>DAO</font></u></a>：<a href="http://www.itisedu.com/phrase/200604162200335.html" target=_new><u><font color=#0000ff>数据访问对象</font></u></a>(DataAccessObj<a href="http://www.itisedu.com/phrase/200603011335015.html" target=_new><u><font color=#0000ff>EC</font></u></a>ts)：是一种<a href="http://www.itisedu.com/phrase/200603101726185.html" target=_new><u><font color=#0000ff>面向对象</font></u></a>的界面接口。通过DAO/Jet功能可以访问IS<a href="http://www.itisedu.com/phrase/200603091620485.html" target=_new><u><font color=#0000ff>AM</font></u></a>数据库，使用DAO/ODBC<a href="http://www.itisedu.com/phrase/200603091205485.html" target=_new><u><font color=#0000ff>DI</font></u></a>rect功能可以实现远程<a href="http://www.itisedu.com/phrase/200604162201165.html" target=_new><u><font color=#0000ff>RDO</font></u></a>功能。使用DAO的程序编码非常简单，DAO提供丰富的游标(Cursor)<a href="http://www.itisedu.com/phrase/200603090857555.html" target=_new><u><font color=#0000ff>类</font></u></a>型的结果集和非游标(Cursor-Less)类型的结果集，同DDL(数据描述语言)的功能很类似。<br>现在vb数据库编程大都使用ADO,很少人还用DAO.</font></p>
            <p><font face=Verdana>DAO是集合，对象，方法和属性；它用对象集合来处理数据库，表，<a href="http://www.itisedu.com/phrase/200603141659315.html" target=_new><u><font color=#0000ff>视图</font></u></a>和索引等。使用DAO编程，可以访问并操作数据库，管理数据库的对象和定义数据库的结构等。</font></p>
            <p><font face=Verdana>ADO是类似于DAO和RDO的面向对象的数据库访问技术。DAO是第一个面向对象的接口，它显露了mi<a href="http://www.itisedu.com/phrase/200604161514015.html" target=_new><u><font color=#0000ff>CR</font></u></a><a href="http://www.itisedu.com/phrase/200602281634075.html" target=_new><u><font color=#0000ff>OS</font></u></a>oft Jet数据库引擎，并允许VB开发者通过ODBC直接连接到其他数据库一样，直接连接到access表。DAO适合单系统应用程序或小范围本地分布使用。</font></p>
            <p><font face=Verdana>ADO是DAO/RDO的后继产品，它扩展了DAO和RDO所使用的对象模型，这以为着它包含较少的对象，更多的属性，方法（和参数），以及事件。ADO当前并不支持DAO的所有功能，它主要包括RDO风格的功能性，以便和<a href="http://www.itisedu.com/phrase/200604162245295.html" target=_new><u><font color=#0000ff>OLE DB</font></u></a>数据源交互，另外还包括远程和DHTML技术。<br></font></p>
            </td>
        </tr>
    </tbody>
</table>
<br></p>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39880.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-18 14:30 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39880.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]JDO之前世今生</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39871.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Mon, 18 Feb 2008 02:44:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39871.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39871.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39871.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39871.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39871.html</trackback:ping><description><![CDATA[<table class=buttomBorder cellSpacing=3 cellPadding=3 width="100%" border=0>
    <tbody>
        <tr>
            <td class=contentTitle align=middle>JDO之前世今生
            <hr width="70%">
            </td>
        </tr>
        <tr>
            <td align=middle>2007-04-13&nbsp; &nbsp;来源:www.javaresearch.org &nbsp;作者:未知</td>
        </tr>
        <tr>
            <td class=content vAlign=top align=left>
            <table class=rtable width="98%" border=0>
                <tbody>
                    <tr>
                        <td class=text align=left width="100%"><br>（本文转自《CSDN开发高手》2003第10期）<br><br>
                        <h3>1&nbsp;&nbsp;&nbsp;&nbsp;Java与数据库应用，JDBC</h3>
                        <br>Java发明以来，在短短的几年之间，迅速占领了从桌面应用（J2SE）到服务器（J2EE），再到小型设备嵌入式系统（J2ME）的应用开发市场，其语言吸取了SmallTalk的一切皆对象的理念，摆脱了C++的历史累赘，简洁、自由的风格赢得了很多开发者的喜爱。从JDK1.1开始，Java成为实用的语言，而不是被人观望的新品秀；再经过JDK1.2的大量增强（尤其是Collection&nbsp;Framework），JDK1.3的虚拟机效率提升（HotSpot），JDK1.4的融合百家之长（Logging、RegExp、NewIO等），现在已经是成熟稳重，颇显大家风范。<br>在企业级市场上，大部分的应用建立在数据库基础上，数据是企业的生命，传统开发语言，包括面向过程的C、面向对象的C++、变种Pascal的Delphi（非常棒的语言，我用过四年），面向数据的PowerBuilder等等，先后在数据库开发的舞台上展现风姿。Java当然不会放过这些，于是，出现了JDBC。在JDBC的帮助下，Java也迅速渗入数据库开发的市场，尤其是面向企业服务器的应用开发。<br>今天要谈的JDO，与JDBC有非常密切的关系，尽管JDO并不是只面向JDBC的数据对象包装规范。下面先简单地介绍一下JDBC。<br>
                        <h4>1.1&nbsp;&nbsp;&nbsp;&nbsp;关系数据库之百家争鸣，ODBC</h4>
                        关系数据库的历史一言难尽，我只能从我的接触经历和所见所闻，简单地叙述一下。最早的时候，计算机还只在一些大型的研究机关露面，并不是普罗大众可以涉及的。苹果电脑将个人电脑引入民间，再随着IBM的PC标准开放，个人电脑逐步普及开来，加上微软的DOS操作系统，以及Borland的Turbo系列语言开发环境，老百姓发现原来电脑可以做这么多事！后来，出现了DBASE，一个简单的关系数据库系统，和SQL语言。后来，Borland看到了数据库的市场前景，推出了Paradox（也是当今Delphi和C++Builder中仍然使用的Paradox），一举占领了民用数据库的大部分江山，之后，Borland干脆收购了Dbase，后来又购买了InterBase，将数据库市场的领先优势一直保持到Windows3.0出现。这时候，微软在Windows1.0和2.0被人痛骂之后顽强地推出3.0，以及更稳定的3.1和Win32API，造就了个人电脑桌面操作系统的霸主地位，在Borland未警觉的情况下，购买了同样具有类Dbase数据库技术的Fox公司，并迅速将其易用化，形成了FoxBase，后来演变成FoxPro，逐渐超过了Borland，成为个人电脑数据库的大户。微软再接再励，为简单易用而低负荷要求的数据库应用开发了Access，赢得了广大开发人员的心。当然，同期的Oracle、Sybase、Informix等商用数据库凭专注于企业级数据库技术成为高端的几位领军人物。微软当然也想成为高端数据库供应商之一，于是自行开发一套面向企业级应用的数据库，不过很快项目夭折，微软不甘心，购买了Sybase的底层TDS技术，包装成了SQL&nbsp;Server，凭微软的高度易用性的特点，也占领了不少市场。<br>当市场上出现众多的数据库产品之后，Borland和微软都发现自己拥有的数据库产品挺多，市场也不小，不同的产品给用户带来不同的配置任务，不利于所有产品的推广，于是，两者纷纷开始制定数据库访问的规范，微软推出了ODBC，其面向开发人员的亲和性，逐步获得了认可，同时，Borland纠集了IBM和Novell也推出了IDAPI数据库接口规范，也就是今天BDE的核心，不过后来Novell和IBM先后退出，只剩Borland独力支撑。不过Borland是一个技术实力雄厚的公司，其技术一向领先于微软，BDE的性能比初期的ODBC不知道要好多少倍，后来微软偷师学艺，把连接池等技术加到ODBC中，在Delphi3.0及其BDE在市场上风光无限的时候，逐步赶了上来并有超过。直到今天，BDE仍是Borland的产品线上的数据库访问标准，而微软如果不是将ODBC和多数数据库的客户端内嵌进Windows的话，估计BDE仍是市场的赢家。不过，微软是玩弄市场的老手，通过对操作系统的垄断，其数据库产品和ODBC标准终究占据了多数开发市场。<br>
                        <h4>1.2&nbsp;&nbsp;&nbsp;&nbsp;从optional&nbsp;pack到JDK的标准API</h4>
                        <br>Java开始涉及数据库应用后，Sun就极力制定Java的数据库规范，JDBC&nbsp;API就是类似ODBC一样，对数据库访问的底层协议进行最基本的包装，然后形成一套统一的数据访问接口，数据库连接、SQL语句句柄、结果集，都带有ODBC的影子。以方便配置为目的，Sun极力推荐完全瘦客户端的TYPE&nbsp;4型JDBC驱动，这是一个不需要安装数据库客户端的驱动规范，是现在使用最多的。当然，为了保持与旧的数据库兼容，JDBC规范中包括了专用于连接ODBC的TYPE&nbsp;1驱动和需要安装数据库客户端的TYPE&nbsp;2驱动，以及可以由厂商在数据库服务端专门提供面向JDBC的服务的TYPE&nbsp;3驱动。<br>JDBC最早出现时，还不属于标准JDK的一部分，而是作为一个额外包提供下载。后来，随着Java编写的数据库应用的的增多，和JDBC规范本身的逐渐成熟，JDBC终于成为JDK1.1的一部分。<br>JDBC目前最新的是3.0版本，还有正在讨论中的4.0版本。实际上，在开发中使用得最多的还是1.0中的API，2.0中主要增加了可双向滚动的结果集、更新批处理等提高可用性和性能的API，3.0主要增加了连接池、可更新的结果集等特性。4.0将在可管理性、连接池规范化等方面再做改进。<br>
                        <h3>2&nbsp;&nbsp;&nbsp;&nbsp;面向对象与数据库</h3>
                        <br>现在的程序员，没有不知道面向对象的。作为接近真实客观世界的开发概念，面向对象使程序代码更易读、设计更合理。在普遍存在的数据库应用领域，开发人员对面向对象的追求从未停止过。从八十年代开始，就有很多公司和研究机构在进行着面向对象与数据库结合的研究。<br>
                        <h4>2.1&nbsp;&nbsp;&nbsp;&nbsp;SmallTalk、C与C++、Delphi?DObject&nbsp;Pascal、Java</h4>
                        面向对象的语言最早有好几种雏形，IBM的SmallTalk是其中最为流行的，在SmallTalk中，一切都是对象，一切都是类，它将面向对象的概念发挥到了极致。面向对象的编程比起传统的面向过程的方式挺进了一大步，使人们认识到：原来软件可以这样写。不过，由于计算机基本结构与底层硬件体系和系统软件的限制，SmallTalk还不能在理想的性能前提下推广到普通的应用上，这一点暂时限制了SmallTalk的发展，接着，C语言的面向对象版C++出现了，由于使用C语言的人很多，C++很快成为面向对象编程的主流语言。不过，为了保证与C的兼容，C++保留了很多面向过程的痕迹，比如恶心的指针、全局变量等等。Pascal的改进版Object&nbsp;Pascal相对来说安全许多，后来Borland干脆将Object&nbsp;Pascal换了个名字，叫Delphi，从此开创了一片面向对象编程的新世界，&nbsp;Delphi的严谨语法和快速编译吸引了众多的应用开发者，加上Borland的完美的VCL组件体系，比起MFC来方便而容易，另外，Delphi完整的数据库组件，也将数据库开发变得简单而容易，Delphi再次成为成熟的面向对象开发语言。微软当然不会放过这些，通过将MFC内置到操作系统中，微软的VC++也抢回一些市场。这也是为什么Delphi开发的应用程序编译后会比VC、VB开发的程序大的原因。<br>1995年，Sun的一个开发小组本来为了小型嵌入式系统开发OAK语言，结果无心插柳柳成荫，发展出了Java语言，它是一个完全摆脱了传统语言的各种负担的面向对象的语言，当然，也保留了一些非面向对象的核心（原始类型）以保证速度。现在Java也为最流行的面向对象语言之一。当然，微软同样不会放过它，擅于模仿的微软立即弄出一个C#来与之竞争，并在C#中保留了一些变种的指针（指代）以吸引传统的C开发者。关于这些语言的各自特点，这里就不一一赘述了。<br>
                        <h4>2.2&nbsp;&nbsp;&nbsp;&nbsp;数据库与数据对象化</h4>
                        <br>数据库是企业级应用不可缺少的，因此，在面向对象流行的时候，数据库厂商也在进行着数据对象化的研究。这些研究在上个世纪八十年代就初现端倪。<br>数据库的对象化一般有两个方向：一个是在主流的关系数据库的基础上加入对象化特征，使之提供面向对象的服务，但访问语言还是基于SQL；另一个方向就是彻底抛弃关系数据库，用全新的面向对象的概念来设计数据库，这就是对象数据库ODBMS。<br>
                        <h5>2.2.1&nbsp;&nbsp;&nbsp;&nbsp;关系数据库对象化、SQL99与JDBC3.0</h5>
                        随着许多关系数据库厂商开始提供对象化服务，各自的接口开始互不兼容，在经历一些麻烦之后，关系数据库厂商感觉到规范化的必要，因为当初关系数据库雄霸天下时SQL92标准起了很大作用，大家可以按照统一的编程方式来访问高性能的商用数据库。<br>关系数据库厂商集中起来，重新将对象化服务规范起来，形成了SQL99规范，将其中的对象结构等内容规范起来，开始一个崭新的面向对象的关系数据库（ORDBMS）的历程。<br>JDBC3.0就是在这种情况下出台的，它将对关系数据库中的对象服务的访问API规范起来，为Java平台提供了访问ORDBMS的标准方式。当然，JDBC3.0对传统的SQL操作也进行了很多功能增强。<br>Oracle是一个传统的关系数据库厂商，在对象化的道路上，Oracle当然采取追加对象化特征的道路，以侵入数据对象化的市场，保持Oracle在数据库领域的领导地位。如果说Oracle7.4使Oracle走向全盛的话，从Oracle8开始，Oracle就成为关系数据库加对象类型的先驱。在Oracle8中，我们可以定义一些数据结构（Record），将普通的类型包装在其中成为数据元素，然后可以在客户端按Record结构进行访问，初步提供了面向对象的数据库服务。<br>
                        <h5>2.2.2&nbsp;&nbsp;&nbsp;&nbsp;对象数据库</h5>
                        <br>对象数据库就是采用全新的面向对象概念来设计数据库的全新数据库类型。在这方面，主要以一些大学研究机构进行设计和开发，有些也形成了产品，不过由于市场方面的原因（主要是关系数据库的容易上手和市场绝对领导地位）和ODBMS先天的一些弱点（比如查询引擎很难优化），使ODBMS没有象关系数据库那样流行起来。<br>不过对象数据库的对象化特点还是令人割舍不下，目前还是有一些很好的产品在市场上，从商用的到免费的都用。目前在ODBMS领域占据领导地位的是Versant、FastObjects和ObjectStore等几大厂商，并且，市场份额也在逐步扩展。免费的产品包括C++编写的Ozone、纯Java的db4o等等。还有一些研究机构开发一些底层的面向对象数据库引擎，但只提供一些底层的API，不提供管理方面的功能，以及一些算法提供开放式接口，让厂商去选择和实现。比如美国威斯康新大学计算机系数据库组的SHORE引擎，就是一个非常出色的面向对象数据库引擎，现在还在积极的更新中，一些其它研究机构和数据库厂商采用它完成了自己的特别的对象数据库，比如专用于地理信息的数据库、专用于宇宙空间数据研究的数据库等等。<br>目前对象数据库最大的障碍是缺乏统一的规范，各个数据库厂商有各自的访问接口。对象数据库比起关系数据库来，不只是基本的几种数据类型那么简单，它还涉及继承处理、多态等一大堆面向对象特征的实现，规范化道路当然困难重重。这也是对象数据库无法普及的一个重要原因。<br>也有一些机构提出了一些建议的规范，比如制定Corba标准的OMG小组的一个分组ODMG提出的ODMG规范，目前已经是3.0版本，其中的OQL对象查询语言相当具有吸引力。还有一些中立的机构提出了其它的一些标准化的对象访问API，也可算是面向对象数据库的规范之一。象前面提到的FastObjects和Ozone就是符合ODMG3.0规范的。<br>
                        <h3>3&nbsp;&nbsp;&nbsp;&nbsp;Java对象映射</h3>
                        <br>话说回来，在一般的开发人员眼中，数据库就是指关系数据库，因此，很多应用还是采用简单的JDBC来访问数据库。在开发的过程中，大家逐渐感觉到JDBC的局限性，比如调用复杂、容易产生资源泄漏等等，与面向对象的Java语言有一段距离，因此，很多开发小组开始思考如何将应用中的数据进行对象化建模，然后再想办法与JDBC结合起来，这就是Java数据库开发中的层出不穷的对象包装技术。<br>
                        <h4>3.1&nbsp;&nbsp;&nbsp;&nbsp;对象包装技术</h4>
                        <br>
                        <h5>3.1.1&nbsp;&nbsp;&nbsp;&nbsp;传统包装与演变</h5>
                        <br>传统包装顾名思义，就是最初出现的包装方式，很多公司都经历过这一步，产生了很多风格各异的包装方法。当然，笔者也有过还算丰富的尝试过程。<br>举例来说，如果我们有一个用户类：<br>public&nbsp;class&nbsp;User&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;userId;<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;name;<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;java.util.Date&nbsp;birthday;<br>}<br>我们可以将其当作一个简单的数据类，然后写一些工具方法来实现与JDBC的交互。这些方法，我们可以放到一个另外的工具类中，也可以放到User类中作为静态方法。这些方法包括简单的增、删、改、查（以Oracle为例）：<br>public&nbsp;class&nbsp;User&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;userId;<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;name;<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;java.util.Date&nbsp;birthday;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;User&nbsp;addUser(String&nbsp;name,&nbsp;Date&nbsp;birthday)&nbsp;throws&nbsp;SQLException&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Connection&nbsp;conn&nbsp;=&nbsp;&#8230;;&nbsp;//获取一个JDBC连接<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;PreparedStatement&nbsp;ps&nbsp;=&nbsp;conn.prepareStatement(&#8220;&#8230;&#8221;);&nbsp;//&nbsp;获取一个序列值来作为用户标识<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ResultSet&nbsp;rs&nbsp;=&nbsp;ps.executeQuery();&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rs.next();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;User&nbsp;user&nbsp;=&nbsp;new&nbsp;User();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.userId&nbsp;=&nbsp;rs.getInt(1);&nbsp;//读取序列值为新用户标识<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.name&nbsp;=&nbsp;name;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.birthday&nbsp;=&nbsp;birthday;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps&nbsp;=&nbsp;conn.prepareStatement(&#8220;insert&nbsp;into&nbsp;&#8230;.&#8221;);&nbsp;//插入用户数据记录的SQL<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps.setInt(1,user.id);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps.setString(2,user.name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps.setDate(3,user.birthday);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps.executeUpdate();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rs.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;conn.close();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;user;<br>}<br><br>public&nbsp;static&nbsp;void&nbsp;deleteUser(int&nbsp;userId)&nbsp;throws&nbsp;SQLException&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;Connection&nbsp;conn&nbsp;=&nbsp;&#8230;.;<br>&nbsp;&nbsp;&nbsp;&nbsp;//&#8230;<br>}<br><br>public&nbsp;static&nbsp;User&nbsp;getById(int&nbsp;userId)&nbsp;throws&nbsp;SQLException&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;//&#8230;<br>}<br><br>//&#8230;<br>}<br><br>以上就是一个简单的数据包装的基本雏形，我们可以看到，这是一个非常简单的JDBC包装，一些代码可以模块化，以实现重用。另外，这段代码还有很大隐患，就是中途如果出现异常的话，就会使系统出现JDBC资源漏洞，因为JDBC分配的资源（conn,ps,rs等）是不能被Java虚拟机的垃圾回收机制回收的。因此，我们的addUser方法就需要改成下面的样子：<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;User&nbsp;addUser(String&nbsp;name,&nbsp;Date&nbsp;birthday)&nbsp;throws&nbsp;SQLException&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Connection&nbsp;conn&nbsp;=&nbsp;null;<br>PreparedStatement&nbsp;ps&nbsp;=&nbsp;null;<br>ResultSet&nbsp;rs&nbsp;=&nbsp;null;<br>User&nbsp;user&nbsp;=&nbsp;new&nbsp;User();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br>try&nbsp;{<br>conn&nbsp;=&nbsp;&#8230;;&nbsp;//获取一个JDBC连接<br>ps&nbsp;=&nbsp;conn.prepareStatement(&#8220;&#8230;&#8221;);&nbsp;//&nbsp;获取一个序列值来作为用户标识<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rs&nbsp;=&nbsp;ps.executeQuery();&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rs.next();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.userId&nbsp;=&nbsp;rs.getInt(1);&nbsp;//读取序列值为新用户标识<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.name&nbsp;=&nbsp;name;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.birthday&nbsp;=&nbsp;birthday;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps&nbsp;=&nbsp;conn.prepareStatement(&#8220;insert&nbsp;into&nbsp;&#8230;.&#8221;);&nbsp;//插入用户数据记录的SQL<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps.setInt(1,user.id);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps.setString(2,user.name);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps.setDate(3,user.birthday);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ps.executeUpdate();<br>&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;finally&nbsp;{&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//这里注意一定要按照创建的顺序关闭JDBC资源：<br>&nbsp;&nbsp;&nbsp;&nbsp;if(rs&nbsp;!=&nbsp;null)&nbsp;try&nbsp;{&nbsp;rs.close();&nbsp;}&nbsp;catch(SQLException&nbsp;ex)&nbsp;{&nbsp;ex.printStackTrace();&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(ps&nbsp;!=&nbsp;null)&nbsp;try&nbsp;{&nbsp;ps.close();&nbsp;}&nbsp;catch(SQLException&nbsp;ex)&nbsp;{&nbsp;ex.printStackTrace();&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(conn&nbsp;!=&nbsp;null)&nbsp;try&nbsp;{&nbsp;conn.close();&nbsp;}&nbsp;catch(SQLException&nbsp;ex)&nbsp;{&nbsp;ex.printStackTrace();&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;user;<br>}<br><br>所有的数据库访问方法都必须进行这样的包装，当我们的数据类达到一定的数量后（比如十几个，几十个），这些方法占据了大量的代码，维护困难、出现BUG机会增多，并且不易排错，尤其是资源漏洞这种容易引起服务器稳定性问题的BUG。<br>为了保持数据类的纯洁，我们可以将JDBC操作方法集中到一个公共工具类中去完成，这样，这个工具类会非常庞大，但每个数据类会变得很简单，这种方式，可以称作是DataAccessObject模式，相当于EJB中的ValueObject，是脱离数据库细节的纯对象模型。<br>这些都是最基本的存储处理，在基本增删改查（这里的查指按关键字查找对象）的基础上，我们还需要进行复杂的匹配查询（SQL），这使得我们的存储处理代码进一步复杂化。简单地，我们可以写一个类似的方法：<br>public&nbsp;static&nbsp;Collection&nbsp;findBy(String&nbsp;sql)&nbsp;throws&nbsp;SQLException&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;//&#8230;&nbsp;（这里获取JDBC连接）<br>&nbsp;&nbsp;&nbsp;&nbsp;Collection&nbsp;col&nbsp;=&nbsp;new&nbsp;Vector();<br>&nbsp;&nbsp;&nbsp;&nbsp;ps&nbsp;=&nbsp;conn.prepareStatement(sql);<br>&nbsp;&nbsp;&nbsp;&nbsp;rs&nbsp;=&nbsp;ps.executeQuery();<br>&nbsp;&nbsp;&nbsp;&nbsp;while(rs.next())&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;User&nbsp;user&nbsp;=&nbsp;new&nbsp;User();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.userId&nbsp;=&nbsp;rs.getInt(1);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.name&nbsp;=&nbsp;rs.getString(2);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;user.birthday&nbsp;=&nbsp;rs.getDate(3);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;col.add(user);<br>&nbsp;&nbsp;&nbsp;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;col;<br>&nbsp;&nbsp;&nbsp;&nbsp;//&#8230;&nbsp;（同前，这里是清理JDBC资源的代码）<br>}<br>这就是一个查询接口的基本定义，查询采用的语言仍是SQL。<br>如果我们需要将参数从SQL串中独立出来以节省数据库的解析时间并规范化，我们还需要将查询条件作为参数传递到这个方法中去，方法的接口改为：<br>public&nbsp;static&nbsp;Collection&nbsp;findBy(String&nbsp;sql,&nbsp;Object[]&nbsp;params)&nbsp;throws&nbsp;SQLException&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;//&#8230;<br>&nbsp;&nbsp;&nbsp;&nbsp;ps&nbsp;=&nbsp;conn.prepareStatement(sql);<br>&nbsp;&nbsp;&nbsp;&nbsp;for(int&nbsp;i&nbsp;=&nbsp;0;&nbsp;i&nbsp;&lt;&nbsp;params.length;&nbsp;i++)&nbsp;ps.setObject(i+1,params[i]);<br>&nbsp;&nbsp;&nbsp;&nbsp;//&#8230;<br>}<br>调用的时候sql参数中会包含一些&#8220;？&#8221;号，如：<br>select&nbsp;ID,NAME,BIRTHDAY&nbsp;from&nbsp;USER&nbsp;where&nbsp;&#8230;&nbsp;=&nbsp;?&nbsp;and&nbsp;&#8230;&nbsp;&gt;&nbsp;?&nbsp;and&nbsp;&#8230;<br>当然，也有一些开发团队喜欢将所有可能的查询都写死成一个个的专用查询方法，在其中完成对应的SQL操作，这一点类似于EJBQL，只不过是将EJBQL中容器实现的功能通过手工编码来实现。这样做使得查询受到限制，但可以提供更保险的接口。<br>还有一些开发人员看到每个类中写这样一些查询方法使得这个类的代码变得庞大，维护麻烦，便将所有的查询方法放到一个公共的工具类中去，只是在方法中再加入一个参数：Class&nbsp;cls来表示需要查询哪个对象，使得每个数据类变得紧凑一些。当然，这样的结果是那个公共类变得异常庞大，谁维护谁倒霉，可以说是牺牲一人，幸福团队。不过如果这个人心理素质不够好、压力承受能力不强的话，一些对数据类的改动可能会受到他的阻碍，这时候就是&#8220;一夫当关，万夫莫开&#8221;。<br><br>现在，我们已经实现了基本对象的包装，现在才能开始考虑更多的问题。首先，我们可能会从规范化的角度出发，给每一个属性加上读写访问器getter/setter，在前面的User类中，可能我们会将基本属性部分写为：<br>public&nbsp;class&nbsp;User&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;int&nbsp;userId;<br>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;String&nbsp;name;<br>&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;Date&nbsp;birthday;<br><br>　　//以下是针对以上属性的getter/setter，一般可以用IDE工具生成&nbsp;&nbsp;&nbsp;&nbsp;<br>public&nbsp;int&nbsp;getUserId()&nbsp;{&nbsp;return&nbsp;userId;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setUserId(int&nbsp;value)&nbsp;{&nbsp;userId&nbsp;=&nbsp;value;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;getName()&nbsp;{&nbsp;return&nbsp;name;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setName(String&nbsp;value)&nbsp;{&nbsp;name&nbsp;=&nbsp;value;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Date&nbsp;getBirthday()&nbsp;{&nbsp;return&nbsp;birthday;&nbsp;}<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;void&nbsp;setBirthday(Date&nbsp;value)&nbsp;{&nbsp;birthday&nbsp;=&nbsp;value};<br><br>&nbsp;&nbsp;&nbsp;&nbsp;//&#8230;<br>}<br><br>这样，一个比较规范的数据类包装就算完成了。<br>另外，我们知道，面向对象概念中，一个属性可以是另一个对象，也就是说，对象之间是存在着引用关系的，这种关系还分为一对一、一对多、多对多等几种情况。从一个既定对象出发，其某个属性可以是另一个对象，也可以是包含另一组对象的集合。那么，在我们的数据包装里面，当然最好也能方便地处理对象之间的关系。假定现在我们又有一个数据类Group：<br>public&nbsp;class&nbsp;Group&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;int&nbsp;grouId;<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;groupName；<br>&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Set&nbsp;users;&nbsp;//set&nbsp;of&nbsp;User<br>}<br>这里为了简单表明含义，暂不采用getter/setter。<br>而User对所属的Group有一个引用：<br>public&nbsp;Group&nbsp;belongTo;<br>在这里，User.belongTo和Group.users就是一个一对多的关系。<br>在我们的数据类中，如何才能实现数据库的存取呢？就算是不考虑Group.users这个反向关系，光是User.belongTo就是一件头疼的事。如果我们在取出一个User对象时同时将其Group对象也取出来，可以保证不会在访问某个用户的组时得到一个null。不过这样有几个缺点：<br>1.&nbsp;&nbsp;&nbsp;&nbsp;数据类的存取处理（JDBC）变得复杂，需要执行很多SQL读取才行，有时候只需要访问User的基本属性时浪费时间和资源；尤其是对集合型属性的预读取，更加可怕<br>2.&nbsp;&nbsp;&nbsp;&nbsp;如果按这个逻辑，双向的关系处理变得危险，很容易陷入死循环，如果要避免，必须在类代码中加入一些特别的机制，也是很麻烦的事<br>3.&nbsp;&nbsp;&nbsp;&nbsp;如果对象之间的关系是更复杂的情况下，比如三个、四个对象之间互相关联，那就是一场噩梦，对代码的编写和维护都异常艰难<br><br>于是，很多开发人员自然而然地退后一步，在User类中只保留一个groupId，并不保存Group对象，这样，可以将User.belongTo属性变成int类型，而另外写一个getter方法：<br>public&nbsp;Group&nbsp;getBelongTo()&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Group.findById(belongTo);<br>}<br><br>而在Group类中，干脆将users属性去掉，只保留一个方法：<br>public&nbsp;Set&nbsp;getUsers()&nbsp;{<br>&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;HashSet(User.findBy(&#8220;select&nbsp;&#8230;&nbsp;from&nbsp;USER&nbsp;where&nbsp;BELONG_TO=?&#8221;,new&nbsp;Object[]{&nbsp;new&nbsp;Integer(groupId)&nbsp;}));<br>}<br>也许细心一点的读者已经看出来了，这里的几个方法都没有将SQLException捕捉，也没有在方法中声明，也就是说是有语法错误的，因为SQLException不是一个RuntimeException。不错，确实是这样，不过我们这里为了简单明了起见，省掉这些处理，以更直接清楚地表达意思。<br><br>这样，实际上，我们的对象关系包装已经名存实亡，在类的内部有很多用于访问所引用对象的复杂代码，这些已经违背了我们将对象关系保持的初衷。有些开发人员甚至不在类中保留访问关系对象的方法，而是在客户调用时再去访问另一对象类的读取方法，如：<br>&#8230;<br>User&nbsp;user&nbsp;=&nbsp;User.getById(&#8230;);<br>//对user对象进行一些访问，如显示其姓名等等<br>Group&nbsp;group&nbsp;=&nbsp;Group.findById(user.belongTo);<br>//对group对象进行一些访问，如显示组名等等<br>&#8230;<br><br>在这样的代码里，实际上我们已经从根本上退回了关系数据库的出发点，这与直接访问数据表有多大区别呢？只不过是在表上面套了一层貌似面向对象的皮而已。不幸的是，这种方式还存在于很多应用之中。<br><br>从前面提到的这些面向对象包装的细节问题，我们可以看到这种传统包装方式的一些主要的缺陷：<br>
                        <li>3.1.1.1&nbsp;&nbsp;&nbsp;&nbsp;数据库命名与对象设计命名的一致性问题<br>很多时候，我们兴致勃勃地设计好一个类图，并且经过评审之后，开始对它进行数据库包装，这时候，发现有些属性名在具体的数据库中与该数据库的关键字冲突，不能用作表名或字段名，必须在数据表设计时采用另外的名称，或者很麻烦地加上引号来使用。于是，写数据库处理代码的人有意见了，他必须很清楚地记得一个属性在类中是什么属性名，在表中又是什么字段名，在编写的类逐渐增多后，尤其是一个类经过历次变动之后，或者经过很长时间又需要改动，并去处理这些JDBC代码时，代码维护人员简单要发疯了！<br>
                        <li>3.1.1.2&nbsp;&nbsp;&nbsp;&nbsp;对象的查询仍局限于SQL这一点也是这种简单的包装方法最不能摆脱关系数据库的地方。上面也已经说过，一些命名冲突带来了很多维护工作量，代码中必须还保留数据表的命名体系，而不是对象类的命名体系。这将使调用人员仍需要清楚记得两套命名体系，无论时间经过多久，或者开发人员是否有流动。<br>此外，对于普遍需要用到的连表查询，也给应用开发带来困难，这些地方仍不能突破SQL的限制。<br>
                        <li>3.1.1.3&nbsp;&nbsp;&nbsp;&nbsp;SQL资源占用多<br>在处理对象集合访问或者处理集合类型属性时，往往我们只能在同一个Connection中处理一切事务，这就要求一次性地将集合中的对象全部读入，如果集合很大的话，容易造成数据库拥塞，使得性能大打折扣，适得其反。这方面的优化也是很多开发人员一直在努力改进的。<br>
                        <li>3.1.1.4&nbsp;&nbsp;&nbsp;&nbsp;对象关系处理复杂<br>前面提过，对象之间的关系处理上，普通的包装技术是一种表面上的处理，在访问时调用者仍需要用大量的代码进行处理，并且，这还只是读取，在写入关系属性时会有更多的细节问题需要处理。<br>
                        <li>3.1.1.5&nbsp;&nbsp;&nbsp;&nbsp;面向对象特色只能应用一小部分<br>面向对象的包装到前面所说的为止，都还只是很基本的处理，而面向对象的精华：继承和多态，在这里得不到任何帮助。我们放弃了很多合理的设计来迁就数据库的包装。<br><br>以上就是基本数据包装的主要缺陷，还有更多的小问题也需要额外的处理。<br>不过，有责任心的开发人员当然不会就此善罢甘休，他们冥思苦想，可能会用更好的方式来实现对象之间关系的处理，而且还会加入一些延迟访问的机制，将对象之间的引用在需要用的时候才去连接数据库取数据，另外，在类的继承上，他们也试图去在数据库包装上得到体现。<br>值得感谢的是，一些富有经验的团队在经历若干改进之后，毫不吝惜将他们的成果贡献出来，并将其独立化，成为可复用的组件。这也就是后来出现的对象包装产品，包括商用的和免费的。<br>
                        <h5>3.1.2&nbsp;&nbsp;&nbsp;&nbsp;产品化包装中间件</h5>
                        <br>面向对象的包装产品化后，逐步推广开来，称作关系/对象映射：O/R&nbsp;Mapping。并且，在产品化的过程中，产品提供者在产品中逐渐提供了更多的功能。先是一些自动命名转换器得以应用，将客户代码中的类名、属性名在内部处理的时候自动地转换到对应的数据库结构命名空间上，这样，应用开发的时候不再关心具体的数据库结构，不再需要记忆不同地命名体系，只需要一心一意地根据类图来进行开发。在此之后，这些O/R&nbsp;Mapping产品的开发团队又向前迈了一大步：引入了词法分析器，提供面向对象的查询语言！很多对象关系的查询使应用开发变得非常方便，使O/R&nbsp;Mapping产品上了一个新的台阶。<br>
                        <li>3.1.2.1&nbsp;&nbsp;&nbsp;&nbsp;TopLink<br>TopLink是一个非常早期的产品，最初面向C++，后来也实现了Java的映射。TopLink性能优异，功能强大，并且提供了独特的查询过滤器机制，以及对关系的处理和查询都非常有效，于是，TopLink逐渐从商用化O/R&nbsp;Mapping产品中胜出，成为市场上的最出色的映射产品。也正因为这一点，最大的关系数据库厂商Oracle将其收购，成为提供最强数据库和最强对象映射中间件的厂商。<br>
                        <li>3.1.2.2&nbsp;&nbsp;&nbsp;&nbsp;Castor、Hibernate<br>TopLink虽然强大，但太强大的东西免不了得意忘形，TopLink开始将用户锁死到自己的产品上，查询方式是最突出的。它的查询体系含有很多别扭的概念（在我看来是如此），但为达到一般O/R产品不能达到的功能，开发者只能接受这些。慢慢地，也产生积怨，再加上其高昂的价格，让很多新老用户望而却步。于是，免费的产品开始崛起。<br>免费的O/R&nbsp;Mapping工具有很多种，这里只提其中最有影响力的两种：Castor和Hibernate。<br>Castor是Exolab组织开发的面向Java的包装工具，它最大的特色就是实现了大部分的ODMG&nbsp;OQL规范，在查询上，可以象完全使用一个对象数据库一样类图进行查询（后面会有介绍）。它的原理是通过Java反射API去实现属性的设置和读取。不过由于各种原因，Castor后来的版本更新越来越慢，最终停步在1.0之前，成为至今未出到1.0正式版的O/R&nbsp;Mapping产品。不管怎么样，它还是一个相当不错的产品。<br>Hibernate是一个现在很火热的O/R&nbsp;Mapping产品，目前已经出到2.0版，它功能一样强大，同样使用Java反射API进行对象的设置，但它的查询语言就是一套比较独特的体系，这一点有点类似TopLink，但Hibernate更具有亲和力，对关系的查询更方便，只不过比起Castor来，在方便性和规范性上还是稍逊一筹。就目前状况而言，Hibernate的用户量和技术支持要强一些。<br>
                        <h4>3.2&nbsp;&nbsp;&nbsp;&nbsp;面向对象的数据库查询</h4>
                        <br>在对数据库进行面向对象研究的过程中，软件世界的开发人员和设计人员们发现：对数据库能够进行对象化的查询，才是对数据库进行彻底的面向对象化。这体现在我们使用一种全新的数据库查询语言，能够很简洁易懂地对数据库中的对象进行查询。一个典型的例子如下：<br>假设我们已经有前面提到的两个数据类：User和Group，它们之间有一对多的关系：User.belongTo和Group.users。在数据库中已经存在很多这两个类的实例，以及相互之间的关系。我们可以使用下面的对象式查询语言来查询符合条件的User对象：<br>select&nbsp;*&nbsp;from&nbsp;User&nbsp;where&nbsp;User.belongTo.name=&#8217;GROUP1&#8217;<br>或者<br>select&nbsp;userId,name&nbsp;from&nbsp;User&nbsp;where&nbsp;User.belongTo.name=&#8217;GROUP2&#8217;<br>等等。从中我们可以看出，通过使用面向对象中的成员属性指定符&#8220;.&#8221;，可以让我们达到SQL中的连表的效果，实际上，第一个句查询的SQL等价版本是：<br>select&nbsp;a.*&nbsp;from&nbsp;USER&nbsp;a,&nbsp;GROUP&nbsp;b<br>where&nbsp;a.BELONG_TO&nbsp;=&nbsp;b.GROUP_ID<br>&nbsp;&nbsp;and&nbsp;b.NAME&nbsp;=&nbsp;&#8216;GROUP1&#8217;<br><br>由此可见，对象式的查询语言，比起实现同样功能的SQL语言来说，简单了很多，意义也更明确，更符合使用者的思维习惯。在类图比较复杂、查询涉及的类又比较多的时候，这种新型的查询语言体现出绝对的优势。<br>
                        <h5>3.2.1&nbsp;&nbsp;&nbsp;&nbsp;ODMG，OQL，Java&nbsp;Binding</h5>
                        <br>在面向对象式查询语言的研究过程中，开发人员们逐渐实现了相似的查询语言，然后互想取长补短，最终在ODMG组织（www.odmg.org）的统一下，形成了规范化的语言：ODMG&nbsp;OQL，这是一种完全面向对象的数据库查询语言，语法与前面提到的类似，不过考虑了更广泛的情况，语句更加简洁而严谨。<br>OQL并不是针对某种语言的，它可以被应用到很多种开发语言中，它不象SQL那样只是纯字符串式的查询语句，因为面向对象查询中还必须提供相关类的信息，所以OQL需要在编程语言中实现一些特定的API。<br>目前，ODMG的OQL已经被规范化地应用到SmallTalk、Java、C++这些面向对象的程序设计语言当中，在ODMG的规范中，这几个模块被称作SmallTalk&nbsp;Binding、Java&nbsp;Binding和C++&nbsp;Binding。<br>不过，由于历史原因，ODMG并没有象想象中地那样得到广泛应用，现有的十几个面向对象数据库中，采用ODMG&nbsp;OQL规范的少之又少，目前也只有FastObjeccts、Ozone这些产品采纳了这个规范，而象Versant这样的大厂商还没有采取OQL来查询数据库，而是自己定义了自己的一套API，称作VQL（Versant&nbsp;Query&nbsp;Lanaguage）。<br>在JDO之前的O/R&nbsp;Mapping产品中，也有一些产品使用OQL（有时候是其子集），比如Castor、Apache的Jakarta小组开发的OJB等等。<br>
                        <h5>3.2.2&nbsp;&nbsp;&nbsp;&nbsp;第三方协议</h5>
                        <br>软件世界是一个多姿多彩的世界，总有那么一些好事之士不断地冒出新奇的想法。还有一些开发面向对象数据库的组织制定了自己的一套对象式数据库查询语言，自己的规范。<br>不过这些规范相对来说，影响力小得多。比起ODMG来，可以说应用范围太小，更不用说与SQL这样广泛应用的标准进行比较了。<br>
                        <h5>3.2.3&nbsp;&nbsp;&nbsp;&nbsp;EJBQL</h5>
                        <br>Sun为了使Java应用在企业级数据库应用中，不遗余力地推广J2EE，在2001年的时候，推出了EJB2.0规范，其中包含了富有特色的面向CMP方式的EntityBean的查询语言：EJBQL，功能类似于ODMG&nbsp;OQL，只不过只能在EJB发布时静态地存在于应用描述符中，不能在程序中动态地使用。这是EJBQL最大的弱点，也许EJB3.0规范会将其动态化，但到了那一天，世界多半已经不是现在的样子了。<br>
                        <h5>3.2.4&nbsp;&nbsp;&nbsp;&nbsp;JDO</h5>
                        <br>JDO中有最近规定的一个对象式查询语言规范，称作JDOQL，比起OQL来，JDOQL将查询语言中的很多元素与Java语言紧密地结合在一起，有的人觉得麻烦，有些人觉得规范，评论各不相同。从笔者个人的角度来看，这样有利于没写过数据库应用、没用过SQL的新手很快地习惯JDOQL，但实际上，有多少人会在没写过SQL，没了解过关系数据库的情况下去用JDO写数据库应用呢？毕竟市场说明了一切。个人认为，JDO中对数据库对象的查询多少显得有些累赘，如果能更简化一点，那将更吸引使用传统SQL的开发人员。<br>
                        <h3>4&nbsp;&nbsp;&nbsp;&nbsp;JDO历程与主要产品</h3>
                        <br>说起JDO，其来由还有一段特殊的背景。Java语言在JDK1.1达到比较实用的目的后，企业级数据库应用也正是软件开发市场中的重要组成部分，Sun看到这一点后，也希望通过Java这个强大的武器在数据库开发市场攻占市场份额。JDK1.2推出后，Sun同时推出了面向企业应用的EJB，对基于java的中间件服务器框架进行了规范化定义，这就是J2EE。不过在JDK1.2时，Java的速度还是不能与传统的C/C++和Delphi这样一些应用开发语言相比。为了防止业界对Java的激情因此而消退，Sun宣布将在JDK中加入强大的虚拟机技术HotSpot，其中包含更先进的垃圾收集算法和更优化的Java字节代码再编译技术（相当于JIT，Java即时编译技术）。HotSpot引起了Java关注者的极大兴趣，但Sun的HotSpot一拖再拖，最后包含在JDK1.3中出来时，性能也没有象预期的那样好，比起C++编译生成的代码来还是有一段距离。<br>这个时候，大家开始对Sun心存怀疑，而Sun深知这一点，于是将公众的注意力赶紧转移到EJB上，从EJB1.0到EJB1.1，再到EJB2.0，业界又开始关注J2EE中间件技术上来。很快，开发人同发现用EJB来编写数据库应用还是有很大的难度，虽然在分布式技术上EJB确实有很大的价值。在这个时候，Sun决定推出JDO技术作为轻量级的Java数据库访问规范，而这一点也受到很多传统O/R&nbsp;Mapping市场的欢迎。为了与传统O/R&nbsp;Mapping有所区别，Sun一开始就高姿态地将JDO定位成不只是面向关系数据库的Java规范，而是针对所有的存储技术，包括面向对象数据库和其它类型的存储体系（如文件），就象EJB&nbsp;EntityBean一样，虽然。就笔者的角度，这个做法使第一版的JDO抛弃了很多传统O/R&nbsp;Mapping提供的面向关系数据库的功能，可以算是一个失策。<br>
                        <h4>4.1&nbsp;&nbsp;&nbsp;&nbsp;规范提出、JSR</h4>
                        <br>JDO最早是由Sun召集众多的O/R&nbsp;Mapping开发团队集中起来共同提出的，首先是通过会议确定了JDO需要包括的内容，然后正式提出一个Java规范请求（JSR-12），正式开始了JDO规范的制定。下面是主要的进展里程碑。<br>JSR&nbsp;#000012&nbsp;approved&nbsp;in&nbsp;July&nbsp;1999<br>1999-8组建的专家小组：包括Sun、Apple、BEA、IBM、Oracle、SAP、WebGain等<br>2000-5&nbsp;完成公开评论草案<br>2000-6&nbsp;在JavaOne上引入<br>2001-3&nbsp;最终草案0.93<br>2001-5&nbsp;最终草案0.96公布<br>2001-6&nbsp;在JavaOne上启动<br>2001-11&nbsp;最终草案0.98<br>2002-4&nbsp;1.0版正式公布<br>2002-8&nbsp;1.0.1修正版<br>2003-8&nbsp;2.0规范启动<br>&#8230;<br>
                        <h4>4.2&nbsp;&nbsp;&nbsp;&nbsp;Oracle与JDO</h4>
                        <br>作为JDO专家组的重要成员，同时作为最大的关系数据库厂商的Oracle地位显然非同一般。在JDO规范中，Oracle也可说是立下汗马功劳，很多API的形成，Oracle都提供了很重要的参考意见，最终的投票Oracle也是毫不犹豫。<br>可是，世间的事总是变化莫测的，就在JDO1.0快出台之时，Oracle收购了TopLink，这一点使Oracle的身份变得特殊而复杂。TopLink是一个商业产品，是以商业利益为目标的，而Oracle也是追求利益最大化的典型商家，这一点与JDO的开放精神背道而驰。因此，我们看到后期Oracle对JDO的不积极态度，甚至在前一阵的JavaOne大会上有人从Oracle的角度非正式地攻击JDO。<br>
                        <h4>4.3&nbsp;&nbsp;&nbsp;&nbsp;主要产品以及各自特点</h4>
                        <br>在JDO规范制定的同时，出现了几个主要的JDO产品，有美国的基于对象数据库的FastObjects&nbsp;j1、法国的支持Versant对象数据库、文件数据库、主流RDBMS的LiDO、南非的JDOGenie、德国的JRelay等等，这些都是很不错的JDO产品。下面列举一下我对主要的几个产品的印象：<br>&nbsp;&nbsp;&nbsp;&nbsp;LiDO（法国LibeLis公司）<br>我对JDO的认识主要是通过LiDO这个产品，它在2002年3月的一份图文并茂的教程中简要解说了JDO的使用和优点。这个教程可以在这里下载：<a href="http://www.objectweb.org/conference/JDO.pdf"><u><font color=#0000ff>http://www.objectweb.org/conference/JDO.pdf</font></u></a>。LiDO的特色是大而全，支持文件型数据库、RDBMS、ODBMS，甚至是XML数据库。不过配置较麻烦。最新版本是2.0RC。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;KodoJDO（美国SolarMetrics公司）<br>Kodo是JDO的中流砥柱之一，在JDO1.0还未最后通过的时候，它就是一个比较成熟的产品了，其特点是注重性能和稳定性，目前最新版本是2.5.0，是客户最多的产品。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;JDOGenie（南非HemSphere公司）<br>这是目前我最推荐的产品，最新版本是1.4.7，性能也不错，稳定性还有待验证，但它有一个最大的特点：集成性好，最易学，其公司的CTO&nbsp;David&nbsp;Tinker也是一个善解人意的年轻人，采纳了很多网友的意见对产品进行改进，主要是在配置上非常方便，有一个专门的图形界面工具，可以进行配置、数据库生成、对象查询等等很实用的功能。<br>&nbsp;&nbsp;&nbsp;&nbsp;JRelay（德国ObjectIndustries公司）<br>这也是一个出现得比较早的产品，也有一个GUI工具用于配置，曾几何时，这个工具还是相对很方便的，但一年多过去了，好象没什么进展，最新版本是2.0，我试过一段时间，后来就没有再跟进了。&nbsp;<br>&nbsp;&nbsp;&nbsp;&nbsp;FrontierSuite&nbsp;for&nbsp;JDO&nbsp;（美国ObjectFrontier）<br>这个产品与JRelay、Kodo一起，可算是早期的JDO三个主要产品，它支持正向开发和反向开发（Reverse&nbsp;Engineer）。它的特色是反向工程（从表结构生成数据类）比较方便，与UML的结合也很强，不过真正运行起来的时候，配置复杂。<br>&nbsp;&nbsp;&nbsp;&nbsp;TJDO（一群跨国界的有志之士）<br>这是一个在Sun提供的参考产品（Reference&nbsp;Implementation）的基础上加入一些扩展功能而形成的一个免费产品，目前最新版本是2.0beta3，不过进展也缓慢，这个版本已经出现好几个月了没有进一步的更新。&nbsp;<br>
                        <h3>5&nbsp;&nbsp;&nbsp;&nbsp;目前状况与未来展望</h3>
                        <br>从2002年4月JDO1.0规范正式公布以来，各个产品层出不穷，从商业到免费的层次，都有不错的产品推出。象Kodo、Lido、JDOGenie等产品都已经比较成熟，可以考虑投入开发使用。在2002年8月，JDO又推出1.0.1修正版，修正了1.0版规范中的一些文字错误，以及轻微地改进了部分异常定义，不过改动都不大。从现在的情形来看，除了Kodo有一些大学的项目用到外，好象还没看到多少使用JDO作开发的应用。<br>JDO毕竟是一个新技术，从概念上到实际应用上对其掌握的用户还不多，而这些产品在配置、使用上的方便性易用性还有待大幅度改进，因此，真正用JDO来开发项目的用户还廖廖无几，至少我还不知道有哪些项目使用了JDO。我自己也尝试使用JDO来开发项目，但由于一些JDO1.0版本中还不够完善的一些硬伤（比如不支持关系数据库统计功能），使我对JDO仍处于观望阶段。<br>在八月中旬进行的JDO2.0规划会议中，来自各国的各个JDO产品厂商、JDO技术咨询公司、JDO研究机构的代表汇聚一堂，将各自收集到的用户对JDO2.0的需求总结起来，提出一个个的新的议题，并且确定了每个议题的JDO规范撰写负责人，比如高级fetchGroup特性由目前实现得最好的JDOGenie的CTO&nbsp;David&nbsp;Tinker负责，关于managed-relationship特性由Kodo的产品总监负责，用户要求最多的JDO对象与PersistenceManager的脱钩/重挂钩特性由Sun的Craig&nbsp;Russell亲自操刀，等等。<br>最具有吸引力的JDO2.0议题，笔者个人认为是专门为关系数据库设立的子规范JDO/R，这也是我一直以来最关心的，这将使目前JDBC的开发将可以被JDO完全取代，并且保证开发过程保持面向对象的特色。还有一些将一个类映射到多个表之类的特性也在规范化的列表上，这将有利于DBA在不影响应用开发的前提下根据需要更改数据表结构，实现更好的性能。类似的新特性还有很多，粗略地看，这些都规范化起来后，真不知道各个厂商还能做什么样的扩展特性，也许以后厂商之间拼的只能是技术支持服务和产品性能了，当然，最后还有价格的竞争。<br>说了这么多，我想大家关心的还是JDO2.0到底什么时候能出来，我们什么时候可以用上它，什么时候有中文版产品，价格到底如何。这些问题目前笔者还无法一一回答，只能根据笔者所掌握的信息初步解释一下。据前几天的JDO2.0启动大会上David&nbsp;Jordan的预期，JDO2.0正式版将在18个月后正式完成。那正式完成后厂商什么时候才能提供符合规范的产品呢？这个问题不用担心，因为规范在制定的过程中会不断地公布公众预览版（Public&nbsp;Review），这样，厂商可以先实现其中的功能，等规范正式完成后，也不会有太大的变化，厂商也不会需要太多时间来跟进最终规范。所以，我估计一年之后，我们就可以在JDO2.0上进行开发了。至于价格如何，1.0规范的产品初步印象是每个开发人员需要一个License，一个License大概2000美元。如果JDO2.0产品的价格还保持这么贵的话（至少对中国用户来说），我们也还有很多免费（如JPOX，TJDO）或半免费（如JCredo）产品可以选择。最后一个关于中文版的问题，有待于厂商对中国市场的考察，或者看看是否有国内的JDO产品了。不过，在JDO2.0规范制定的同时，我们可以先集众人之力将其普及，使广大的使用Java语言进行数据库开发的开发人员都来认识JDO，了解JDO，甚至将其用到项目开发之中。<br>也许，JDO的目标已经吸引了Java世界以外的人，微软发现了这一点，也立即计划在.NET体系中加入一个仿照JDO的中间件，具体是采用ObjectStore的产品，ObjectStore是一个同时做JDO和.NET-DO（姑且使用这个名称）的公司。<br><br>在这里，笔者可以大胆地预测，在未来的一两年内，JDO将在Java世界大放光彩！<br>
                        <h4>5.1&nbsp;&nbsp;&nbsp;&nbsp;一点花絮</h4>
                        <br>在2003年6月举行的JavaOne大会上，JDO备受瞩目，很多开发者或开发组织对其产生了极大的兴趣，在各大网站媒体上也频频曝光，大多对其评价不错，当然，也有一些负面的评价。<br>不过，网站上的报道也不可尽信，比如服务器领域的权威网站TheServerSide.com上介绍JavaOne大会第二天关于JDO的一次会议的报道就有误导之嫌，从报道的内容来看，好象会议用来答疑与交流的的最后五分钟全被一个好事者占据，这个人拼命鼓吹Oracle的TopLink解决方案和一些易用性的改进，从而攻击JDO的市场前景。后来，我就这一信息与参加会议的JDO专家组的David&nbsp;Jordan交流时，他纠正了我的错误理解，实际情形是：那个好事者是一个积极的JDO拥护者，他花了超过五分钟时间向大家揭露Oracle的TopLink改进实际上也是抄袭JDO的概念而进行的一些API改动！不过有一点是相同的，这个好事者占据了大家的提问时间，使这次会议在意犹未尽中结束。<br><br>&nbsp;&nbsp;&nbsp;&nbsp;本文的版权属于笔者本人，但欢迎转载，前提是注明出处和原作者。另外，欢迎在<a class=l2 href="http://www.javaresearch.org/expert.jsp?expert=sun2bin" target=_blank><u><font color=#0000ff>我的专栏</font></u></a>中查看我的另几篇文章，并提出宝贵意见！<br><br></li>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<br><br><a href="http://www.javazy.com/contentex/2007413143952.shtml">http://www.javazy.com/contentex/2007413143952.shtml</a>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39871.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-18 10:44 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39871.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]JDBC连接各种数据库经验总结</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39870.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Mon, 18 Feb 2008 02:43:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39870.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39870.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39870.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39870.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39870.html</trackback:ping><description><![CDATA[<div class=tit>JDBC连接各种数据库经验总结</div>
<div class=date>2007年12月04日 星期二 12:11</div>
<table style="TABLE-LAYOUT: fixed">
    <tbody>
        <tr>
            <td>
            <div class=cnt>Java数据库连接（JDBC）由一组用 Java 编程语言编写的类和接口组成。JDBC 为工具/数据库开发人员提供了一个标准的 API，使他们能够用纯Java API 来编写数据库应用程序。然而各个开发商的接口并不完全相同，所以开发环境的变化会带来一定的配置变化。本文主要集合了不同数据库的连接方式。<br>一、连接各种数据库方式速查表<br>下面罗列了各种数据库使用JDBC连接的方式，可以作为一个手册使用。<br>1、Oracle8/8i/9i数据库（thin模式）<br>Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();<br>String url="jdbc:oracle:thin:@localhost:1521:orcl"; //orcl为数据库的SID<br>String user="test";<br>String password="test";<br>Connection conn= DriverManager.getConnection(url,user,password);<br>2、DB2数据库<br>Class.forName("com.ibm.db2.jdbc.app.DB2Driver ").newInstance();<br>String url="jdbc:db2://localhost:5000/sample"; //sample为你的数据库名<br>String user="admin";<br>String password="";<br>Connection conn= DriverManager.getConnection(url,user,password);<br>3、Sql Server7.0/2000数据库<br>Class.forName("com.microsoft.jdbc.sqlserver.SQLServerDriver").newInstance();<br>String url="jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=mydb";<br>//mydb为数据库<br>String user="sa";<br>String password="";<br>Connection conn= DriverManager.getConnection(url,user,password);<br>4、Sybase数据库<br>Class.forName("com.sybase.jdbc.SybDriver").newInstance();<br>String url =" jdbc:sybase:Tds:localhost:5007/myDB";//myDB为你的数据库名<br>Properties sysProps = System.getProperties();<br>SysProps.put("user","userid");<br>SysProps.put("password","user_password");<br>Connection conn= DriverManager.getConnection(url, SysProps);<br>5、Informix数据库<br>Class.forName("com.informix.jdbc.IfxDriver").newInstance();<br>String url = "jdbc:informix-sqli://123.45.67.89:1533/myDB:INFORMIXSERVER=myserver;<br>user=testuser;password=testpassword"; //myDB为数据库名<br>Connection conn= DriverManager.getConnection(url);<br>6、MySQL数据库<br>Class.forName("org.gjt.mm.mysql.Driver").newInstance();<br>String url ="jdbc:mysql://localhost/myDB?user=soft&amp;password=soft1234&amp;useUnicode=true&amp;characterEncoding=8859_1"<br>//myDB为数据库名<br>Connection conn= DriverManager.getConnection(url);<br>7、PostgreSQL数据库<br>Class.forName("org.postgresql.Driver").newInstance();<br>String url ="jdbc:postgresql://localhost/myDB" //myDB为数据库名<br>String user="myuser";<br>String password="mypassword";<br>Connection conn= DriverManager.getConnection(url,user,password);<br>8、access数据库直连用ODBC的<br>Class.forName("sun.jdbc.odbc.JdbcOdbcDriver") ;<br>String url="jdbc:odbc:Driver={MicroSoft Access Driver (*.mdb)};DBQ="+application.getRealPath("/Data/ReportDemo.mdb");<br>Connection conn = DriverManager.getConnection(url,"","");<br>Statement stmtNew=conn.createStatement() ;<br>二、JDBC连接MySql方式<br>下面是使用JDBC连接MySql的一个小的教程<br>1、查找驱动程序<br>MySQL目前提供的java驱动程序为Connection/J，可以从MySQL官方网站下载，并找到mysql-connector-java-3.0.15-ga-bin.jar文件，此驱动程序为纯java驱动程序，不需做其他配置。<br>2、动态指定classpath<br>如果需要执行时动态指定classpath，就在执行时采用－cp方式。否则将上面的.jar文件加入到classpath环境变量中。<br>3、加载驱动程序<br>try{<br>Class.forName(com.mysql.jdbc.Driver);<br>System.out.println(Success loading Mysql Driver!);<br>}catch(Exception e)<br>{<br>System.out.println(Error loading Mysql Driver!);<br>e.printStackTrace();<br>}<br>4、设置连接的url<br>jdbc：mysql：//localhost/databasename[?pa=va][＆pa=va]<br>三、以下列出了在使用JDBC来连接Oracle数据库时可以使用的一些技巧<br>1、在客户端软件开发中使用Thin驱动程序<br>在开发Java软件方面，Oracle的数据库提供了四种类型的驱动程序，二种用于应用软件、applets、servlets等客户端软件，另外二种用于数据库中的Java存储过程等服务器端软件。在客户机端软件的开发中，我们可以选择OCI驱动程序或Thin驱动程序。OCI驱动程序利用Java本地化接口（JNI），通过Oracle客户端软件与数据库进行通讯。Thin驱动程序是纯Java驱动程序，它直接与数据库进行通讯。为了获得最高的性能，Oracle建议在客户端软件的开发中使用OCI驱动程序，这似乎是正确的。但我建议使用Thin驱动程序，因为通过多次测试发现，在通常情况下，Thin驱动程序的性能都超过了OCI驱动程序。<br>2、关闭自动提交功能，提高系统性能<br>在第一次建立与数据库的连接时，在缺省情况下，连接是在自动提交模式下的。为了获得更好的性能，可以通过调用带布尔值false参数的Connection类的setAutoCommit()方法关闭自动提交功能，如下所示：<br>conn.setAutoCommit(false);<br>值得注意的是，一旦关闭了自动提交功能，我们就需要通过调用Connection类的commit()和rollback()方法来人工的方式对事务进行管理。<br>3、在动态SQL或有时间限制的命令中使用Statement对象<br>在执行SQL命令时，我们有二种选择：可以使用PreparedStatement对象，也可以使用Statement对象。无论多少次地使用同一个SQL命令，PreparedStatement都只对它解析和编译一次。当使用Statement对象时，每次执行一个SQL命令时，都会对它进行解析和编译。这可能会使你认为，使用PreparedStatement对象比使用Statement对象的速度更快。然而，我进行的测试表明，在客户端软件中，情况并非如此。因此，在有时间限制的SQL操作中，除非成批地处理SQL命令，我们应当考虑使用Statement对象。<br>此外，使用Statement对象也使得编写动态SQL命令更加简单，因为我们可以将字符串连接在一起，建立一个有效的SQL命令。因此，我认为，Statement对象可以使动态SQL命令的创建和执行变得更加简单。<br>4、利用helper函数对动态SQL命令进行格式化<br>在创建使用Statement对象执行的动态SQL命令时，我们需要处理一些格式化方面的问题。例如，如果我们想创建一个将名字O'Reilly插入表中的SQL命令，则必须使用二个相连的"''"号替换O'Reilly中的"'"号。完成这些工作的最好的方法是创建一个完成替换操作的helper方法，然后在连接字符串心服用公式表达一个SQL命令时，使用创建的helper方法。与此类似的是，我们可以让helper方法接受一个Date型的值，然后让它输出基于Oracle的to_date()函数的字符串表达式。<br>5、利用PreparedStatement对象提高数据库的总体效率<br>在使用PreparedStatement对象执行SQL命令时，命令被数据库进行解析和编译，然后被放到命令缓冲区。然后，每当执行同一个PreparedStatement对象时，它就会被再解析一次，但不会被再次编译。在缓冲区中可以发现预编译的命令，并且可以重新使用。在有大量用户的企业级应用软件中，经常会重复执行相同的SQL命令，使用PreparedStatement对象带来的编译次数的减少能够提高数据库的总体性能。如果不是在客户端创建、预备、执行PreparedStatement任务需要的时间长于Statement任务，我会建议在除动态SQL命令之外的所有情况下使用PreparedStatement对象。<br>6、在成批处理重复的插入或更新操作中使用PreparedStatement对象<br>如果成批地处理插入和更新操作，就能够显著地减少它们所需要的时间。Oracle提供的Statement和 CallableStatement并不真正地支持批处理，只有PreparedStatement对象才真正地支持批处理。我们可以使用addBatch()和executeBatch()方法选择标准的JDBC批处理，或者通过利用PreparedStatement对象的setExecuteBatch()方法和标准的executeUpdate()方法选择速度更快的Oracle专有的方法。要使用Oracle专有的批处理机制，可以以如下所示的方式调用setExecuteBatch()：<br>PreparedStatement pstmt3D null;<br>try {<br>((OraclePreparedStatement)pstmt).setExecuteBatch(30);<br>...<br>pstmt.executeUpdate();<br>}<br>调用setExecuteBatch()时指定的值是一个上限，当达到该值时，就会自动地引发SQL命令执行，标准的executeUpdate()方法就会被作为批处理送到数据库中。我们可以通过调用PreparedStatement类的sendBatch()方法随时传输批处理任务。<br>7、使用Oracle locator方法插入、更新大对象（LOB）<br>Oracle的PreparedStatement类不完全支持BLOB和CLOB等大对象的处理，尤其是Thin驱动程序不支持利用PreparedStatement对象的setObject()和setBinaryStream()方法设置BLOB的值，也不支持利用setCharacterStream()方法设置CLOB的值。只有locator本身中的方法才能够从数据库中获取LOB类型的值。可以使用PreparedStatement对象插入或更新LOB，但需要使用locator才能获取LOB的值。由于存在这二个问题，因此，我建议使用locator的方法来插入、更新或获取LOB的值。<br>8、使用SQL92语法调用存储过程<br>在调用存储过程时，我们可以使用SQL92或Oracle PL/SQL，由于使用Oracle PL/SQL并没有什么实际的好处，而且会给以后维护你的应用程序的开发人员带来麻烦，因此，我建议在调用存储过程时使用SQL92。<br>9、使用Object SQL将对象模式转移到数据库中<br>既然可以将Oracle的数据库作为一种面向对象的数据库来使用，就可以考虑将应用程序中的面向对象模式转到数据库中。目前的方法是创建Java bean作为伪装的数据库对象，将它们的属性映射到关系表中，然后在这些bean中添加方法。尽管这样作在Java中没有什么问题，但由于操作都是在数据库之外进行的，因此其他访问数据库的应用软件无法利用对象模式。如果利用Oracle的面向对象的技术，可以通过创建一个新的数据库对象类型在数据库中模仿其数据和操作，然后使用JPublisher等工具生成自己的Java bean类。如果使用这种方式，不但Java应用程序可以使用应用软件的对象模式，其他需要共享你的应用中的数据和操作的应用软件也可以使用应用软件中的对象模式。<br>10、利用SQL完成数据库内的操作<br>我要向大家介绍的最重要的经验是充分利用SQL的面向集合的方法来解决数据库处理需求，而不是使用Java等过程化的编程语言。<br>如果编程人员要在一个表中查找许多行，结果中的每个行都会查找其他表中的数据，最后，编程人员创建了独立的UPDATE命令来成批地更新第一个表中的数据。与此类似的任务可以通过在set子句中使用多列子查询而在一个UPDATE命令中完成。当能够在单一的SQL命令中完成任务，何必要让数据在网上流来流去的？我建议用户认真学习如何最大限度地发挥SQL的功能。 <br>11 JNDI<br>&lt;Resource name="jdbc/test" auth="Container" type="javax.sql.DataSource"/&gt; <br>&lt;ResourceParams name="jdbc/test"&gt; <br>&lt;parameter&gt; <br>&lt;name&gt;username&lt;/name&gt; <br>&lt;value&gt;system&lt;/value&gt; <br>&lt;/parameter&gt; <br>&lt;parameter&gt; <br>&lt;name&gt;password&lt;/name&gt; <br>&lt;value&gt;manager&lt;/value&gt; <br>&lt;/parameter&gt; <br>&lt;parameter&gt; <br>&lt;name&gt;driverClassName&lt;/name&gt; <br>&lt;value&gt;oracle.jdbc.driver.OracleDriver&lt;/value&gt; <br>&lt;/parameter&gt; <br>&lt;parameter&gt; <br>&lt;name&gt;url&lt;/name&gt; <br>&lt;value&gt;jdbc:oracle:thin:@192.168.0.27:1521:titan&lt;/value&gt; <br>&lt;/parameter&gt; <br>&lt;/ResourceParams&gt;<br>try{<br>InitialContext ctx=new InitialContext();<br>Object o = ctx.lookup("java:comp/env/hibernate");<br>out.print("class="+o.getClass().getName());<br>DataSource ds=(javax.sql.DataSource)o;<br>}catch(NamingException e){<br>&nbsp;&nbsp;&nbsp;&nbsp; e.printSatckTrace;<br>}</div>
            </td>
        </tr>
    </tbody>
</table>
<br><br><a href="http://hi.baidu.com/29163077/blog/item/c0a6f560a4c25047eaf8f81c.html">http://hi.baidu.com/29163077/blog/item/c0a6f560a4c25047eaf8f81c.html</a>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39870.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-18 10:43 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39870.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]数据库知识总结</title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39868.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Mon, 18 Feb 2008 02:41:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39868.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39868.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39868.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39868.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39868.html</trackback:ping><description><![CDATA[<div class=tit>数据库知识总结</div>
<div class=date>2008-01-10 15:35</div>
<table style="TABLE-LAYOUT: fixed">
    <tbody>
        <tr>
            <td>
            <div class=cnt>一．用SqlConnection连接SQL Server<br><br>1..加入命名空间<br><br>using System.Data.SqlClient;<br><br>2.连接数据库<br><br>SqlConnection myConnection = new SqlConnection();<br>myConnection.ConnectionString = "user id=sa;password=sinofindb;initial catalog=test;data source=127.0.0.1;Connect Timeout=30";<br>myConnection.Open();<br><br><br><br>改进（更通用）的方法：<br><br>string MySqlConnection="user id=sa;password=sinofindb;Database =test;data source=127.0.0.1;Connect Timeout=30";<br>SqlConnection myConnection = new SqlConnection(MySqlConnection);<br>myConnection.Open();<br><br><br><br>二。用OleDbConnection连接<br><br><br>1.加入命名空间<br><br>using System.Data.OleDb;<br><br><br>2.连接sql server<br><br>string MySqlConnection="Provider=SQLOLEDB;Data Source=localhost;Initial Catalog=test;Integrated Security=SSPI;";<br><br>SqlConnection myConnection = new SqlConnection(MySqlConnection);<br>myConnection.Open();<br><br><br><br>3.连接Access(可通过建立.udl文件获得字符串)<br><br>string MySqlConnection="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\db2000.mdb;<br><br>Persist Security Info=False;<br><br><br>4.连接Oracle(也可通过OracleConnection连接)<br><br>string MySqlConnection="Provider=MSDAORA;Data Source=db; user id=sa;password=sinofindb";<br><br><br><br>三.创建Command对象<br><br><br>1．SqlCommand 构造函数<br><br>①初始化 SqlCommand 类的新实例。public SqlCommand();<br><br>SqlCommand myCommand = new SqlCommand();<br><br><br><br>②初始化具有查询文本的 SqlCommand 类的新实例。public SqlCommand(string);<br><br>String mySelectQuery = "SELECT * FROM mindata";<br>SqlCommand myCommand = new SqlCommand(mySelectQuery);<br>③初始化具有查询文本和 SqlConnection 的SqlCommand类实例。<br><br>Public SqlCommand(string, SqlConnection);<br><br>String mySelectQuery = "SELECT * FROM mindata";<br>string myConnectString = "user id=sa;password=;database=test;server=mySQLServer";<br>SqlConnection myConnection = new SqlConnection(myConnectString);<br>SqlCommand myCommand = new SqlCommand(mySelectQuery,myConnection);<br><br><br>④初始化具有查询文本、SqlConnection 和 Transaction 的 SqlCommand 类实例。<br><br>public SqlCommand(string, SqlConnection, SqlTransaction);<br><br>SqlTransaction myTrans = myConnection.BeginTransaction();<br>String mySelectQuery = "SELECT * FROM mindata";<br>string myConnectString = "user id=sa;password=;database=test;server=mySQLServer";<br>SqlConnection myConnection = new SqlConnection(myConnectString);<br>SqlCommand myCommand = new SqlCommand(mySelectQuery,myConnection, myTrans);<br><br><br>2.建立SqlCommand与SqlConnection的关联。<br><br>myCommand.Connection = myConnection;<br><br>或者：SqlCommand myCommand = myConnection.CreateCommand;<br><br><br><br>3．设置SqlCommand的查询文本。<br><br>myCommand.CommandText = "SELECT * FROM mindata";<br><br>或者第2种构造：SqlCommand myCommand = new SqlCommand(mySelectQuery);<br><br>给SqlCommand对象提供两个查询字符串，每个查询字符串访问不同的表，返回不同的结果集。<br><br>两个查询语句用分号分隔。<br><br><br><br>4. 执行命令。<br><br>ExecuteReader<br>返回一行或多行<br><br>ExecuteNonQuery<br>对 Connection 执行 Transact-SQL 语句并返回受影响的行数(int)<br><br>ExecuteScalar<br>返回单个值(如一个聚合值).返回结果集中第一行的第一列。忽略额外的列或行<br><br>ExecuteXmlReader<br>将 CommandText 发送到 Connection 并生成一个 XmlReader 对象。<br><br><br><br><br>SqlDataReader myReader = myCommand.ExecuteReader();<br><br>或SqlDataReader myReader = myCommand.ExecuteReader(CommandBehavior.CloseConnection);<br><br>&nbsp;&nbsp;&nbsp; while(myReader.Read()) //循环读取数据<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(myReader.GetString(0));// 获取指定列的字符串形式的值<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine(myReader. GetValue(1));// 获取以本机格式表示的指定列的值<br>&nbsp;&nbsp;&nbsp;&nbsp; }<br><br><br>CommandText = "select count(*) as NumberOfRegions from region";<br>Int count = (int) myCommand.ExecuteScalar();<br><br><br><br>关于OleDbCommand对象的使用。<br><br><br><br>四．DataReader的使用<br><br>1．遍历结果集<br><br>while (myReader.Read())<br>&nbsp;&nbsp; Console.WriteLine("\t{0}\t{1}", myReader.GetInt32(0), myReader.GetString(1));<br>myReader.Close();<br><br><br>2．使用序数索引器。<br><br>while (myReader.Read())<br>&nbsp;&nbsp; Console.WriteLine("\t{0}\t{1}", myReader[0].ToString(), myReader[1].ToString());<br>myReader.Close();<br><br><br>3．使用列名索引器。<br><br>while (myReader.Read())<br>&nbsp;&nbsp; Console.WriteLine("\t{0}\t{1}", myReader["code].ToString(), myReader["name"].ToString());<br>myReader.Close();<br><br><br><br>4.使用类型访问器。<br><br>public char GetChar(int i); 获取指定列的单个字符串形式的值<br>public DateTime GetDateTime(int i); 获取指定列的 DateTime 对象形式的值<br>public short GetInt16(int i); 获取指定列的 16 位有符号整数形式的[C#]<br>public string GetString(int i); 获取指定列的字符串形式的值<br><br><br>5．得到列信息。<br><br>myReader.FieldCount&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 获取当前行中的列数<br>myReader.GetFieldType(序号)&nbsp;&nbsp;&nbsp; 获取是对象的数据类型的 Type<br>myReader.GetDataTypeName(序号)&nbsp;&nbsp; 获取源数据类型的名称<br>myReader.GetName(序号)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 获取指定列的名称<br>myReader.GetOrdinal(序号)&nbsp;&nbsp;&nbsp; 在给定列名称的情况下获取列序号<br><br><br>6.得到数据表的信息。<br><br>myReader.GetSchemaTable()&nbsp;&nbsp;&nbsp; 返回一个 DataTable<br><br><br>7．操作多个结果集。<br>myReader.NextResult()&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 使数据读取器前进到下一个结果集<br>do<br>{<br>&nbsp;&nbsp; while (myReader.Read())<br>&nbsp;&nbsp; Console.WriteLine("\t{0}\t{1}", myReader.GetInt32(0), myReader.GetString(1));<br>}<br>while(myReader.NextResult());<br><br><br>五．DataAdapter<br><br><br>1.创建SqlDataAdapter<br>初始化 SqlDataAdapter 类的新实例。<br>public SqlDataAdapter();<br>将指定的 SqlCommand 作为SelectCommand 属性，初始化 SqlDataAdapter 类的新实例。<br>public SqlDataAdapter(SqlCommand);<br>用 selectcommand字符串 和 SqlConnection对象初始化SqlDataAdapter 类的新实例。<br>public SqlDataAdapter(string, SqlConnection);<br>用 selectcommand字符串 和 一个连接字符串 初始化SqlDataAdapter 类的新实例。<br>public SqlDataAdapter(string, string);<br><br><br>2．DataAdapter和SqlConnection，SqlCommand建立关联。<br>&nbsp;&nbsp; 1．DataAdapter在构造参数时建立<br>&nbsp;&nbsp; 2．SqlDataAdapter adapter = new SqlDataAdapter();<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; adapter.SelectCommand = new SqlCommand(query, conn);<br><br><br>3．DataAdapter.Fill（）方法。<br><br>在 DataSet 中添加或刷新行以匹配使用 DataSet 名称的数据源中的行，并创建一个名为&#8220;Table&#8221;的 DataTable。<br>public override int Fill(DataSet);<br>在 DataSet 中添加或刷新行以匹配使用 DataSet 和 DataTable 名称的数据源中的行。<br>public int Fill(DataSet, string);<br><br><br>在 DataSet 的指定范围中添加或刷新行以匹配使用 DataSet 和 DataTable 名称的数据源中的行。<br><br>public int Fill(DataSet, int, int, string);<br><br><br>在 DataTable 中添加或刷新行以匹配使用 DataTable 名称的数据源中的行。<br>public int Fill(DataTable);<br><br><br>在 DataTable 中添加或刷新行以匹配使用指定 DataTable 和 IDataReader 名称的数据源中的行。<br>protected virtual int Fill(DataTable, IDataReader);<br><br>在 DataTable 中添加或刷新行以匹配使用 DataTable 名称、指定的 SQL SELECT 语句和 CommandBehavior 的数据源中的行。<br>protected virtual int Fill(DataTable, IDbCommand, CommandBehavior);<br><br><br>六．DataTable 类<br><br>七．DataColumn 类<br><br>八．DataRow 类<br><br><br>九．DataSet 类<br>1．创建DataSet 对象<br><br>初始化 DataSet 类的新实例。<br>public DataSet();<br><br>用给定名称初始化 DataSet 类的新实例。<br>public DataSet(string);<br><br><br>2．用DataAdapter填充DataSet<br><br>&nbsp;&nbsp;&nbsp; DataSet myds=new DataSet();<br>adapter.fill(myds)<br>adapter.fill(myds,&#8221;表名&#8221;);&nbsp;&nbsp; 用一个表去填充DataSet.<br><br><br><br>十. DataTableCollection 类。&nbsp;&nbsp;&nbsp;&nbsp; 表示 DataSet 的表的集合。<br><br>DataTableCollection dtc = ds.Tables;<br>DataTable table = dtc[&#8220;表名&#8221;];<br>String strExpr = "id &gt; 5";<br>String strSort = "name DESC";<br>DataRow[] foundRows = customerTable.Select( strExpr, strSort,);<br><br>进行动态的筛选和排序。<br>DataTable.Select() 方法 ：&nbsp;&nbsp; 获取 DataRow 对象的数组，<br><br>①获取所有 DataRow 对象的数组。<br>public DataRow[] Select();<br><br><br><br>②按主键顺序(如没有主键,则按照添加顺序)，获取与筛选条件相匹配的所有 DataRow 对象的数组。<br>public DataRow[] Select(string);<br><br><br>③获取按照指定的排序顺序且与筛选条件相匹配的所有 DataRow 对象的数组。<br><br>public DataRow[] Select(string, string);<br><br><br>④获取与排序顺序中的筛选器以及指定的状态相匹配的所有 DataRow 对象的数组。<br><br>public DataRow[] Select(string, string, DataViewRowState);<br><br><br>十一。DataView 类 ： 是DataTable内容的动态视图。<br><br>1．&nbsp;&nbsp; 创建对象<br><br>初始化 DataView 类的新实例。<br><br>&nbsp;&nbsp; public DataView();<br><br>用指定的 DataTable 初始化 DataView 类的新实例。<br><br>&nbsp;&nbsp; public DataView(DataTable);<br><br>用指定的 DataTable、RowFilter、Sort 和 DataViewRowState 初始化 DataView 类的新实例。<br><br>&nbsp;&nbsp; public DataView(DataTable, string, string, DataViewRowState);<br><br><br>DataView myview = new DataView(ds.Tables["Suppliers"], "id &gt; 5", "name DESC"，<br>DataViewRowState.CurrentRows);<br><br><br>2 .得到DataView的行数据。<br><br>&nbsp;&nbsp;&nbsp; foreach (DataRowView myrowview in myview)<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (int i = 0; i &lt; myview.Table.Columns.Count; i++)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.Write(myrowview&nbsp;&nbsp; + "\t");<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Console.WriteLine();<br>&nbsp;&nbsp;&nbsp; }<br></div>
            </td>
        </tr>
    </tbody>
</table>
<br><a href="http://hi.baidu.com/27360411/blog/item/e69c9bcc3316b91400e92871.html">http://hi.baidu.com/27360411/blog/item/e69c9bcc3316b91400e92871.html</a><br>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39868.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-18 10:41 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39868.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[转]sql数据库连接-01ADO.NET的数据库访问小结 </title><link>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39867.html</link><dc:creator>巴西木</dc:creator><author>巴西木</author><pubDate>Mon, 18 Feb 2008 02:40:00 GMT</pubDate><guid>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39867.html</guid><wfw:comment>http://www.cnitblog.com/wufajiaru/comments/39867.html</wfw:comment><comments>http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39867.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/wufajiaru/comments/commentRss/39867.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/wufajiaru/services/trackbacks/39867.html</trackback:ping><description><![CDATA[ADO.NET的数据访问对象是以下几个：<br>　　1、Connection对象：与数据源建立连接，连接sql server7.0 或更新版本数据库用SqlConnection,连接OLEDB数据源使用OledbConnection.<br>　　2、Command 对象：对数据源执行SQL命令并返回结果，SQL Server7.0或更新版本用SqlCommand，OLE DB数据源使用OledbCommand.<br>　　3、DataReader对象： 读取数据源的数据，只能将数据源的数据从头到尾依次读出，Sql server7.0或以上版本使用SqlDataReader,Oledb数据源使用OledbReader<br>　　4、DataAdapter对象：对数据源执行操作并返回结果，在DataSet与数据源之间建立通信,将数据源中的数据写入DataSet ,或根据DataSet中的数据必定数据源。Sql server7.0或以上版本使用SqlDataAdapter,Oledb 数据源使用OledbAdpater.<br>　　5、DataSet对象：服务器内存中的数据库<br>　　6、DataView对象:用于显示DataSet中的数据
<p><font face=Arial>　　从数据库中读取纪录的另一种方法是使用Dataset对象和Dataadapter对象.Dataset是ADO.NET的主要组件之一，它用于缓存从数据源检索到的数据信息。Dataadapter作为Dataset和数据源之间的桥接器，用于检索和保存数据。Dataadapter从数据库中获取数据后使用Fill方法把数据填充到Dataset中。下面以Sqldataadapter为例说明如何使用Dataset对象和Dataadapter对象从数据库中读取记录。执行查询的关键步骤如下：<br>　　1、创建与数据库建立连接的Sqlconnection,传递连接字符串。<br>　　2、构造包含查询语句的Sqldataadapter对象;<br>　　3、若要使用查询结果填充Dataset对象，则调用命令Fill方法。</font></p>
<font face=Arial>
<p><br>　　c#利用ado.net进行数据库开发的基本步骤：<br>　　1、创建和数据库连接的connection 对象。<br>　　2、配置DataAdapter对象并创建和操作数据集DataSet。<br>　　3、将数据库中的表添加到DataSet中。<br>　　4、把数据集DataSet绑定到DataGrid上。利用DataAdapter 的Fill方法把数据填充到DataSet，最终的数据库中的数据显示在用户界面的DataGrid中。</p>
<p><br>　　c#中从数据库查询记录的方法分类:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 一般使用两种方法：<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;一种是通过DataReader对象直接访问;另一种则是通过数据集Dataset和Dataadapter对象访问.<br>　　使用ADO.NET的Datareader对象能从数据库中检索数据。检索出来的数据形成一个只读只进的数据流，存储在客户端的网络缓冲区内。Datareader对象的read方法可以前进到一下条记录。在默认情况下，每执行一次read方法只会在内存中存储一条记录系统的开销非常少。<br>　　创建datareader之前必须先创建sqlcommand对象，然后调用该对象的executereader方法来构造sqldatareader对象，而不是直接使用构造函数。<br>　　下面的示例程序完成的功能是访问sqlserver数据库，并使用datareader从northwind数据中读取记录，并将查询结果通过控制台输出。<br>　　using System;<br>　　using System.Data;<br>　　using System.Data.SqlClient;<br>　　namespace ReadDataFromDB{</p>
<p>　　class Class1{</p>
<p>　　static void Main(string[] args){<br>　　string myconn="Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind";<br>　　//需要执行的SQL语句<br>　　string mysql="select OrderID,CustomerID from Orders where CustomerID='CHOPS'";<br>　　//打开数据库连接。<br>&nbsp;&nbsp;&nbsp; SqlConnection myconnection=new SqlConnection(myconn);<br>　　myconnection.Open();<br>&nbsp;&nbsp;&nbsp; //创建SqlCommand 对象<br>　　SqlCommand mycommand=new(mysql,myconnection);<br>&nbsp;&nbsp;&nbsp; //通过SqlCommand的ExecuteReader()方法构造DataReader 对象。<br>　　SqlDataReader myreader=mycommand.ExecuteReader();<br>　　while(myreader.read()){<br>　　Console.WriteLine(myreader.GetInt32(0)+","+myreader.GetString(1));</p>
<p>　　}<br>　　myreader.Close();<br>　　myconnection.Close();</p>
<p>　　}</p>
<p>　　}</p>
<p>　　}</p>
<br><br><br><a href="http://blog.csdn.net/wuxianwei/archive/2008/01/22/2058070.aspx">http://blog.csdn.net/wuxianwei/archive/2008/01/22/2058070.aspx</a></font>
<img src ="http://www.cnitblog.com/wufajiaru/aggbug/39867.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/wufajiaru/" target="_blank">巴西木</a> 2008-02-18 10:40 <a href="http://www.cnitblog.com/wufajiaru/archive/2008/02/18/39867.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>