自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(2)
  • 资源 (119)
  • 收藏
  • 关注

原创 数据库系统--元组演算

1、元组演算的概念  在元组演算中,元组演算表达式简称为元组表达式,其一般形式为{t|p(t)}。t:元组变量,表示一个元数固定的元组;p:公式,在数理逻辑中也称为谓词,也就是计算机语言中的条件表达式。{t|p(t)}表示满足公式p的所有元组t的集合。2、原子公式★R(s),其中R是关系名,s是元组变量。★s[i]θu[j],其中s和u是元组变量,θ是算术比

2010-01-11 03:32:00 2151

转载 session详解。

摘要:虽然session机制在web应用程序中被采用已经很长时间了,但是仍然有很多人不清楚session机制的本质,以至不能正确的应用这一技术。本文将详细讨论session的工作机制并且对在Java web application中应用session机制时常见的问题作出解答。目录:一、术语session二、HTTP协议与状态保持三、理解cookie机制

2009-12-29 14:14:00 524

Berkeley DB Java Edition 4.0.92 开发包

这个是最流行的嵌入式高性能开源数据库内核开发包,java企业开发必备。

2010-04-14

SQL SERVER 2005 详细操作演示教程ppt

SQL SERVER 2005 详细操作演示教程ppt,每个操作都配图。方便各位快速入门。

2010-04-11

powerdesigner 12 详细操作演示教程ppt

这个文档ppt配图非常细致,基本是手把手配图了,方便数据库设计员有样学样。

2010-04-11

arcgis api for flex 1.3 arcgis_api_for_flex_1_3

这个压缩包包含agslib 1.3和相关的全套范例源代码!!! 可以在flex里做高级地学分析。

2010-04-06

org.eclipse.jdt.core_3.4.0.v_874.jar

您开发drools规则应用是否遇到过报错org.drools.RuntimeDroolsException: Unable to load dialect 'org.drools.rule.builder.dialect.java.JavaDialectConfiguration:java'呢? 这个jar包可解您燃眉之急。

2010-03-08

java日志记录组件log4j-1.2.14和commons-logging-1.1.1

本压缩包内附带log4j-1.2.14和commons-logging-1.1.1,Java日志记录行业标准组件。不要分啦。鄙视开源组件还收费的猥琐鬼。

2010-03-05

Flex 3 cookbook 中文版官方教程。高清带目录

这个是做flex富客户端必备的资料。做flex就必须经常参考的官方flex教程的中文版。

2010-01-18

基于龙芯的MIPS Linux中断代码分析

本文详细讲解了龙芯cpu的lootloader启动加载机制和中断处理原理。有志于推广国产cpu的人士适用。

2010-01-14

地理学的数学模型与应用.pdf

这本书详细探讨了高等数学在地理学各个分支上的深入应用,gis资深开发者以及gis领域研究员适用。

2010-01-12

一个超级简单可用的flex+asp.net的图片上传演示源代码压缩档

这个是新手学习flex + asp.net的图片上传的简单而好的代码。

2010-01-12

drools 5.0完整组件打包压缩文档 drools-5.0-bin.zip

这个是drools5.0完整组件库。包含了drools引擎所依赖的完整jar包集合。不收资源分啦。

2010-01-04

Drools4.0官方使用手册中文参考.doc

这个是DRools4.0的官方word文档参考哦。很详细全面的。 ````````````` 第2章. 规则引擎 2.1. 什么是规则引擎? 2.1.1. 背景介绍 A.I.(Artificial Intelligence)是一个关注于“使计算机像人类一样思考“的广泛的研究领域,包括Neural Networks(神经网络), Genetic Algorithms(遗传算法), Decision Trees(决策树), Frame Systems(框架系统) and Expert Systems(专家系统)。Knowledge representation(知识呈现)是A.I.的一部分,关注于如何呈现和操纵知识。专家系统使用知识表示把知识编码简化成一个可用于推理的知识库──比如,我们可以用知识库处理数据以推出结论。专家系统又叫基于知识的系统、基于知识的专家系统,并被认为是A.I.的一个应用。开发一个专家库系统的过程被称为知识工程。EMYCIN是最早的专家系统Shell(外壳)之一,它从医学诊断专家系统MYCIN发展而来。早期的专家系统有自己的logic hard coded "shells"(逻辑硬件编码外壳),把逻辑与系统相分离,为用户输入提供一个简单的使用环境。Drools是一个使用基于规则的方法实现的专家系统的规则引擎,更准确的说属于产生式规则系统。 术语“产生式规则”从形式语法中产生,形式语法——使用一种抽象结构来准确描述形式语言 (wikipedia)。 The term "Production Rule" originates from formal grammar - where it is described as "an abstract structure that describes a formal language precisely, i.e., a set of rules that mathematically delineates a (usually infinite) set of finite-length strings over a (usually finite) alphabet" (wikipedia). 业务规则管理系统在普通的规则引擎基础上通过提供—集中的业务用户,规则建立系统,管理,发布,协作,分析和终端用户工具等来达到更高的附加价值;使得企业能够以更顺利的方式引入规则引擎 规则引擎这个术语是非常不明确的,因为任何以任意形式使用能够应用于数据生成结果的规则的系统都可以称为规则引擎。包括像表单验证和动态表达式引擎这样的简单系统都可以称之为规则引擎。作者Malcolm Chisholm 的著作《How to Build a Business Rules Engine (2004)》就例证了这种不明确性。该书实际是讲述如何为管理校验规则而建立和维护一个数据库计划。该书中接着展示了如何根据这些校验规则产生VB代码来校验输入—在某些情况下这是很有用的,作者十分惊讶于这种不明确性,在没有觉察到各种规则引擎间细微不同之处时,他希望能发现其中的奥秘以帮助增强Drools引擎。JBoss jBPM(业务流程管理工具)在它的判断节点上使用表达式和代理引用来控制工作流中的事务。通过在每个节点上求值以决定分支的流向—这同样是一个规则引擎。产生式规则系统既是一种规则引擎,又是一个专家系统,而之前提到的校验器和表达式求值规则引擎不是专家系统 产生式规则系统完全关注于精确表达propositional(命题)和first order logic(一阶逻辑)的知识表示,不存在含糊不清的定义。产生式规则系统的核心是一个能够处理大量规则和事实的推理引擎。推理引擎将事实、数据与产生式规则(也可以叫做产生式,或干脆叫规则)进行匹配,以推出结论。产生式规则是一个用一阶逻辑进行知识呈现的二元结构。 when <conditions> then <actions> 将新的或已存在的事实与产生式规则进行匹配的过程被称为模式匹配,这个过程由推理机完成。推理机使用的用于模式匹配的算法有很多,包括: • Linear 线性的 • Rete 网状 • Treat • Leaps 叶状 Drool实现了Rete和Leaps算法;Leaps是试验性质的,因为它是个十分新的算法。Drools中的Rete算法被称为ReteOO,表示Drools为面向对象系统(Object Oriented systems)增强并优化了Rete算法。其它基于Rete算法的引擎也有他们对Rete算法进行独有增强后的市场术语,比如RetePlus,ReteIII。要知道象ReteIII这样的名字纯粹是市场性的,不像原始版本的Rete算法,它们没有公布实现细节,这一点很重要;因此,问类似于“Drools是用ReteIII实现的吗?”的问题是没有任何意义的。最寻常的对Rete算法的增强在下面这篇文章中有论述"Production Matching for Large Learning Systems (Rete/UL)" (1995) by Robert B. Doorenbos。 规则保存在Production Memory(规则库)中,推理机要匹配的facts(事实)保存在Working Memory(工作内存)中。事实被插入到工作内存中后,可能被修改或删除。一个有大量规则和事实的系统可能会很多规则被满足,这些规则被称为具有冲突性。Agenda通过(冲突决策策略)管理这些冲突规则的执行顺序。 Figure 2.1. 基础Rete网络 产生式规则系统的推理机是有状态的并且能够维持其中状态值的准确性,称为Truth Maintence(真值维护)。规则引擎中的动作仅当其依赖的约束为真值情况下执行,如果约束不再有效,则推论动作不会执行。"Honest Politician"(Drools提供的一个示例)就是这种真值维护的示范,在示例中规定,只要在存在诚实的政治家时,一个政体才有希望。 when an honest Politician exists then logically assert Hope when Hope exists then print "Hurrah!!! Democracy Lives" when Hope does not exist then print "Democracy is Doomed" 产生式规则系统有两种执行方法──正向推理和逆向推理,两种方法都使用的系统称为混合型产生式规则系统。理解这两种操作方法是理解产生式规则系统之所以不同和怎样从中选择最合适的系统的关键。正向推理是数据驱动的,facts事实被传递到工作空间中,在那里有一个或多个规则与这些事实匹配,并由Agenda安排执行—我们从一个事实开始,传递事实,最后得到一个结论。Drools是基于正向推理的规则引擎。 Figure 2.2. 正向推理 逆向推理是由目标驱动的,这意味着我们从一个引擎需要满足的结论开始进行推理。在这个结论不能满足时,将搜索一些能够满足的结论来推理,称为子目标,这些子目标将帮助完成当前目标的某些未知部分——引擎持续这个过程,直到最初的结论被证明或没有可证明的子目标。Prolog是逆向驱动型的引擎。Drools将在下一个主要版本中加入对逆向推理的支持。 Figure 2.3. 逆向推理 2.2. 为何使用规则引擎? 人们常常会问到: 1. 何时应当使用规则引擎? 2. 规则引擎与"if...then" 这样的硬编码比起来有什么优点? 3. 为何应当使用规则引擎取代脚本框架? 我们尝试通过以下说明来解答这些问题 2.2.1. 规则引擎的优点 • 声明式编程 规则引擎允许你描述做什么而不是如何去做。 这里的主要优点是使用规则更加容易对复杂的问题进行表述,并得到验证。 (规则比编码更容易阅读). 规则系统能够解决非常非常困难的问题,并提供了方案怎样达到和在解决问题的方向上所作的每一个决定的原因(这对于类似神经网络这样的AI系统来说不容易达到) • 逻辑与数据分离 数据保存在系统对象中,逻辑保存在规则中。这根本性的打破了面向对象系统中将数据和逻辑耦合起来的局面,这点是有利的也是不利的,在于你的观察角度。这样做的结果是,将来逻辑发生改变时更容易被维护,因为逻辑保存在规则中。这点在逻辑是跨领域或多领域中使用时尤其有用。通过将逻辑集中在一个或数个清晰的规则文件中,取代了之前分散在代码中的局面。 • 速度及可测量性 Rete算法、Leaps算法,以及由此衍生出来的Drools的Rete、Leaps算法,提供了对系统数据对象非常有效率的匹配。这些都是高效率尤其当你的数据是不完全的改变(规则引擎能够记得之前的匹配)。这些算法经过了大量实际考验的证明。 • 知识集中化 通过使用规则,将建立一个可执行的规则库。这意味着规则库代表着现实中的业务策略的唯一对应,理想情况下可读性高的规则还可以被当作文档使用。 • 工具集成 例如Eclipse(将来可能在基于Web的界面上)这样的工具为规则的修改与管理、即时获得反馈、内容验证与修补提供了办法。审查与调试工具同样也可用了。 • 解释机制 通过将规则引擎的决断与决断的原因一起记录下来,规则系统提供了很好的“解释机制”。 • 易懂的规则 通过建立对象模型以及DSL(域定义语言),你可以用接近自然语言的方式来编写规则。这让非技术人员与领域专家可以用他们自己的逻辑来理解规则(因为程序的迷宫已经被隐藏起来了) 。 2.2.2. 何时应当使用规则引擎? 对这个问题最简短的回答就是“当没有令人满意的传统的程序设计方法能够解决这个问题时”。下面上对所谓没有传统解决方法的一个描述: • 对于传统代码来说,问题需要的精确度太高。 这种问题可能并不复杂,但是你找不到一种稳定的方法去建立它。 • 问题超越了任何有明显运算法则的方案。 它是一个难以解决的复杂问题,没有明显的传统解决方案或者问题没有一个准确的定论。 • 业务逻辑经常发生改变 逻辑本身是简单的(但不是指过于简单),但是规则经常发生变化。在许多软件组织中正式版本的间隔是较长并且较少的,规则可以在适当的安全前提下帮助提供一定的敏捷性。 • 领域专家(或者业务分析师)是非技术人员 领域专家通常对业务规则和流程具有很好的认知。他们通常是不了解软件技术的人员,但是具有很好的逻辑性。规则能够让他们用自己的术语来描述业务逻辑。当然他们仍然需要严密的思考和良好的逻辑思维能力(许多在非软件技术型岗位上的人没有进行过形式逻辑的训练,因此在和他们工作时要特别小心,在将业务知识编撰成规则时,要特别注意业务规则和流程应当是当前能够理解的)。 如果规则对于你的项目组来说是一种新的技术,那在使用前必须将学习与管理的费用成本考虑进去。规则不是一种无意义的技术,这篇文档尽量让其易于理解。 在一个面向对象的应用中,规则引擎通常被用在包含业务逻辑的关键部分(具体与应用相关),特别是在十分繁杂凌乱的部分。这是对面向对象中将所有逻辑封装在对象中的一个倒置。但这并不是说应该抛弃对象模型,相反的来说在任何一个现实应用中业务逻辑仅仅是应用的一部分。如果你曾注意到在你的代码中有很多”if””else””switch”和其它凌乱的逻辑,你总是要回过头去修改它们(可能是由于提供给你的逻辑是错误的,或是你的理解变化了),那么可以考虑使用规则。如果你所面对的问题没有算法或者模式合适解决,考虑使用规则。 规则可以被嵌入你的应用中,或者作为一个服务使用。通常规则最好被当作一个有状态的组件使用——因此它们通常在应用中是一个整体。无论怎样,在一些规则被成功定义为可重用的服务的个案中,规则是无状态的。 如果考虑在组织中使用规则,那考虑产品中将如何使用和更新规则是很重要的(选择很多,但是不同的组织间有不同的需要——通常这超出了应用者/项目团队的控制)。 2.2.3. 何时不要使用规则 这里引用Drools邮件发送清单中的话(Dave Hamu):“在我看来,在使用规则引擎的兴奋中,人们忘记了规则引擎只是一个复杂的应用或方法中的一部分。实际上,规则引擎不是用于规则的工作流引擎或进程管理工具。对特定的工作要使用恰当的工具。当然,必要时老虎钳可以当作锤子用,但那并不是发明老虎钳的本意。” 因为规则引擎是动态的 (动态的在这里意味着规则可以象数据一样保存、管理和更新),它们通常被看作发布软件系统的一种解决方案(大多数IT部门似乎存在的目的是防止软件系统被遗弃)。如果这是你希望使用规则引擎的原因,应当意识到在可以写出公开发布的规则时,规则引擎能够以最佳方式工作。做为另一个方面,你也可以考虑使用数据驱动的设计(查找表)或者脚本/流程引擎带有能够在数据库中管理并能够动态更新的脚本。 2.2.4. 脚本或流程引擎 希望之前的讨论能够让你明白何时应该使用一个规则引擎。 另一方面,基于脚本的引擎也提供了"动态重组"的能力。 另外流程引擎 (通常为工作流)如jBPM允许你使用绘图(或编程)方式描述过程的步骤——这些步骤也能够带有包含简单规则的策略决策点。过程引擎与规则通常能够很好的在一起工作,因此这不是一个二选一的要求。 对于规则引擎的一个关键点是一些规则引擎实际上就是脚本引擎。在脚本引擎下是你的程序被牢牢绑定在脚本上(如果那里有规则,则必须直接调用),这导致未来维护更加困难,因为它们趋向于越来越复杂。在脚本引擎之上的好处是能够很容易的开始实现规则并迅速获得反馈(概念上会使得命令式编程更简单) 许多人在过去已经成功实现了数据驱动的系统(通过控制表中保存的元数据来影响应用的行为)——保持在一定控制范围内时这能够很好的工作。但是当超过了允许范围(如只有建立者能够改变应用的行为)太多这将很快失控或者导致应用停滞不前。 2.2.5. 紧密耦合与松散耦合 无疑在系统设计中你听说过紧密耦合与松散耦合。通常人们认为在设计中松散耦合是更好的,因为增加了系统灵活性。同样你可以有紧密耦合与松散耦合两种规则。紧密耦合在这里意味着一个规则的执行后将导致另一个规则有一个明显的结果,换句话说就是在规则之间有清晰的逻辑推理关系。如果你的规则都是紧密耦合的,那这些规则在将来会缺乏灵活性,并且更明显,这样规则引擎可能是使用过度了(因为逻辑是一组清晰的规则推理——能够被直接编码[一个决策树可能更适宜])。这并不是说紧密耦合或松散耦合本质就不好,但是在你考虑使用规则引擎并且捕捉规则时应当牢记这点。松散耦合使得系统中的规则在变更,删除和新增时不会影响其它无关的规则。 2.3. 知识表征 2.3.1. 一阶逻辑 规则是由一阶逻辑或断言逻辑编写而成,是由命题逻辑扩展而来。Emil Leon Post(数学家与逻辑学家 1897-1954)是第一个制定了利用符号来表示逻辑的推理系统——作为一个推论,他证明了任何逻辑系统(包括数学)能够被这样的一个符号系统来表达。 一个命题就是一项能够被归纳为True或Flase的一个声明。如果事实能够被一个独立的声明证明就称之为“封闭声明”。在程序中这表现为一个不含任何变量的表达式: 10 == 2 * 5 包含了一个或多个变量或Fact的表达式称为“开放声明”,在这种表达式中,只有当一个变量的实例被放入表达式后,才能知道该表达式是否为真值: Person.sex == "male" 在SQL语句中,一条语句的执行结果通常是将匹配的结果返回: select * from People where People.sex == "male" 所有由以上SQL返回回来的数据都会推论为是男性的数据,下图显示SQL如何作为一个推理引擎从People表中返回我们需要的结果。 Figure 2.4. SQL 作为一个单纯的推理引擎 因此在Java中,我们可以认为一个简单命题的形式是“变量”“运算符”“值”——在这里值通常代表一个字符串——命题可以看作是一个字段约束。命题之间可以使用“&&”或“||”进行逻辑合并。如下例: person.getEyeColor().equals("blue") || person.getEyeColor().equals("green") 这在规则引擎中也可以用“||”逻辑运算符来表示。 Person( eyeColour == "blue" ) || Person( eyeColor == "green" ) “||”逻辑运算也可以直接作用于字段约束上(Drools4.0M2实现该功能) Person( eyeColour == "blue"||"green" ) 命题逻辑并不能表达数据结构的标准(不具有图灵完备性),这约束了其可以定义的问题。一阶逻辑或断言逻辑通过两种新的量词概念以允许表达式定义结构——具体来说是全称量词和存在量词,从而扩展了命题逻辑。全称量词允许对每一个对象检查某些情况是否为真,通常使用“forall”这个条件元来支持(在Drools4.0M2中实现)。存在量词检查对象的存在性,这意味着该对象至少要出现一次——由“not”和“exist”这两个条件元支持。 设想我们定义了两个类——Student和Module。Module代表了一个学生在每个学期里要上的所有课程,通过List集合引用。在学期末,每个课程有一个得分。如果某个学生的所有课程中有一门低于40分代表该学生本学期不合格——通过存在量词可以使用“less then 40” 这样的开放命题来检查各Module中是否有符合该条件的情况。 public class Student { private String name; private List modules; ... } public class Module { private String name; private String studentName; private int score; Java具有图灵完备性,因此你可以通过编写代码遍历数据结构来检查存在性。下面的代码用来返回所有学期不合格的学生列表。 List failedStudents = new ArrayList(); for ( Iterator studentIter = students.iterator(); studentIter.hasNext() { Student student = ( Student ) studentIter.next(); for ( Iterator it = student.getModules.iterator(); it.hasNext(); ) { Module module = ( Module ) it.next(); if ( module.getScore() < 40 ) { failedStudents.add( student ) ; break; } } } 早期的SQL实现不是图灵完备的,因此不能提供对所存取的数据结构的量化性。目前的SQL引擎通过对嵌套SQL语句进行“exist”和“in”的关键字构造来支持存在性。以下代码显示如何通过SQL和规则来获取学期不合格的学生。 select * from Students s where exists ( select * from Modules m where m.student_name = s.name and m.score < 40 ) rule "Failed_Students" when exists( $student : Student() && Module( student == $student, score < 40 ) ) 2.4. Rete 算法 RETE算法是由Charles Forgy博士发明的,发表在他的博士论文中(1978-79)。这篇文章的简化版本发布在1982年(http://citeseer.ist.psu.edu/context/505087/0)。 单词Rete是拉丁语中的网的意思,代表网络的概念。Rete算法可以被分为两个部分:规则编辑和允许环境中的执行。 编辑算法描述了在生产空间(Production Memory)的规则如何产生一个有效的鉴别网络。用通俗的话来说,有效的鉴别网络是用来过滤数据的。办法是对在网络间传递的数据进行过滤。在网络顶部时节点将匹配许多数据,但是到了网络底部是将匹配较少的数据。在网络的很底部是终端节点。在Frogy博士1982年的文章中,他描述了四种基本的节点:root,1-input,2-input和terminal。 Figure 2.5. Rete Nodes 所有对象通过Root节点进入网络。从那之后立刻进入ObjectTypeNode节点。ObjectTypeNode节点的目的是保证引起不会做超过它需要做的工作范围。例如有两个对象:Account和Order。如果规则引擎尝试在每一个节点评估所有对象,这将花费很多循环。为了让工作更有效率,规则引擎应当只将与节点匹配的对象类型传入节点。最初是建立一个ObjectTypeNode节点,所有1-input和2-input节点都跟在后面。通过这种方法,应用传进来的Account对象不会被传送到需要Order对象的节点上。在Drools中,当一个对象被设置后,它将通过对象的类在HashMap中查找有效的ObjectTypesNode节点列表,如果这个列表不存在,它会搜索所有的ObjectTypesNode节点,找到有效的匹配并缓存到列表中。这能够让Drools通过一个instanceof检查来匹配任何对象类型。 Figure 2.6. ObjectTypeNodes ObjectTypdeNode节点能够向AlphaNode、LeftInputAdapteNode和BetaNode节点传播数据。AlphaNode节点用来对字符串进行求值。虽然在1982年的论文中只提到了等式操作,但许多Rete算法的实现支持其它操作。例如,Account.name==”Mr Trout”是一个字符串等式。当规则对一个对象类型有很多字符串等式时,它们会链接在一起。这意味着如果应用设置了一个Account对象,它必须满足了一个字符串等式后才能传递到下一个AlphaNode节点。在Forgy博士的论文中,他称之为内在条件。下面显示了针对Cheese对象的结合AlphaNode节点情况:Cheese( name == "cheddar, strength == "strong" ): Figure 2.7. AlphaNodes Drools 通过在ObjectTypdeNode 节点向AlphaNode节点传递时使用Hash操作优化了Rete算法。每次一个AlphaNode节点被加入到ObjectTypdeNode 节点时,将在HashMap中增加一个以字符串为键,AlphaNode节点为值的键值对。当一个新的对象实例进入ObjectTypdeNode节点时,它可以直接从HashMap中返回正确的AlphaNode节点,避免了多余的字符串检查。 有两种two-input节点——JoinNode和NotNode,都是BetaNode的类型。BetaNode节点用于比较两个对象和它们的字段。两个对象可能是相同或不同的类型。我们将这两个输入称为左和右。BetaNode的左输入通常是一组对象的列表,在Drools中称为语义(Tuple)。右边的输入是单个的对象。这两者能够使用“exist”进行对比检查。BetaNode具有记忆功能。左边的输入被称为Beta Memory,会记住所有到达过的语义。右边的输入成为Alpha Memory,会记住所有到达过的对象。Drools通过在BetaNode节点上建立索引扩展了Rete算法。例如,如果我们知道一个BetaNode用来对一个字符型字段进行检查,对每一个进入的对象,我们能够使用那个字符串的值进行一个Hash查找。这意味着当Fact从相反的一边进入BetaNode时,不需要再对所有Fact进行检索以发现有效链接,只要一个查找就可以返回潜在的有效候选。在任何时候,一个有效的链接是发现语义与对象的链接,它指的是一个局部匹配,并传播到下一个节点。 Figure 2.8. JoinNode 为了让最初的对象,在上图中是Cheese,进入Rete网络,我们使用了一个LeftInputNodeAdapter——将一个对象作为输入并传播一个对象的语义。 终端节点被用来表示一个单独的规则已经匹配了它的所有条件——在这一点上,我们说这个规则实现完全的匹配。一个使用“or”链接符的规则在每一个可能的逻辑路径上产生子规则,在这种情况下可以有多个终端节点。 Drools使用了节点共享技术。许多规则重复着同样的模式,节点共享允许我们删除这些模式的多余复制,从而避免对每一个单独得实例进行重复的评估。下面两个规则在一开始共享了相同的模式,但后面部分不同: rule when Cheese( $chedddar : name == "cheddar" ) $person : Person( favouriteCheese == $cheddar ) then System.out.println( $person.getName() + " likes cheddar" ); end rule when Cheese( $chedddar : name == "cheddar" ) $person : Person( favouriteCheese != $cheddar ) then System.out.println( $person.getName() + " does not like cheddar" ); end 你可以在下图看到,在编译的Rete网络中Alpha节点被共享了,但是Beta节点没有共享。每一个Beta节点有自己的终端节点。如果第二个模式是相同的也会被共享。 Figure 2.9. Node Sharing 2.5. Drools 规则引擎 2.5.1. 概述

2010-01-02

Maven权威指南(中文版).pdf 带目录 高清字体

这本书讲授如何使用maven2管理软件的团队开发。 正式的 Apache Maven1 的定义: Maven是一个项目管理工具,它包含了一个项 目对象模型 (Project Object Model),一组标准集合,一个项目生命周期(Project Lifecycle),一个依赖管理系统(Dependency Management System),和用来运行定义在 生命周期阶段(phase)中插件(plugin)目标(goal)的逻辑。

2009-12-25

Hibernate第3版开发手册.pdf 中文版

这个是hibernate 3 开发详细解析。

2009-12-17

mysql-connector-java-5.1.10.zip

这个是mysql的java连接组件包。将压缩包内的jar包拖进java工程的lib 目录就可用。 有感于某些人对这种开源的组件还要收什么下载资源分,太猥琐啦,这个就不要分了。

2009-12-13

JSP网页编程.ppt

这个没什么好说的。一份讲解jsp的ppt

2009-12-11

powerdesigner 9.5 物理模型用户入门手册

图书说明... .................................................................v 1 关于PDM教学...............................................................1 你将要做什么.....................................................................2 学习所需时间............... .................................................... 2 你将要学到到的内容. ............................................................ 3 安装............................................................................ 4 2 怎样开始PDM教学...........................................................5 启动Po werDesigner.............................................................. 6 打开新的PDM..................................................................... 7 返回操作PDM教学................................................................. 9 使用选项板梗具........................ ......................................... 11 定义PDM 属性和选项.............................................................. 16 在图形窗口安排符号.............................................................. 19 保存tutorial PDM................................................................ 20 3 在P D M 中创建一张表格...................................................21 添加一张表格...... ............................................................. 23 添加列...........................................................................25 创建一个区域...... ............................................................. 29 将列加于区域上.................................................................. 32 创建列...........................................................................34 在索引中创建关键字.............................................................. 36 为没有关键字的列创建索引....... ................................................ 39 4 定义参照和参照完整性................................. ...................43 创建一个参照...... ............................................................. 45 定义参照属性.................................................................... 46 定义参照完整性....... .......................................................... 48 5 创建视图...................................................................51 视图的组成.... ................................................................. 52 一般视图.... ................................................................... 53 6 参照完整性触发器的使用..............................................57 定义触发器的参照完整性..........................................59 触发器自动的创建............................................... 60 触发器裕览..................................................... 65 产生触发器的脚本................... .................................... 67 7 抽象数据类型的使用..................... ..............................71 指定一个Java类的抽象数据类型..................................... 73 创建一个PowerDesigner面向对象模型................................ 76 访问Java类的属性................................................. 77 8 生成一个数据库脚本..................... ..............................81 生成一个数据库创建脚本..... ..................................... 82 9 生成一个测试数据脚本................... ................................85 导入测试数据profiles(配置文件) .................................. 87 生成一个新的测试数据profiles(配置文件)........................ 89 定义一个测试数据作为自动测试数据 生成的源........................................................ 91 定义一个文件作为测试数据的源......... ...........................94 将一个测试数据的profiles赋值给所选列............................ 96 生成一个测试数据创建脚本........................................ 100 10 创建一个数据仓库数据库模式.........................................103 创建一个新模型并复制表格...........................................104 向模型添加一个表格................................................107 在当前模型定义一个数据源..........................................110 给关系创建一个关系映射........................................... 112 产生一个extraction脚本........................................... 119 11 多维特性的使用........................................................121 检索多维对象....................................................... 122 cube的重建........................................................ 124 产生cube数据...................................................... 129 退出PowerDesigner ................................................ 131 术语.......................................................................133 索引. .....................................................................137

2009-12-11

MySQL 5.1中文手冊

前言 1. 一般信息 1.1. 关于本手册 1.2. 本手册采用的惯例 1.3. MySQL AB概述 1.4. MySQL数据库管理系统概述 1.4.1. MySQL的历史 1.4.2. MySQL的的主要特性 1.4.3. MySQL稳定性 1.4.4. MySQL表最大能达到多少 1.4.5. 2000年兼容性 1.5. MaxDB数据库管理系统概述 1.5.1. 什么是MaxDB? 1.5.2. MaxDB的历史 1.5.3. MaxDB的特性 1.5.4. 许可和支持 1.5.5. MaxDB和MySQL之间的特性差异 1.5.6. MaxDB和MySQL之间的协同性 1.5.7. 与MaxDB有关的链接 1.6. MySQL发展大事记 1.6.1. MySQL 5.1的新特性 1.7. MySQL信息源 1.7.1. MySQL邮件列表 1.7.2. IRC(在线聊天系统)上的MySQL社区支持 1.7.3. MySQL论坛上的MySQL社区支持 1.8. MySQL标准的兼容性 1.8.1. MySQL遵从的标准是什么 1.8.2. 选择SQL模式 1.8.3. 在ANSI模式下运行MySQL 1.8.4. MySQL对标准SQL的扩展 1.8.5. MySQL与标准SQL的差别 1.8.6. MySQL处理约束的方式 2. 安装MySQL 2.1. 一般安装问题 2.1.1. MySQL支持的操作系统 2.1.2. 选择要安装的MySQL分发版 2.1.3. 怎样获得MySQL 2.1.4. 通过MD5校验和或GnuPG验证软件包的完整性 2.1.5. 安装布局 2.2. 使用二进制分发版的标准MySQL安装 2.3. 在Windows上安装MySQL 2.3.1. Windows系统要求 2.3.2. 选择安装软件包 2.3.3. 用自动安装器安装MySQL 2.3.4. 使用MySQL安装向导 2.3.5. 使用配置向导 2.3.6. 通过非安装Zip文件安装MySQL 2.3.7. 提取安装档案文件 2.3.8. 创建选项文件 2.3.9. 选择MySQL服务器类型 2.3.10. 首次启动服务器 2.3.11. 从Windows命令行启动MySQL 2.3.12. 以Windows服务方式启动MySQL 2.3.13. 测试MySQL安装 2.3.14. 在Windows环境下对MySQL安装的故障诊断与排除 2.3.15. 在Windows下升级MySQL 2.3.16. Windows版MySQL同Unix版MySQL对比 2.4. 在Linux下安装MySQL 2.5.在Mac OS X中安装MySQL 2.6. 在NetWare中安装MySQL 2.7. 在其它类Unix系统中安装MySQL 2.8. 使用源码分发版安装MySQL 2.8.1. 源码安装概述 2.8.2. 典型配置选项 2.8.3. 从开发源码树安装 2.8.4. 处理MySQL编译问题 2.8.5. MIT-pthreads注意事项 2.8.6. 在Windows下从源码安装MySQL 2.8.7. 在Windows下编译MySQL客户端 2.9. 安装后的设置和测试 2.9.1. Windows下安装后的过程 2.9.2. Unix下安装后的过程 2.9.3. 使初始MySQL账户安全 2.10. 升级MySQL 2.10.1. 从5.0版升级 2.10.2. 升级授权表 2.10.3. 将MySQL数据库拷贝到另一台机器 2.11. 降级MySQL 2.12. 具体操作系统相关的注意事项 2.12.1. Linux注意事项 2.12.2. Mac OS X注意事项 2.12.3. Solaris注意事项 2.12.4. BSD注意事项 2.12.5. 其它Unix注意事项 2.12.6. OS/2注意事项 2.13. Perl安装注意事项 2.13.1. 在Unix中安装Perl 2.13.2. 在Windows下安装ActiveState Perl 2.13.3. 使用Perl DBI/DBD接口的问题 3. 教程 3.1. 连接与断开服务器 3.2. 输入查询 3.3. 创建并使用数据库 3.3.1. 创建并选择数据库 3.3.2. 创建表 3.3.3. 将数据装入表中 3.3.4. 从表检索信息 3.4. 获得数据库和表的信息 3.5. 在批处理模式下使用mysql 3.6. 常用查询的例子 3.6.1. 列的最大值 3.6.2. 拥有某个列的最大值的行 3.6.3. 列的最大值:按组 3.6.4. 拥有某个字段的组间最大值的行 3.6.5. 使用用户变量 3.6.6. 使用外键 3.6.7. 根据两个键搜索 3.6.8. 根据天计算访问量 3.6.9. 使用AUTO_INCREMENT 3.7. 孪生项目的查询 3.7.1. 查找所有未分发的孪生项 3.7.2. 显示孪生对状态的表 3.8. 与Apache一起使用MySQL 4. MySQL程序概述 4.1. MySQL程序概述 4.2. 调用MySQL程序 4.3. 指定程序选项 4.3.1. 在命令行上使用选项 4.3.2. 使用选项文件 4.3.3. 用环境变量指定选项 4.3.4. 使用选项设置程序变量 5. 数据库管理 5.1. MySQL服务器和服务器启动脚本 5.1.1. 服务器端脚本和实用工具概述 5.1.2. mysqld-max扩展MySQL服务器 5.1.3. mysqld_safe:MySQL服务器启动脚本 5.1.4. mysql.server:MySQL服务器启动脚本 5.1.5. mysqld_multi:管理多个MySQL服务器的程序 5.2. mysqlmanager:MySQL实例管理器 5.2.1. 用MySQL实例管理器启动MySQL服务器 5.2.2. 连接到MySQL实例管理器并创建用户账户 5.2.3. MySQL实例管理器命令行选项 5.2.4. MySQL实例管理器配置文件 5.2.5. MySQL实例管理器识别的命令 5.3. mysqld:MySQL服务器 5.3.1. mysqld命令行选项 5.3.2. SQL服务器模式 5.3.3. 服务器系统变量 5.3.4. 服务器状态变量 5.4. mysql_fix_privilege_tables:升级MySQL系统表 5.5. MySQL服务器关机进程 5.6. 一般安全问题 5.6.1. 通用安全指南 5.6.2. 使MySQL在攻击者面前保持安全 5.6.3. Mysqld安全相关启动选项 5.6.4. LOAD DATA LOCAL安全问题 5.7. MySQL访问权限系统 5.7.1. 权限系统的作用 5.7.2. 权限系统工作原理 5.7.3. MySQL提供的权限 5.7.4. 与MySQL服务器连接 5.7.5. 访问控制, 阶段1:连接核实 5.7.6. 访问控制, 阶段2:请求核实 5.7.7. 权限更改何时生效 5.7.8. 拒绝访问错误的原因 5.7.9. MySQL 4.1中的密码哈希处理 5.8. MySQL用户账户管理 5.8.1. MySQL用户名和密码 5.8.2. 向MySQL增加新用户账户 5.8.3. 从MySQL删除用户账户 5.8.4. 限制账户资源 5.8.5. 设置账户密码 5.8.6. 使你的密码安全 5.8.7. 使用安全连接 5.9. 备份与恢复 5.9.1. 数据库备份 5.9.2. 示例用备份与恢复策略 5.9.3. 自动恢复 5.9.4. 表维护和崩溃恢复 5.9.5. myisamchk:MyISAM表维护实用工具 5.9.6. 建立表维护计划 5.9.7. 获取关于表的信息 5.10. MySQL本地化和国际应用 5.10.1. 数据和排序用字符集 5.10.2. 设置错误消息语言 5.10.3. 添加新的字符集 5.10.4. 字符定义数组 5.10.5. 字符串比较支持 5.10.6. 多字节字符支持 5.10.7. 字符集问题 5.10.8. MySQL服务器时区支持 5.11. MySQL日志文件 5.11.1. 错误日志 5.11.2. 通用查询日志 5.11.3. 二进制日志 5.11.4. 慢速查询日志 5.11.5. 日志文件维护 5.12. 在同一台机器上运行多个MySQL服务器 5.12.1. 在Windows下运行多个服务器 5.12.2. 在Unix中运行多个服务器 5.12.3. 在多服务器环境中使用客户端程序 5.13. MySQL查询高速缓冲 5.13.1. 查询高速缓冲如何工作 5.13.2. 查询高速缓冲SELECT选项 5.13.3. 查询高速缓冲配置 5.13.4. 查询高速缓冲状态和维护 6. MySQL中的复制 6.1. 复制介绍 6.2. 复制实施概述 6.3. 复制实施细节 6.3.1. 复制主线程状态 6.3.2. 复制从I/O线程状态 6.3.3. 复制从SQL线程状态 6.3.4. 复制传递和状态文件 6.4. 如何设置复制 6.5. 不同MySQL版本之间的复制兼容性 6.6. 升级复制设置 6.6.1. 将复制升级到5.0版 6.7. 复制特性和已知问题 6.8. 复制启动选项 6.9. 复制FAQ 6.10. 复制故障诊断与排除 6.11. 通报复制缺陷 6.12. 多服务器复制中的Auto-Increment 7. 优化 7.1. 优化概述 7.1.1. MySQL设计局限与折衷 7.1.2. 为可移植性设计应用程序 7.1.3. 我们已将MySQL用在何处? 7.1.4. MySQL基准套件 7.1.5. 使用自己的基准 7.2. 优化SELECT语句和其它查询 7.2.1. EXPLAIN语法(获取SELECT相关信息) 7.2.2. 估计查询性能 7.2.3. SELECT查询的速度 7.2.4. MySQL怎样优化WHERE子句 7.2.5. 范围优化 7.2.6. 索引合并优化 7.2.7. MySQL如何优化IS NULL 7.2.8. MySQL如何优化DISTINCT 7.2.9. MySQL如何优化LEFT JOIN和RIGHT JOIN 7.2.10. MySQL如何优化嵌套Join 7.2.11. MySQL如何简化外部联合 7.2.12. MySQL如何优化ORDER BY 7.2.13. MySQL如何优化GROUP BY 7.2.14. MySQL如何优化LIMIT 7.2.15. 如何避免表扫描 7.2.16. INSERT语句的速度 7.2.17. UPDATE语句的速度 7.2.18. DELETE语句的速度 7.2.19. 其它优化技巧 7.3. 锁定事宜 7.3.1. 锁定方法 7.3.2. 表锁定事宜 7.4. 优化数据库结构 7.4.1. 设计选择 7.4.2. 使你的数据尽可能小 7.4.3. 列索引 7.4.4. 多列索引 7.4.5. MySQL如何使用索引 7.4.6. MyISAM键高速缓冲 7.4.7. MyISAM索引统计集合 7.4.8. MySQL如何计算打开的表 7.4.9. MySQL如何打开和关闭表 7.4.10. 在同一个数据库中创建多个表的缺陷 7.5. 优化MySQL服务器 7.5.1. 系统因素和启动参数的调节 7.5.2. 调节服务器参数 7.5.3. 控制查询优化器的性能 7.5.4. 编译和链接怎样影响MySQL的速度 7.5.5. MySQL如何使用内存 7.5.6. MySQL如何使用DNS 7.6. 磁盘事宜 7.6.1. 使用符号链接 8. 客户端和实用工具程序 8.1. 客户端脚本和实用工具概述 8.2. myisampack:生成压缩、只读MyISAM表 8.3. mysql:MySQL命令行工具 8.3.1. 选项 8.3.2. mysql命令 8.3.3. 怎样从文本文件执行SQL语句 8.3.4. mysql技巧 8.4. mysqlaccess:用于检查访问权限的客户端 8.5. mysqladmin:用于管理MySQL服务器的客户端 8.6. mysqlbinlog:用于处理二进制日志文件的实用工具 8.7. mysqlcheck:表维护和维修程序 8.8. mysqldump:数据库备份程序 8.9. mysqlhotcopy:数据库备份程序 8.10. mysqlimport:数据导入程序 8.11. mysqlshow-显示数据库、表和列信息 8.12. myisamlog:显示MyISAM日志文件内容 8.13. perror:解释错误代码 8.14. replace:字符串替换实用工具 8.15. mysql_zap:杀死符合某一模式的进程 9. 语言结构 9.1. 文字值 9.1.1. 字符串 9.1.2. 数值 9.1.3. 十六进制值 9.1.4. 布尔值 9.1.5. 位字段值 9.1.6. NULL值 9.2. 数据库、表、索引、列和别名 9.2.1. 识别符限制条件 9.2.2. 识别符大小写敏感性 9.3. 用户变量 9.4. 系统变量 9.4.1. 结构式系统变量 9.5. 注释语法 9.6. MySQL中保留字的处理 10. 字符集支持 10.1. 常规字符集和校对 10.2. MySQL中的字符集和校对 10.3. 确定默认字符集和校对 10.3.1. 服务器字符集和校对 10.3.2. 数据库字符集和校对 10.3.3. 表字符集和校对 10.3.4. 列字符集和校对 10.3.5. 字符集和校对分配示例 10.3.6. 连接字符集和校对 10.3.7. 字符串文字字符集和校对 10.3.8. 在SQL语句中使用COLLATE 10.3.9. COLLATE子句优先 10.3.10. BINARY操作符 10.3.11. 校对确定较为复杂的一些特殊情况 10.3.12. 校对必须适合字符集 10.3.13. 校对效果的示例 10.4. 字符集支持影响到的操作 10.4.1. 结果字符串 10.4.2. CONVERT() 10.4.3. CAST() 10.4.4. SHOW语句 10.5. Unicode支持 10.6. 用于元数据的UTF8 10.7. 与其它DBMS的兼容性 10.8. 新字符集配置文件格式 10.9. 国家特有字符集 10.10. MySQL支持的字符集和校对 10.10.1. Unicode字符集 10.10.2. 西欧字符集 10.10.3. 中欧字符集 10.10.4. 南欧与中东字符集 10.10.5. 波罗的海字符集 10.10.6. 西里尔字符集 10.10.7. 亚洲字符集 11. 列类型 11.1. 列类型概述 11.1.1. 数值类型概述 11.1.2. 日期和时间类型概述 11.1.3. 字符串类型概述 11.2. 数值类型 11.3. 日期和时间类型 11.3.1. DATETIME、DATE和TIMESTAMP类型 11.3.2. TIME类型 11.3.3. YEAR类型 11.3.4. Y2K事宜和日期类型 11.4. String类型 11.4.1. CHAR和VARCHAR类型 11.4.2. BINARY和VARBINARY类型 11.4.3. BLOB和TEXT类型 11.4.4. ENUM类型 11.4.5. SET类型 11.5. 列类型存储需求 11.6. 选择正确的列类型 11.7. 使用来自其他数据库引擎的列类型 12. 函数和操作符 12.1. 操作符 12.1.1. 操作符优先级 12.1.2. 圆括号 12.1.3. 比较函数和操作符 12.1.4. 逻辑操作符 12.2. 控制流程函数 12.3. 字符串函数 12.3.1. 字符串比较函数 12.4. 数值函数 12.4.1. 算术操作符 12.4.2. 数学函数 12.5. 日期和时间函数 12.6. MySQL使用什么日历? 12.7. 全文搜索功能 12.7.1. 布尔全文搜索 12.7.2. 全文搜索带查询扩展 12.7.3. 全文停止字 12.7.4. 全文限定条件 12.7.5. 微调MySQL全文搜索 12.8. Cast函数和操作符 12.9. 其他函数 12.9.1. 位函数 12.9.2. 加密函数 12.9.3. 信息函数 12.9.4. 其他函数 12.10. 与GROUP BY子句同时使用的函数和修改程序 12.10.1. GROUP BY(聚合)函数 12.10.2. GROUP BY修改程序 12.10.3. 具有隐含字段的GROUP BY 13. SQL语句语法 13.1. 数据定义语句 13.1.1. ALTER DATABASE语法 13.1.2. ALTER TABLE语法 13.1.3. CREATE DATABASE语法 13.1.4. CREATE INDEX语法 13.1.5. CREATE TABLE语法 13.1.6. DROP DATABASE语法 13.1.7. DROP INDEX语法 13.1.8. DROP TABLE语法 13.1.9. RENAME TABLE语法 13.2. 数据操作语句 13.2.1. DELETE语法 13.2.2. DO语法 13.2.3. HANDLER语法 13.2.4. INSERT语法 13.2.5. LOAD DATA INFILE语法 13.2.6. REPLACE语法 13.2.7. SELECT语法 13.2.8. Subquery语法 13.2.9. TRUNCATE语法 13.2.10. UPDATE语法 13.3. MySQL实用工具语句 13.3.1. DESCRIBE语法(获取有关列的信息) 13.3.2. USE语法 13.4. MySQL事务处理和锁定语句 13.4.1. START TRANSACTION, COMMIT和ROLLBACK语法 13.4.2. 不能回滚的语句 13.4.3. 会造成隐式提交的语句 13.4.4. SAVEPOINT和ROLLBACK TO SAVEPOINT语法 13.4.5. LOCK TABLES和UNLOCK TABLES语法 13.4.6. SET TRANSACTION语法 13.4.7. XA事务 13.5. 数据库管理语句 13.5.1. 账户管理语句 13.5.2. 表维护语句 13.5.3. SET语法 13.5.4. SHOW语法 13.5.5. 其它管理语句 13.6. 复制语句 13.6.1. 用于控制主服务器的SQL语句 13.6.2. 用于控制从服务器的SQL语句 13.7. 用于预处理语句的SQL语法 14. 插件式存储引擎体系结构 14.1. 前言 14.2. 概述 14.3. 公共MySQL数据库服务器层 14.4. 选择存储引擎 14.5. 将存储引擎指定给表 14.6. 存储引擎和事务 14.7. 插入存储引擎 14.8. 拔出存储引擎 14.9. 插件式存储器的安全含义 15. 存储引擎和表类型 15.1. MyISAM存储引擎 15.1.1. MyISAM启动选项 15.1.2. 键所需的空间 15.1.3. MyISAM表的存储格式 15.1.4. MyISAM表方面的问题 15.2. InnoDB存储引擎 15.2.1. InnoDB概述 15.2.2. InnoDB联系信息 15.2.3. InnoDB配置 15.2.4. InnoDB启动选项 15.2.5. 创建InnoDB表空间 15.2.6. 创建InnoDB表 15.2.7. 添加和删除InnoDB数据和日志文件 15.2.8. InnoDB数据库的备份和恢复 15.2.9. 将InnoDB数据库移到另一台机器上 15.2.10. InnoDB事务模型和锁定 15.2.11. InnoDB性能调节提示 15.2.12. 多版本的实施 15.2.13. 表和索引结构 15.2.14. 文件空间管理和磁盘I/O 15.2.15. InnoDB错误处理 15.2.16. 对InnoDB表的限制 15.2.17. InnoDB故障诊断与排除 15.3. MERGE存储引擎 15.3.1. MERGE表方面的问题 15.4. MEMORY (HEAP)存储引擎 15.5. BDB (BerkeleyDB)存储引擎 15.5.1. BDB支持的操作系统 15.5.2. 安装BDB 15.5.3. BDB启动选项 15.5.4. BDB表的特性 15.5.5. 修改BDB所需的事宜 15.5.6. 对BDB表的限制 15.5.7. 使用BDB表时可能出现的错误 15.6. EXAMPLE存储引擎 15.7. FEDERATED存储引擎 15.7.1. 安装FEDERATED存储引擎 15.7.2. FEDERATED存储引擎介绍 15.7.3. 如何使用FEDERATED表 15.7.4. FEDERATED存储引擎的局限性 15.8. ARCHIVE存储引擎 15.9. CSV存储引擎 15.10. BLACKHOLE存储引擎 16. 编写自定义存储引擎 16.1. 前言 16.2. 概述 16.3. 创建存储引擎源文件 16.4. 创建handlerton 16.5. 对处理程序进行实例化处理 16.6. 定义表扩展 16.7. 创建表 16.8. 打开表 16.9. 实施基本的表扫描功能 16.9.1. 实施store_lock()函数 16.9.2. 实施external_lock()函数 16.9.3. 实施rnd_init()函数 16.9.4. 实施info()函数 16.9.5. 实施extra()函数 16.9.6. 实施rnd_next()函数 16.10. 关闭表 16.11. 为存储引擎添加对INSERT的支持 16.12. 为存储引擎添加对UPDATE的支持 16.13. 为存储引擎添加对DELETE的支持 16.14. API引用 16.14.1. bas_ext 16.14.2. close 16.14.3. create 16.14.4. delete_row 16.14.5. delete_table 16.14.6. external_lock 16.14.7. extra 16.14.8. info 16.14.9. open 16.14.10. rnd_init 16.14.11. rnd_next 16.14.12. store_lock 16.14.13. update_row 16.14.14. write_row 17. MySQL簇 17.1. MySQL簇概述 17.2. MySQL簇的基本概念 17.3. 多计算机的简单基础知识 17.3.1. 硬件、软件和联网 17.3.2. 安装 17.3.3. 配置 17.3.4. 首次启动 17.3.5. 加载示例数据并执行查询 17.3.6. 安全关闭和重启 17.4. MySQL簇的配置 17.4.1. 从源码创建MySQL簇 17.4.2. 安装软件 17.4.3. MySQL簇的快速测试设置 17.4.4. 配置文件 17.5. MySQL簇中的进程管理 17.5.1. 用于MySQL簇的MySQL服务器进程使用 17.5.2. ndbd,存储引擎节点进程 17.5.3. ndb_mgmd,“管理服务器”进程 17.5.4. ndb_mgm,“管理客户端”进程 17.5.5. 用于MySQL簇进程的命令选项 17.6. MySQL簇的管理 17.6.1. MySQL簇的启动阶段 17.6.2. “管理客户端”中的命令 17.6.3. MySQL簇中生成的事件报告 17.6.4. 单用户模式 17.6.5. MySQL簇的联机备份 17.7. 使用与MySQL簇的高速互连 17.7.1. 配置MySQL簇以使用SCI套接字 17.7.2. 理解簇互连的影响 17.8. MySQL簇的已知限制 17.9. MySQL簇发展的重要历程 17.9.1. MySQL 5.0中的MySQL簇变化 17.9.2. 关于MySQL簇的MySQL 5.1发展历程 17.10. MySQL簇常见问题解答 17.11. MySQL簇术语表 18. 分区 18.1. MySQL中的分区概述 18.2. 分区类型 18.2.1. RANGE分区 18.2.2. LIST分区 18.2.3. HASH分区 18.2.4. KEY分区 18.2.5. 子分区 18.2.6. MySQL分区处理NULL值的方式 18.3. 分区管理 18.3.1. RANGE和LIST分区的管理 18.3.2. HASH和KEY分区的管理 18.3.3. 分区维护 18.3.4. 获取关于分区的信息 19. MySQL中的空间扩展 19.1. 前言 19.2. OpenGIS几何模型 19.2.1. Geometry类的层次 19.2.2. 类Geometry 19.2.3. 类Point 19.2.4. 类Curve 19.2.5. 类LineString 19.2.6. 类Surface 19.2.7. 类Polygon 19.2.8. 类GeometryCollection 19.2.9. 类MultiPoint 19.2.10. 类MultiCurve 19.2.11. 类MultiLineString 19.2.12. 类MultiSurface 19.2.13. 类MultiPolygon 19.3. 支持的空间数据格式 19.3.1. 著名的文本(WKT)格式 19.3.2. 著名的二进制(WKB)格式 19.4. 创建具备空间功能的MySQL数据库 19.4.1. MySQL空间数据类型 19.4.2. 创建空间值 19.4.3. 创建空间列 19.4.4. 填充空间列 19.4.5. 获取空间数据 19.5. 分析空间信息 19.5.1. Geometry格式转换函数 19.5.2. Geometry函数 19.5.3. 从已有Geometry创建新Geometry的函数 19.5.4. 测试几何对象间空间关系的函数 19.5.5. 关于几何最小边界矩形(MBR)的关系 19.5.6. 测试几何类之间空间关系的函数 19.6. 优化空间分析 19.6.1. 创建空间索引 19.6.2. 使用空间索引 19.7. MySQL的一致性和兼容性 19.7.1. 尚未实施的GIS特性 20. 存储程序和函数 20.1. 存储程序和授权表 20.2. 存储程序的语法 20.2.1. CREATE PROCEDURE和CREATE FUNCTION 20.2.2. ALTER PROCEDURE和ALTER FUNCTION 20.2.3. DROP PROCEDURE和DROP FUNCTION 20.2.4. SHOW CREATE PROCEDURE和SHOW CREATE FUNCTION 20.2.5. SHOW PROCEDURE STATUS和SHOW FUNCTION STATUS 20.2.6. CALL语句 20.2.7. BEGIN ... END复合语句 20.2.8. DECLARE语句 20.2.9. 存储程序中的变量 20.2.10. 条件和处理程序 20.2.11. 光标 20.2.12. 流程控制构造 20.3. 存储程序、函数、触发程序和复制:常见问题 20.4. 存储子程序和触发程序的二进制日志功能 21. 触发程序 21.1. CREATE TRIGGER语法 21.2. DROP TRIGGER语法 21.3. 使用触发程序 22. 视图 22.1. ALTER VIEW语法 22.2. CREATE VIEW语法 22.3. DROP VIEW语法 22.4. SHOW CREATE VIEW语法 23. INFORMATION_SCHEMA信息数据库 23.1. INFORMATION_SCHEMA表 23.1.1. INFORMATION_SCHEMA SCHEMATA表 23.1.2. INFORMATION_SCHEMA TABLES表 23.1.3. INFORMATION_SCHEMA COLUMNS表 23.1.4. INFORMATION_SCHEMA STATISTICS表 23.1.5. INFORMATION_SCHEMA USER_PRIVILEGES表 23.1.6. INFORMATION_SCHEMA SCHEMA_PRIVILEGES表 23.1.7. INFORMATION_SCHEMA TABLE_PRIVILEGES表 23.1.8. INFORMATION_SCHEMA COLUMN_PRIVILEGES表 23.1.9. INFORMATION_SCHEMA CHARACTER_SETS表 23.1.10. INFORMATION_SCHEMA COLLATIONS表 23.1.11. INFORMATION_SCHEMA COLLATION_CHARACTER_SET_APPLICABILITY表 23.1.12. INFORMATION_SCHEMA TABLE_CONSTRAINTS表 23.1.13. INFORMATION_SCHEMA KEY_COLUMN_USAGE表 23.1.14. INFORMATION_SCHEMA ROUTINES表 23.1.15. INFORMATION_SCHEMA VIEWS表 23.1.16. INFORMATION_SCHEMA TRIGGERS表 23.1.17. 其他INFORMATION_SCHEMA表 23.2. SHOW语句的扩展 24. 精度数学 24.1. 数值的类型 24.2. DECIMAL数据类型更改 24.3. 表达式处理 24.4. 四舍五入 24.5. 精度数学示例 25. API和库 25.1. libmysqld,嵌入式MySQL服务器库 25.1.1. 嵌入式MySQL服务器库概述 25.1.2. 使用libmysqld编译程序 25.1.3. 使用嵌入式MySQL服务器时的限制 25.1.4. 与嵌入式服务器一起使用的选项 25.1.5. 嵌入式服务器中尚需完成的事项(TODO) 25.1.6. 嵌入式服务器示例 25.1.7. 嵌入式服务器的许可 25.2. MySQL C API 25.2.1. C API数据类型 25.2.2. C API函数概述 25.2.3. C API函数描述 25.2.4. C API预处理语句 25.2.5. C API预处理语句的数据类型 25.2.6. C API预处理语句函数概述 25.2.7. C API预处理语句函数描述 25.2.8. C API预处理语句方面的问题 25.2.9. 多查询执行的C API处理 25.2.10. 日期和时间值的C API处理 25.2.11. C API线程函数介绍 25.2.12. C API嵌入式服务器函数介绍 25.2.13. 使用C API时的常见问题 25.2.14. 创建客户端程序 25.2.15. 如何生成线程式客户端 25.3. MySQL PHP API 25.3.1. 使用MySQL和PHP的常见问题 25.4. MySQL Perl API 25.5. MySQL C++ API 25.5.1. Borland C++ 25.6. MySQL Python API 25.7. MySQL Tcl API 25.8. MySQL Eiffel Wrapper 25.9. MySQL程序开发实用工具 25.9.1. msql2mysql:转换mSQL程序以用于MySQL 25.9.2. mysql_config:获取编译客户端的编译选项 26. 连接器 26.1. MySQL Connector/ODBC 26.1.1. MyODBC介绍 26.1.2. 关于ODBC和MyODBC的一般信息 26.1.3. 如何安装MyODBC 26.1.4. 在Windows平台上从二进制版本安装MyODBC 26.1.5. I在Unix平台上从二进制版本安装MyODBC 26.1.6. 在Windows平台上从源码版本安装MyODBC 26.1.7. 在Unix平台上从源码版本安装MyODBC 26.1.8. 从BitKeeper开发源码树安装MyODBC 26.1.9. MyODBC配置 26.1.10. 与MyODBC连接相关的事宜 26.1.11. MyODBC和Microsoft Access 26.1.12. MyODBC和Microsoft VBA及ASP 26.1.13. MyODBC和第三方ODBC工具 26.1.14. MyODBC通用功能 26.1.15. 基本的MyODBC应用步骤 26.1.16. MyODBC API引用 26.1.17. MyODBC数据类型 26.1.18. MyODBC错误代码 26.1.19. MyODBC与VB:ADO、DAO和RDO 26.1.20. MyODBC与Microsoft.NET 26.1.21. 感谢 26.2. MySQL Connector/NET 26.2.1. 前言 26.2.2. 下载并安装MySQL Connector/NET 26.2.3. Connector/NET体系结构 26.2.4. 使用MySQL Connector/NET 26.2.5. MySQL Connector/NET变更史 26.3. MySQL Connector/J 26.3.1. 基本的JDBC概念 26.3.2. 安装 Connector/J 26.3.3. JDBC引用 26.3.4. 与J2EE和其他Java框架一起使用 Connector/J 26.3.5. 诊断 Connector/J方面的问题 26.3.6. Changelog 26.4. MySQL Connector/MXJ 26.4.1. 前言 26.4.2. 支持平台: 26.4.3. Junit测试要求 26.4.4. 运行Junit测试 26.4.5. 作为JDBC驱动程序的一部分运行 26.4.6. 在Java对象中运行 26.4.7. MysqldResource API 26.4.8. 在JMX代理(custom)中运行 26.4.9. 部署在标准的JMX代理环境下 (JBoss) 26.4.10. 安装 27. 扩展MySQL 27.1. MySQL内部控件 27.1.1. MySQL线程 27.1.2. MySQL测试套件 27.2. 为MySQL添加新函数 27.2.1. 自定义函数接口的特性 27.2.2. CREATE FUNCTION/DROP FUNCTION语法 27.2.3. 添加新的自定义函数 27.2.4. 添加新的固有函数 27.3. 为MySQL添加新步骤 27.3.1. 步骤分析 27.3.2. 编写步骤 A. 问题和常见错误 A.1. 如何确定导致问题的原因 A.2. 使用MySQL程序时的常见错误 A.2.1. 拒绝访问 A.2.2. 无法连接到[local] MySQL服务器 A.2.3. 客户端不支持鉴定协议 A.2.4. 输入密码时出现密码错误 A.2.5. 主机的host_name被屏蔽 A.2.6. 连接数过多 A.2.7. 内存溢出 A.2.8. MySQL服务器不可用 A.2.9. 信息包过大 A.2.10. 通信错误和失效连接 A.2.11. 表已满 A.2.12. 无法创建文件/写入文件 A.2.13. 命令不同步 A.2.14. 忽略用户 A.2.15. 表tbl_name不存在 A.2.16. 无法初始化字符集 A.2.17. 文件未找到 A.3. 与安装有关的事宜 A.3.1. 与MySQL客户端库的链接问题 A.3.2. 如何以普通用户身份运行MySQL A.3.3. 与文件许可有关的问题 A.4. 与管理有关的事宜 A.4.1. 如何复位根用户密码 A.4.2. 如果MySQL依然崩溃,应作些什么 A.4.3. MySQL处理磁盘满的方式 A.4.4. MySQL将临时文件储存在哪里 A.4.5. 如何保护或更改MySQL套接字文件/tmp/mysql.sock A.4.6. 时区问题 A.5. 与查询有关的事宜 A.5.1. 搜索中的大小写敏感性 A.5.2. 使用DATE列方面的问题 A.5.3. 与NULL值有关的问题

2009-12-11

全面解析JDBC文档。

  综述:Java数据库连接体系结构是用于Java应用程序连接数据库的标准方法。JDBC对Java程序员而言是API,对实现与数据库连接的服务提供商而言是接口模型。作为API,JDBC为程序开发提供标准的接口,并为数据库厂商及第三方中间件厂商实现与数据库的连接提供了标准方法。JDBC使用已有的SQL标准并支持与其它数据库连接标准,如ODBC之间的桥接。JDBC实现了所有这些面向标准的目标并且具有简单、严格类型定义且高性能实现的接口。   如何选择合适的JDBC产品?   有关JDBC最新的信息,有兴趣的读者可以查阅JDBC的官方网站--即JavaSoft的主页,其URL为:http://Java.sun.com/products/jdbc   1. JavaSoft框架   JavaSoft提供三种JDBC产品组件,它们是Java开发工具包(JDK)的组成部份:JDBC驱动程序管理器、JDBC驱动程序测试工具包和JDBC-ODBC桥。   JDBC驱动程序管理器是JDBC体系结构的支柱。它实际上很小,也很简单;其主要作用是把Java应用程序连接到正确的JDBC驱动程序上,然后即退出。   JDBC驱动程序测试工具包为使JDBC驱动程序运行您的程序提供一定的可信度。只有通过JDBC驱动程序测试的驱动程序才被认为是符合JDBC标准TM的。   JDBC-ODBC桥使ODBC驱动程序可被用作JDBC驱动程序。它的实现为JDBC的快速发展提供了一条途径,其长远目标提供一种访问某些不常见的DBMS(如果对这些不常见的DBMS未实现JDBC)的方法。   2. JDBC驱动程序的类型   目前比较常见的JDBC驱动程序可分为以下四个种类:   (1)JDBC-ODBC桥加ODBC驱动程序   JavaSoft桥产品利用ODBC驱动程序提供JDBC访问。注意,必须将ODBC二进制代码(许多情况下还包括数据库客户机代码)加载到使用该驱动程序的每个客户机上。因此,这种类型的驱动程序最适合于企业网(这种网络上客户机的安装不是主要问题),或者是用Java编写的三层结构的应用程序服务器代码。   (2)本地API   这种类型的驱动程序把客户机API上的JDBC调用转换为Oracle、Sybase、Informix、DB2或其它DBMS的调用。注意,象桥驱动程序一样,这种类型的驱动程序要求将某些二进制代码加载到每台客户机上。   (3)JDBC网络纯Java驱动程序   这种驱动程序将JDBC转换为与DBMS无关的网络协议,之后这种协议又被某个服务器转换为一种DBMS协议。这种网络服务器中间件能够将它的纯Java客户机连接到多种不同的数据库上。所用的具体协议取决于提供者。通常,这是最为灵活的JDBC驱动程序。有可能所有这种解决方案的提供者都提供适合于Intranet用的产品。为了使这些产品也支持Internet访问,它们必须处理Web所提出的安全性、通过防火墙的访问等方面的额外要求。几家提供者正将JDBC驱动程序加到他们现有的数据库中间件产品中。   (4)本地协议纯Java驱动程序   这种类型的驱动程序将JDBC调用直接转换为DBMS所使用的网络协议。这将允许从客户机机器上直接调用DBMS服务器,是Intranet访问的一个很实用的解决方法。由于许多这样的协议都是专用的,因此数据库提供者自己将是主要来源,有几家提供者已在着手做这件事了。   据专家预计第(3)、(4)类驱动程序将成为从JDBC访问数据库的首方法。第(1)、(2)类驱动程序在直接的纯Java驱动程序还没有上市前会作为过渡方案来使用。对第(1)、(2)类驱动程序可能会有一些变种,这些变种要求有连接器,但通常这些是更加不可取的解决方案。第(3)、(4)类驱动程序提供了Java的所有优点,包括自动安装(例如,通过使用JDBC驱动程序的appletapplet来下载该驱动程序)。   3. JDBC驱动程序的获取   目前已有几十个(1)类的驱动程序,即可与Javasoft桥联合使用的ODBC驱动程序的驱动程序。有大约十多个属于种类(2)的驱动程序是以DBMS的本地API为基础编写的。只有几个属于种类(3)的驱动程序,其首批提供者是SCO、OpenHorizon、Visigenic和WebLogic。此外,JavaSoft和数据库连接的领先提供者Intersolv还合作研制了JDBC-ODBC桥和JDBC驱动程序测试工具包。 如何建立JDBC连接?   Connection 对象代表与数据库的连接。连接过程包括所执行的 SQL 语句和在该连接上所返回的结果。一个应用程序可与单个数据库有一个或多个连接,或者可与许多数据库有连接。   1. 打开连接   与数据库建立连接的标准方法是调用DriverManager.getConnection方法。该方法接受含有某个URL的字符串。DriverManager类(即所谓的JDBC管理层)将尝试找到可与那个URL所代表的数据库进行连接的驱动程序。DriverManager类存有已注册的Driver类的清单。当调用方法getConnection时,它将检查清单中的每个驱动程序,直到找到可与URL中指定的数据库进行连接的驱动程序为止。Driver的方法connect使用这个URL来建立实际的连接。   用户可绕过JDBC管理层直接调用Driver方法。这在以下特殊情况下将很有用:当两个驱动器可同时连接到数据库中,而用户需要明确地选用其中特定的驱动器。但一般情况下,让DriverManager类处理打开连接这种事将更为简单。   下述代码显示如何打开一个与位于URL"jdbc:odbc:wombat"的数据库的连接。所用的用户标识符为"freely",口令为"ec":   String url = "jdbc:odbc:wombat";   Connection con = DriverManager.getConnection(url, "freely", "ec");   2. 一般用法的URL   由于URL常引起混淆,我们将先对一般URL作简单说明,然后再讨论JDBCURL。URL(统一资源定位符)提供在Internet上定位资源所需的信息。可将它想象为一个地址。URL的第一部份指定了访问信息所用的协议,后面总是跟着冒号。常用的协议有"ftp"(代表"文件传输协议")和"http"(代表"超文本传输协议")。如果协议是"file",表示资源是在某个本地文件系统上而非在Internet上(下例用于表示我们所描述的部分;它并非URL的组成部分)。   ftp://Javasoft.com/docs/JDK-1_apidocs.zip   http://Java.sun.com/products/jdk/CurrentRelease   file:/home/haroldw/docs/books/tutorial/summary.html   URL的其余部份(冒号后面的)给出了数据资源所处位置的有关信息。如果协议是file,则URL的其余部份是文件的路径。对于ftp和http协议,URL的其余部份标识了主机并可选地给出某个更详尽的地址路径。例如,以下是JavaSoft主页的URL。该URL只标识了主机:http://Java.sun.com。从该主页开始浏览,就可以进到许多其它的网页中,其中之一就是JDBC主页。JDBC主页的URL更为具体,它具体表示为: http://Java.sun.com/products/jdbc   3. JDBC URL   JDBC URL提供了一种标识数据库的方法,可以使相应的驱动程序能识别该数据库并与之建立连接。实际上,驱动程序编程员将决定用什么JDBC URL来标识特定的驱动程序。用户不必关心如何来形成JDBC URL;他们只须使用与所用的驱动程序一起提供的URL即可。JDBC的作用是提供某些约定,驱动程序编程员在构造他们的JDBC URL时应该遵循这些约定。   由于JDBC URL要与各种不同的驱动程序一起使用,因此这些约定应非常灵活。首先,它们应允许不同的驱动程序使用不同的方案来命名数据库。例如,odbc子协议允许(但并不是要求)URL含有属性值。   其次,JDBC URL应允许驱动程序编程员将一切所需的信息编入其中。这样就可以让要与给定数据库对话的applet打开数据库连接,而无须要求用户去做任何系统管理工作。   最后,JDBC URL应允许某种程度的间接性。也就是说,JDBC URL可指向逻辑主机或数据库名,而这种逻辑主机或数据库名将由网络命名系统动态地转换为实际的名称。这可以使系统管理员不必将特定主机声明为JDBC名称的一部份。网络命名服务(例如DNS、NIS和DCE)有多种,而对于使用哪种命名服务并无限制。 JDBC URL的标准语法如下所示。它由三部分组成,各部分间用冒号分隔: jdbc:<子协遥荆海甲用疲?br>   JDBC URL的三个部分可分解如下:   (1)jdbc协议:JDBC URL中的协议总是jdbc。   (2)<子协议>:驱动程序名或数据库连接机制(这种机制可由一个或多个驱动程序支持)的名称。子协议名的典型示例是"odbc",该名称是为用于指定ODBC风格的数据资源名称的URL专门保留的。例如,为了通过JDBC-ODBC桥来访问某个数据库,可以用如下所示的URL:jdbc:odbc:book。本例中,子协议为"odbc",子名称"book"是本地ODBC数据资源。如果要用网络命名服务(这样JDBC URL中的数据库名称不必是实际名称),则命名服务可以作为子协议。例如,可用如下所示的URL:jdbc:dcenaming:accounts。本例中,该URL指定了本地DCE命名服务应该将数据库名称"accounts"解析为更为具体的可用于连接真实数据库的名称。   (3)<子名称>:种标识数据库的方法。子名称可以依不同的子协议而变化。它还可以有子名称的子名称(含有驱动程序编程员所选的任何内部语法)。使用子名称的目的是为定位数据库提供足够的信息。前例中,因为ODBC将提供其余部份的信息,因此用"book"就已足够。然而,位于远程服务器上的数据库需要更多的信息。例如,如果数据库是通过Internet来访问的,则在JDBC URL中应将网络地址作为子名称的一部份包括进去,且必须遵循如下所示的标准URL命名约定://主机名:端口/子协议。   假设"dbnet"是个用于将某个主机连接到Internet上的协议,则JDBC URL应为:jdbc:dbnet://wombat:356/fred。   4. "odbc"子协议   子协议odbc是一种特殊情况。它是为用于指定ODBC风格的数据资源名称的URL而保留的,并具有下列特性:允许在子名称(数据资源名称)后面指定任意多个属性值。odbc子协议的完整语法为:   jdbc:odbc:<数据资源名称>[;<属性名>=<属性值>],因此,以下都是合法的jdbc:odbc名称:   jdbc:odbc:qeor7   jdbc:odbc:wombat   jdbc:odbc:wombat;CacheSize=20;ExtensionCase=LOWER   jdbc:odbc:qeora;UID=kgh;PWD=fooey   5. 注册子协议   驱动程序编程员可保留某个名称以将之用作JDBC URL的子协议名。当DriverManager类将此名称加到已注册的驱动程序清单中时,为之保留该名称的驱动程序应能识别该名称并与它所标识的数据库建立连接。例如,odbc是为JDBC-ODBC桥而保留的。假设有个Miracle公司,它可能会将"miracle"注册为连接到其Miracle DBMS上的JDBC驱动程序的子协议,从而使其他人都无法使用这个名称。   JavaSoft目前作为非正式代理负责注册JDBC子协议名称。要注册某个子协议名称,请发送电子邮件到下述地址:[email protected]。   6. 发送SQL语句   连接一旦建立,就可用来向它所涉及的数据库传送SQL语句。JDBC对可被发送的SQL语句类型不加任何限制。这就提供了很大的灵活性,即允许使用特定的数据库语句或甚至于非SQL语句。然而,它要求用户自己负责确保所涉及的数据库可以处理所发送的SQL语句,否则将自食其果。例如,如果某个应用程序试图向不支持储存程序的DBMS发送储存程序调用,就会失败并将抛出异常。JDBC要求驱动程序应至少能提供ANSI SQL-2 Entry Level功能才可算是符合JDBC标准TM的。这意味着用户至少可信赖这一标准级别的功能。   JDBC提供了三个类,用于向数据库发送SQL语句。Connection接口中的三个方法可用于创建这些类的实例。下面列出这些类及其创建方法:   (1)Statement:由方法createStatement所创建。Statement对象用于发送简单的SQL语句。   (2)PreparedStatement:由方法prepareStatement所创建。PreparedStatement对象用于发送带有一个或多个输入参数(IN参数)的SQL语句。PreparedStatement拥有一组方法,用于设置IN参数的值。执行语句时,这些IN参数将被送到数据库中。PreparedStatement的实例扩展了Statement,因此它们都包括了Statement的方法。PreparedStatement对象有可能比Statement对象的效率更高,因为它已被预编译过并存放在那以供将来使用。   (3)CallableStatement:由方法prepareCall所创建。CallableStatement对象用于执行SQL储存程序─一组可通过名称来调用(就象函数的调用那样)的SQL语句。CallableStatement对象从PreparedStatement中继承了用于处理IN参数的方法,而且还增加了用于处理OUT参数和INOUT参数的方法。   不过通常来说createStatement方法用于简单的SQL语句(不带参数)、prepareStatement方法用于带一个或多个IN参数的SQL语句或经常被执行的简单SQL语句,而prepareCall方法用于调用已储存过程。   7. 事务   事务由一个或多个这样的语句组成:这些语句已被执行、完成并被提交或还原。当调用方法commit或rollback时,当前事务即告就结束,另一个事务随即开始。缺省情况下,新连接将处于自动提交模式。也就是说,当执行完语句后,将自动对那个语句调用commit方法。这种情况下,由于每个语句都是被单独提交的,因此一个事务只由一个语句组成。如果禁用自动提交模式,事务将要等到commit或rollback方法被显式调用时才结束,因此它将包括上一次调用commit或rollback方法以来所有执行过的语句。对于第二种情况,事务中的所有语句将作为组来提交或还原。   方法commit使SQL语句对数据库所做的任何更改成为永久性的,它还将释放事务持有的全部锁。而方法rollback将弃去那些更改。有时用户在另一个更改生效前不想让此更改生效。这可通过禁用自动提交并将两个更新组合在一个事务中来达到。如果两个更新都是成功,则调用commit方法,从而使两个更新结果成为永久性的;如果其中之一或两个更新都失败了,则调用rollback方法,以将值恢复为进行更新之前的值。   大多数JDBC驱动程序都支持事务。事实上,符合JDBC的驱动程序必须支持事务。DatabaseMetaData给出的信息描述DBMS所提供的事务支持水平。   8. 事务隔离级别   如果DBMS支持事务处理,它必须有某种途径来管理两个事务同时对一个数据库进行操作时可能发生的冲突。用户可指定事务隔离级别,以指明DBMS应该花多大精力来解决潜在冲突。例如,当事务更改了某个值而第二个事务却在该更改被提交或还原前读取该值时该怎么办。   假设第一个事务被还原后,第二个事务所读取的更改值将是无效的,那么是否可允许这种冲突?JDBC用户可用以下代码来指示DBMS允许在值被提交前读取该值("dirty读取"),其中con是当前连接: con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);   事务隔离级别越高,为避免冲突所花的精力也就越多。Connection接口定义了五级,其中最低级别指定了根本就不支持事务,而最高级别则指定当事务在对某个数据库进行操作时,任何其它事务不得对那个事务正在读取的数据进行任何更改。通常,隔离级别越高,应用程序执行的速度也就越慢(由于用于锁定的资源耗费增加了,而用户间的并发操作减少了)。在决定采用什么隔离级别时,开发人员必须在性能需求和数据一致性需求之间进行权衡。当然,实际所能支持的级别取决于所涉及的DBMS的功能。   当创建Connection对象时,其事务隔离级别取决于驱动程序,但通常是所涉及的数据库的缺省值。用户可通过调用setIsolationLevel方法来更改事务隔离级别。新的级别将在该连接过程的剩余时间内生效。要想只改变一个事务的事务隔离级别,必须在该事务开始前进行设置,并在该事务结束后进行复位。我们不提倡在事务的中途对事务隔离级别进行更改,因为这将立即触发commit方法的调用,使在此之前所作的任何更改变成永久性的。 JDBC驱动管理内幕是怎么样的?   DriverManager 类是 JDBC 的管理层,作用于用户和驱动程序之间。它跟踪可用的驱动程序,并在数据库和相应驱动程序之间建立连接。另外,DriverManager类也处理诸如驱动程序登录时间限制及登录和跟踪消息的显示等事务。   对于简单的应用程序,一般程序员需要在此类中直接使用的唯一方法是DriverManager.getConnection。正如名称所示,该方法将建立与数据库的连接。JDBC允许用户调用DriverManager的方法getDriver、getDrivers和registerDriver及Driver的方法connect。但多数情况下,让DriverManager类管理建立连接的细节为上策。   1. 跟踪可用驱动程序   DriverManager类包含一列Driver类,它们已通过调用方法DriverManager.registerDriver对自己进行了注册。所有Driver类都必须包含有一个静态部分。它创建该类的实例,然后在加载该实例时DriverManager类进行注册。这样,用户正常情况下将不会直接调用DriverManager.registerDriver;而是在加载驱动程序时由驱动程序自动调用。加载Driver类,然后自动在DriverManager中注册的方式有两种:   (1)调用方法Class.forName   这将显式地加载驱动程序类。由于这与外部设置无关,因此推荐使用这种加载驱动程序的方法。以下代码加载类acme.db.Driver:Class.forName("acme.db.Driver")。   如果将acme.db.Driver编写为加载时创建实例,并调用以该实例为参数的DriverManager.registerDriver(本该如此),则它在DriverManager的驱动程序列表中,并可用于创建连接。   (2)将驱动程序添加到Java.lang.System的属性jdbc.drivers中   这是一个由DriverManager类加载的驱动程序类名的列表,由冒号分隔:初始化DriverManager类时,它搜索系统属性jdbc.drivers,如果用户已输入了一个或多个驱动程序,则DriverManager类将试图加载它们。以下代码说明程序员如何在~/.hotJava/properties中输入三个驱动程序类(启动时,HotJava将把它加载到系统属性列表中):   jdbc.drivers=foo.bah.Driver:wombat.sql.Driver:bad.test.ourDriver;   对DriverManager方法的第一次调用将自动加载这些驱动程序类。注意:加载驱动程序的第二种方法需要持久的预设环境。如果对这一点不能保证,则调用方法Class.forName显式地加载每个驱动程序就显得更为安全。这也是引入特定驱动程序的方法,因为一旦DriverManager类被初始化,它将不再检查jdbc.drivers属性列表。   在以上两种情况中,新加载的Driver类都要通过调用DriverManager.registerDriver类进行自我注册。如上所述,加载类时将自动执行这一过程。   由于安全方面的原因,JDBC管理层将跟踪哪个类加载器提供哪个驱动程序。这样,当DriverManager类打开连接时,它仅使用本地文件系统或与发出连接请求的代码相同的类加载器提供的驱动程序。   2. 建立连接   加载Driver类并在DriverManager类中注册后,它们即可用来与数据库建立连接。当调用DriverManager.getConnection方法发出连接请求时,DriverManager将检查每个驱动程序,查看它是否可以建立连接。   有时可能有多个JDBC驱动程序可以与给定的URL连接。例如,与给定远程数据库连接时,可以使用JDBC-ODBC桥驱动程序、JDBC到通用网络协议驱动程序或数据库厂商提供的驱动程序。在这种情况下测试驱动程序的顺序至关重要,因为DriverManager将使用它所找到的第一个可以成功连接到给定URL的驱动程序。   首先DriverManager试图按注册的顺序使用每个驱动程序(jdbc.drivers中列出的驱动程序总是先注册)。它将跳过代码不可信任的驱动程序,除非加载它们的源与试图打开连接的代码的源相同。它通过轮流在每个驱动程序上调用方法Driver.connect,并向它们传递用户开始传递给方法DriverManager.getConnection的URL来对驱动程序进行测试,然后连接第一个认出该URL的驱动程序。这种方法初看起来效率不高,但由于不可能同时加载数十个驱动程序,因此每次连接实际只需几个过程调用和字符串比较。   以下代码是通常情况下用驱动程序(例如JDBC-ODBC桥驱动程序)建立连接所需所有步骤的示例: Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");//加载驱动程序 String url = "jdbc:odbc:fred"; DriverManager.getConnection(url,"userID","passwd"); 如何利用JDBC发送SQL语句?   Statement对象用于将SQL语句发送到数据库中。实际上有三种Statement对象,它们都作为在给定连接上执行SQL语句的包容器:Statement、PreparedStatement(它从Statement继承而来)和CallableStatement(它从PreparedStatement继承而来)。它们都专用于发送特定类型的SQL语句:Statement对象用于执行不带参数的简单SQL语句;PreparedStatement对象用于执行带或不带IN参数的预编译SQL语句;CallableStatement对象用于执行对数据库已存储过程的调用。   Statement接口提供了执行语句和获取结果的基本方法;PreparedStatement接口添加了处理IN参数的方法;而CallableStatement添加了处理OUT参数的方法。   1. 创建Statement对象   建立了到特定数据库的连接之后,就可用该连接发送SQL语句。Statement对象用Connection的方法createStatement创建,如下列代码段中所示: Connection con = DriverManager.getConnection(url,"sunny",""); Statement stmt = con.createStatement();   为了执行Statement对象,被发送到数据库的SQL语句将被作为参数提供给Statement的方法:   ResultSet rs = stmt.executeQuery("SELECT a,b,c FROM Table2");   2. 使用Statement对象执行语句   Statement接口提供了三种执行SQL语句的方法:executeQuery、executeUpdate和execute。使用哪一个方法由SQL语句所产生的内容决定。   方法executeQuery用于产生单个结果集的语句,例如SELECT语句。方法executeUpdate用于执行INSERT、UPDATE或DELETE语句以及SQL DDL(数据定义语言)语句,例如CREATE TABLE和DROP TABLE。INSERT、UPDATE或DELETE语句的效果是修改表中零行或多行中的一列或多列。executeUpdate的返回值是一个整数,指示受影响的行数(即更新计数)。对于CREATE TABLE或DROP TABLE等不操作行的语句,executeUpdate的返回值总为零。   执行语句的所有方法都将关闭所调用的Statement对象的当前打开结果集(如果存在)。这意味着在重新执行Statement对象之前,需要完成对当前ResultSet对象的处理。应注意,继承了Statement接口中所有方法的PreparedStatement接口都有自己的executeQuery、executeUpdate和execute方法。Statement对象本身不包含SQL语句,因而必须给Statement.execute方法提供SQL语句作为参数。PreparedStatement对象并不需要SQL语句作为参数提供给这些方法,因为它们已经包含预编译SQL语句。   CallableStatement对象继承这些方法的PreparedStatement形式。对于这些方法的PreparedStatement或CallableStatement版本,使用查询参数将抛出SQLException。   3. 语句完成   当连接处于自动提交模式时,其中所执行的语句在完成时将自动提交或还原。语句在已执行且所有结果返回时,即认为已完成。对于返回一个结果集的executeQuery方法,在检索完ResultSet对象的所有行时该语句完成。对于方法executeUpdate,当它执行时语句即完成。但在少数调用方法execute的情况中,在检索所有结果集或它生成的更新计数之后语句才完成。   有些DBMS将已存储过程中的每条语句视为独立的语句;而另外一些则将整个过程视为一个复合语句。在启用自动提交时,这种差别就变得非常重要,因为它影响什么时候调用commit方法。在前一种情况中,每条语句单独提交;在后一种情况中,所有语句同时提交。   4. 关闭Statement对象   Statement对象将由Java垃圾收集程序自动关闭。而作为一种好的编程风格,应在不需要Statement对象时显式地关闭它们。这将立即释放DBMS资源,有助于避免潜在的内存问题。   5. 使用方法execute   execute方法应该仅在语句能返回多个ResultSet对象、多个更新计数或ResultSet对象与更新计数的组合时使用。当执行某个已存储过程或动态执行未知SQL字符串(即应用程序程序员在编译时未知)时,有可能出现多个结果的情况,尽管这种情况很少见。例如,用户可能执行一个已存储过程,并且该已存储过程可执行更新,然后执行选择,再进行更新,再进行选择,等等。通常使用已存储过程的人应知道它所返回的内容。   因为方法execute处理非常规情况,所以获取其结果需要一些特殊处理并不足为怪。例如,假定已知某个过程返回两个结果集,则在使用方法execute执行该过程后,必须调用方法getResultSet获得第一个结果集,然后调用适当的getXXX方法获取其中的值。要获得第二个结果集,需要先调用getMoreResults方法,然后再调用getResultSet方法。如果已知某个过程返回两个更新计数,则首先调用方法getUpdateCount,然后调用getMoreResults,并再次调用getUpdateCount。   对于不知道返回内容,则情况更为复杂。如果结果是ResultSet对象,则方法execute返回true;如果结果是Javaint,则返回false。如果返回int,则意味着结果是更新计数或执行的语句是DL命令。在调用方法execute之后要做的第一件事情是调用getResultSet或getUpdateCount。调用方法getResultSet可以获得两个或多个ResultSet对象中第一个对象;或调用方法getUpdateCount可以获得两个或多个更新计数中第一个更新计数的内容。   当SQL语句的结果不是结果集时,则方法getResultSet将返回null。这可能意味着结果是一个更新计数或没有其它结果。在这种情况下,判断null真正含义的唯一方法是调用方法getUpdateCount,它将返回一个整数。这个整数为调用语句所影响的行数;如果为-1则表示结果是结果集或没有结果。如果方法getResultSet已返回null(表示结果不是ResultSet对象),则返回值-1表示没有其它结果。也就是说,当下列条件为真时表示没有结果(或没有其它结果):   ((stmt.getResultSet()==null)&&(stmt.getUpdateCount()==-1))   如果已经调用方法getResultSet并处理了它返回的ResultSet对象,则有必要调用方法getMoreResults以确定是否有其它结果集或更新计数。如果getMoreResults返回true,则需要再次调用getResultSet来检索下一个结果集。如上所述,如果getResultSet返回null,则需要调用getUpdateCount来检查null是表示结果为更新计数还是表示没有其它结果。   当getMoreResults返回false时,它表示该SQL语句返回一个更新计数或没有其它结果。因此需要调用方法getUpdateCount来检查它是哪一种情况。在这种情况下,当下列条件为真时表示没有其它结果:   ((stmt.getMoreResults()==false)&&(stmt.getUpdateCount()==-1))   下面的代码演示了一种方法用来确认已访问调用方法execute所产生的全部结果集和更新计数: stmt.execute(queryStringWithUnknownResults); while(true){ introwCount=stmt.getUpdateCount(); if(rowCount>0){//它是更新计数 System.out.println("Rows changed="+count); stmt.getMoreResults(); continue; } if(rowCount==0){//DDL命令或0个更新 System.out.println("No rows changed or statement was DDL command"); stmt.getMoreResults(); continue; } //执行到这里,证明有一个结果集 //或没有其它结果 ResultSet rs=stmt.getResultSet(); if(rs!=null){ ...//使用元数据获得关于结果集列的信息 while(rs.next()){ ...//处理结果 stmt.getMoreResults(); continue; } break;//没有其它结果 如何获得SQL语句的执行结果?   ResultSet包含符合SQL语句中条件的所有行,并且它通过一套get方法(这些get方法可以访问当前行中的不同列)提供了对这些行中数据的访问。ResultSet.next方法用于移动到ResultSet中的下一行,使下一行成为当前行。   下面的代码段是执行SQL语句的示例。该SQL语句将返回行集合,其中列1为int,列2为String,而列3则为字节数组: Java.sql.Statementstmt=conn.createStatement(); ResultSet r=stmt.executeQuery("SELECT a,b,c FROM Table1"); while(r.next()){ //打印当前行的值。 Int i=r.getInt("a"); String s=r.getString("b"); Float f=r.getFloat("c"); System.out.println("ROW="+i+" "+s+" "+f); }   1. 行和光标   ResultSet维护指向其当前数据行的光标。每调用一次next方法,光标向下移动一行。   最初它位于第一行之前,因此第一次调用next将把光标置于第一行上,使它成为当前行。随着每次调用next导致光标向下移动一行,按照从上至下的次序获取ResultSet行。   在ResultSet对象或其父辈Statement对象关闭之前,光标一直保持有效。在SQL中,结果表的光标是有名字的。如果数据库允许定位更新或定位删除,则需要将光标的名字作为参数提供给更新或删除命令。可通过调用方法getCursorName获得光标名。   DatabaseMetaData.supportsPositionedDelete和supportsPositionedUpdate方法来检查特定连接是否支持这些操作。当DBMS支持定位更新和删除操作时,DBMS/驱动程序必须确保适当锁定选定行,以使定位更新不会导致更新异常或其它并发问题。   2. 列   方法getXXX提供了获取当前行中某列值的途径。在每一行内,可按任何次序获取列值。但为了保证可移植性,应该从左至右获取列值,并且一次性地读取列值。   列名或列号可用于标识要从中获取数据的列。例如,如果ResultSet对象rs的第二列名为"title",并将值存储为字符串,则下列任一代码将获取存储在该列中的值:   String s=rs.getString("title");   String s=rs.getString(2);   注意列是从左至右编号的,并且从列1开始。同时,用作getXXX方法的输入的列名不区分大小写。   提供使用列名这个选项的目的是为了让在查询中指定列名的用户可使用相同的名字作为getXXX方法的参数。另一方面,如果select语句未指定列名(例如在"select * from table1"中或列是导出的时),则应该使用列号。这些情况下,用户将无法确切知道列名。   有些情况下,SQL查询返回的结果集中可能有多个列具有相同的名字。如果列名用作getXXX方法的参数,则getXXX将返回第一个匹配列名的值。因而,如果多个列具有相同的名字,则需要使用列索引来确保检索了正确的列值。这时,使用列号效率要稍微高一些。   关于ResultSet中列的信息,可通过调用方法ResultSet.getMetaData得到。返回的ResultSetMetaData对象将给出其ResultSet对象各列的编号、类型和属性。   如果列名已知,但不知其索引,则可用方法findColumn得到其列号。   3. 数据类型和转换   对于getXXX方法,JDBC驱动程序试图将基本数据转换成指定Java类型,   然后返回适合的Java值。例如,如果getXXX方法为getString,而基本数据库中数据类型为VARCHAR,则JDBC驱动程序将把VARCHAR转换成JavaString。getString的返回值将为JavaString对象。   4. 对非常大的行值使用流   ResultSet可以获取任意大的LONGVARBINARY或LONGVARCHAR数据。方法getBytes和getString将数据返回为大的块(最大为Statement.getMaxFieldSize的返回值)。但是,以较小的固定块获取非常大的数据可能会更方便,而这可通过让ResultSet类返回Java.io.Input流来完成。从该流中可分块读取数据。注意:必须立即访问这些流,因为在下一次对ResultSet调用getXXX时它们将自动关闭(这是由于基本实现对大块数据访问有限制)。   JDBCAPI具有三个获取流的方法,分别具有不同的返回值:   ·getBinaryStream:返回只提供数据库原字节而不进行任何转换的流。   ·getAsciiStream返回提供单字节ASCII字符的流。   ·getUnicodeStream返回提供双字节Unicode字符的流。   注意:它不同于Java流,后者返回无类型字节并可(例如)通用于ASCII和Unicode字符。下列代码演示了getAsciiStream的用法: Java.sql.Statementstmt=con.createStatement(); ResultSet r=stmt.executeQuery("SELECT x FROM Table2"); //现在以4K块大小获取列1结果: byte buff=newbyte[4096]; while(r.next()){ Java.io.InputStream fin=r.getAsciiStream(1); for(;;){ intsize=fin.read(buff); if(size==-1){//到达流末尾 break; } //将新填充的缓冲区发送到ASCII输出流: output.write(buff,0,size); } }   5. NULL结果值   要确定给定结果值是否是JDBC NULL,必须先读取该列,然后使用ResultSet.wasNull 方法检查该次读取是否返回JDBC NULL。   当使用ResultSet.getXXX方法读取JDBC NULL时,方法wasNull将返回下列值之一:   (1)Javanull值   对于返回Java对象的getXXX方法(例如getString、getBigDecimal、getBytes、getDate、getTime、getTimestamp、getAsciiStream、getUnicodeStream、getBinaryStream、getObject等)。   (2)零值:对于getByte、getShort、getInt、getLong、getFloat和getDouble。   (3)false值:对于getBoolean。   6. 可选结果集或多结果集   通常使用executeQuery(它返回单个ResultSet)或executeUpdate(它可用于任何数据库修改语句,并返回更新行数)可执行SQL语句。但有些情况下,应用程序在执行语句之前不知道该语句是否返回结果集。此外,有些已存储过程可能返回几个不同的结果集和/或更新计数。   为了适应这些情况,JDBC提供了一种机制,允许应用程序执行语句,然后处理由结果集和更新计数组成的任意集合。这种机制的原理是首先调用一个完全通用的execute方法,然后调用另外三个方法,getResultSet、getUpdateCount和getMoreResults。这些方法允许应用程序一次一个地研究语句结果,并确定给定结果是ResultSet还是更新计数。   用户不必关闭ResultSet;当产生它的Statement关闭、重新执行或用于从多结果序列中获取下一个结果时,该ResultSet将被Statement自动关闭。  基于JDBC有哪些数据库通用访问方法?   1. 通用数据库Bean设计   本实例中对数据库连接和执行SQL语句等通用数据库操作进行了封装,通过实现DBConnBean和DBQueryBean两个JavaBean来完成上述功能。其中DBConnBean负责Java应用程序和数据库的连接;DBQueryBean提供了一组执行标准SQL的功能,可以实现标准SQL完成的所有功能。其功能代码分别如下所示:   ① DBConnBean.Java的源代码如下所示: package dbaccess; import Java.sql.*; import Java.util.*; import Java.io.*; public class DBConnBean implements Serializable{ private String DBDriver = "sun.jdbc.odbc.JdbcOdbcDriver"; private String DBHost = "127.0.0.1"; private String DBName = "demo"; private String conp = "jdbc:odbc:db_demo"; private String username = ""; private String password = ""; private boolean xdebug = true; public Connection con = null; public String sql = null; Statement stmt = null; public ResultSet result = null; private int affectedRows = 0; public DBConnBean() { xdebug = true; con = null; sql = null; } public Connection Connect() throws Exception { String msg = null; try { Class.forName(DBDriver).newInstance(); } catch(Exception e) { msg = "加载数据库驱动失败"; if (xdebug) msg += "(驱动'"+DBDriver+"')"; throw new Exception(msg); } try { String conStr = conp; con = DriverManager.getConnection(conStr,username,password); } catch(SQLException e) { msg = "!!数据库连接失败"; if (xdebug) { msg += "(错误信息='" + e.getMessage()+"' SQL状态值='" + e.getSQLState()+"' 错误代码='" + e.getErrorCode()+"')"; } throw new Exception(msg); } return con; } protected void finalize() throws Throwable { super.finalize(); if (stmt != null) stmt.close(); if (result != null) result.close(); } //最近一次对数据库查询受影响的行数 public int getAffectedRows() { return affectedRows; } public Connection getCon() { return con; } public String getConp() { return conp; } public String getDBDriver() { return DBDriver; } public String getDBName() { return DBName; } public boolean getDebug() { return xdebug; } public String getPassword() { return password; } public ResultSet getResult() { return result; } public String getSql() { return sql; } public String getUsername() { return username; } public void over() throws Throwable { finalize(); } public ResultSet query() throws Exception { result = null; affectedRows = 0; if (con == null) Connect(); if (stmt == null) stmt = con.createStatement(); if (sql.substring(0,6).equalsIgnoreCase("select")) { result = stmt.executeQuery(sql); } else { affectedRows = stmt.executeUpdate(sql); } return result; } public ResultSet query(String s) throws Exception { sql = s; return query(); } public void setDBDriver(String s) { DBDriver = s; } public void setDebug(boolean b) { xdebug = b; } public void setgetConp(String s) { conp = s; } public void setgetDBName(String s) { DBName = s; } public void setgetUsername(String s) { username = s; } public void setPassword(String s) { password = s; } public void setSql(String s) { sql = s; } } ② DBQueryBean.Java的源代码如下所示: package dbaccess; import Java.sql.*; import Java.util.*; import Java.io.*; import Java.lang.reflect.*; public class DBQueryBean implements Serializable { DBConnBean dbc; String sql = null; int rowcount = 0; int colcount = 0; // int limitcount = 0; Vector result = null; public String _WATCH = ""; public DBQueryBean() { dbc = new DBConnBean(); try { dbc.Connect(); } catch(Exception e) { handleException(e); } } protected void finalize() throws Throwable { super.finalize(); if (dbc != null) dbc.over(); if (result != null) result.removeAllElements(); } public String get(int row, int col) { if (result==null || row >= result.size()) return null; String r[] = (String[])result.elementAt(row); if (col >= Java.lang.reflect.Array.getLength(r)) return null; return r[col]; } public int getAffRows() { return dbc.getAffectedRows(); } public int getColumncount() { return colcount; } public String[] getRow(int row) { if (result==null || row >= result.size()) return null; return (String [])result.elementAt(row); /*String ret[] = new String[colcount]; Vector r = (Vector)result.elementAt(row); for (int i=0; i<colcount; i++) ret[i] = (String)r.elementAt(i); return ret;*/ } public int getRowcount() { return rowcount; } public void handleException(Exception e) { _WATCH = e.getMessage(); } public void init() { rowcount = 0; colcount = 0; // limitcount = 0; result = null; } public void over() throws Throwable { finalize(); } public int query(String sql) { result = new Vector(); int ret = 0; try { ResultSet rs = dbc.query(sql); if (rs == null) { ret = dbc.getAffectedRows(); } else { ResultSetMetaData rm = rs.getMetaData(); colcount = rm.getColumnCount(); while (rs.next()) { String row[] = new String[colcount]; for (int i=0; i<colcount; i++) row[i] = rs.getString(i+1); result.addElement(row); rowcount++; } rs.close(); // to release the resource. ret = result.size(); } } catch(Exception e) { handleException(e); return -1; } return ret; } }   2. 数据库表结构   本实例中主要出现了三个数据库表,表名和字段分别如下所示:   计划采购表:jhcg_table 字段名称 中文名称 类型 长度 Goods_no 物品编号 vchar 10 Goods_name 物品名称 Vchar 50 Amount 采购数量 Int Price 采购单价 float Gold 币种 Vchar 15 Units 单位 Vchar 10 Date 时间 Date Remark 备注 vchar 100   库存统计表:kctj_table 字段名称 中文名称 类型 长度 Goods_no 物品编号 Vchar 10 Goods_name 物品名称 Vchar 50 amount 库存数量 Int Date 时间 Date remark 备注 Vchar 100   实际采购表:sjcg_table 字段名称 中文名称 类型 长度 Goods_no 物品编号 Vchar 10 Goods_name 物品名称 Vchar 50 Amount 采购数量 Int Price Price 采购单价 Float Gold 币种 Vchar 15 Units 采购单位 Vchar 10 Date 时间 Date Remark 备注 vchar 100   其中业务逻辑非常简单,即根据计划采购表和库存统计表生成实际采购表。同时,对各表完成数据库的增、删、改、查等通用操作。   3. JSP设计   ① 插入操作   完成对数据库表的记录插入功能,其中计划采购表的插入主页面(insert_jhcg.htm)为: 图1 计划采购表插入主页面   insert_jhcg.htm将用户输入传送给demo_insert_jhcg.jsp,完成插入操作。改jsp文件的功能代码为: <html> <body> <jsp:useBean id="DBConn" class="dbaccess.DBConnBean" scope="page"/> <jsp:useBean id="DBBean" class="dbaccess.DBQueryBean" scope="page"/> <hr> <!--test JavaBean--> <% if (DBConn == null||DBBean == null){ out.println("JavaBean not found!"); return; } %> <!--try db_demo connection--> <% try{ DBConn.Connect(); }catch(Exception e){ out.println(e.getMessage()); } %> <!--execute sql statement--> <% String insGoodno = request.getParameter("ed_jhcg_no"); String insGoodname = request.getParameter("ed_jhcg_name"); int insAmount = (Integer.valueOf(request.getParameter("ed_jhcg_amount"))).intValue(); float insPrice = (Float.valueOf(request.getParameter("ed_jhcg_price"))).floatValue(); String insGold = request.getParameter("ed_jhcg_gold"); String insUnit = request.getParameter("ed_jhcg_unit"); String insRemark = request.getParameter("ed_jhcg_remark"); String sqlStatement = "insert into jhcg_table(good_no,good_name,amount, price,gold,unit,remark) values("+"'"+insGoodno+"'"+","+"'"+insGoodname+"'"+", "+insAmount+","+insPrice+","+"'"+insGold+"'"+","+"'"+insUnit+"'"+","+"'"+ insRemark+"'"+")"; try{ DBBean.query(sqlStatement); }catch(Exception e){ out.println(e.getMessage()); } %> <a href="demo_main.htm">Records inserted...Click here to return</a></p> </body> </html>   ② 查询操作   该查询主页面主要提供对三个数据库表的条件查询功能,如下图所示: 图2 查询主页面   query.htm将用户选择查询的数据库表和查询条件发送给demo_query.jsp,由jsp文件完成数据库查询操作和查询结果集的返回及显示,其功能代码如下: <html> <body> <% String sqlStatement; String sqlField = ""; String whichTable = ""; String whereClause = ""; String queryNo = ""; String queryName = ""; %> <jsp:useBean id="DBConn" class="dbaccess.DBConnBean" scope="page"/> <jsp:useBean id="DBBean" class="dbaccess.DBQueryBean" scope="page"/> <hr> <!--test JavaBean--> <% if (DBConn == null||DBBean == null){ out.println("JavaBean not found!"); return; } %> <!--try db_demo connection--> <% try{ DBConn.Connect(); }catch(Exception e){ out.println(e.getMessage()); } %> <!--prepare sql statement--> <% String queryRequest = request.getParameter("rb_request"); //out.println("queryRequest:"+queryRequest); String whichCB = ""; if (queryRequest.equals("1")){ whichCB = "ck_jhcg"; whichTable = "jhcg_table"; queryNo = request.getParameter("ed_jhcg_no"); queryName = request.getParameter("ed_jhcg_name"); if (!queryNo.equals("")) whereClause = " where good_no="+"'"+queryNo+"'"; if (!queryName.equals("")){ if (!queryNo.equals("")) whereClause += " and good_name="+"'"+queryName+"'"; else whereClause = " where good_name="+"'"+queryName+"'"; } } if (queryRequest.equals("2")){ whichCB = "ck_kctj"; whichTable = "kctj_table"; queryNo = request.getParameter("ed_kctj_no"); queryName = request.getParameter("ed_kctj_name"); if (!queryNo.equals("")) whereClause = " where good_no="+"'"+queryNo+"'"; if (!queryName.equals("")){ if (!queryNo.equals("")) whereClause += " and good_name="+"'"+queryName+"'"; else whereClause = " where good_name="+"'"+queryName+"'"; } } if (queryRequest.equals("3")){ whichCB = "ck_sjcg"; whichTable = "sjcg_table"; queryNo = request.getParameter("ed_sjcg_no"); queryName = request.getParameter("ed_sjcg_name"); if (!queryNo.equals("")) whereClause = " where good_no="+"'"+queryNo+"'"; if (!queryName.equals("")){ if (!queryNo.equals("")) whereClause += " and good_name="+"'"+queryName+"'"; else whereClause = " where good_name="+"'"+queryName+"'"; } } String[] printTitle = request.getParameterValues(whichCB); %> <!--create query sql statement--> <% sqlStatement = "select "; for(int i = 0;i<printTitle.length;i++){ sqlField += printTitle[i]+","; } sqlStatement += sqlField.substring(0,sqlField.length()-1)+" from "+whichTable; if (!whereClause.equals("")) sqlStatement += whereClause; %> <!--show query response--> <% try{ DBBean.query(sqlStatement); }catch(Exception e){ out.println("Database Error!"); } int rows = DBBean.getRowcount(); int cols = DBBean.getColumncount(); %> <Table align="center" width="80%" border=1> <tr align=center> <% for(int i = 0;i < printTitle.length;i++){ out.println("<td><b>"); out.println(printTitle[i]); out.println("</b></td>"); } %> </tr> <% for (int i = 0;i < rows;i++){ out.println("<tr>"); for (int j = 0;j < cols;j++) out.println("<td>"+DBBean.get(i,j)+"</td>"); out.println("</tr>"); } %> </Table> <br> <hr> <a href="demo_main.htm">Click here to return</a></p> </body> </html>   ③ 生成实际采购表   生成数据库表是一个隐式操作,程序根据计划采购表和库存统计表的相应字段生成实际采购表,不需要用户的任何输入,其功能代码如下(demo_create.jsp): <%@page import="Java.util.*"%> <html> <body> <jsp:useBean id="DBConn" class="dbaccess.DBConnBean" scope="page"/> <jsp:useBean id="DBBean" class="dbaccess.DBQueryBean" scope="page"/> <hr> <!--test JavaBean--> <% if (DBConn == null||DBBean == null){ out.println("JavaBean not found!"); return; } %> <!--try db_demo connection--> <% try{ DBConn.Connect(); }catch(Exception e){ out.println(e.getMessage()); } %> <!--prepare sql statement--> <% int amount_jhcg,amount_kctj; Vector updateRs = new Vector(); DBBean.query("delete * from sjcg_table"); //delete all old records in sjcg_table DBBean.query("select jhcg_table.good_no,jhcg_table.good_name,jhcg_table.amount,kctj_table.amount,jhcg_table.unit from jhcg_table left join kctj_table on kctj_table.good_no=jhcg_table.good_no"); int rows = DBBean.getRowcount(); int cols = DBBean.getColumncount(); for (int i = 0;i < rows;i++){ String record[] = new String[4]; record[0] = DBBean.get(i,0); record[1] = DBBean.get(i,1); amount_jhcg = (Integer.valueOf(DBBean.get(i,2))).intValue(); if (DBBean.get(i,3) == null) amount_kctj = 0; else amount_kctj = (Integer.valueOf(DBBean.get(i,3))).intValue(); record[2] = Integer.toString(amount_jhcg - amount_kctj); record[3] = DBBean.get(i,4); updateRs.addElement(record); } for (int i = 0;i < rows;i++){ String insRecord[] = (String [])updateRs.elementAt(i); String insGoodno,insGoodname,insUnit,insAmount; insGoodno = insRecord[0]; insGoodname = insRecord[1]; insAmount = insRecord[2]; insUnit = insRecord[3]; String sqlStatement = "insert into sjcg_table(good_no,good_name,amount,unit) values?quot;+"'"+insGoodno+"'"+","+"'"+insGoodname+"'"+","+insAmount+","+"'"+insUnit+"'"+")"; DBBean.query(sqlStatement); DBBean.query("delete * from sjcg_table where amount<=0"); } %> <a href="demo_main.htm">Database created...Click here to return</a></p> </body> </html>   上述的开发工具综合应用介绍了基于Java开发电子商务应用系统的全过程,包括应用开发平台搭建、业务流程分析、JavaBean封装和JSP开发等内容,其中JSP开发中涉及到了通用SQL(查询和插入数据库表)和游标操作(生成实际采购表),基本可以完成任何网络数据库应用的需求。本实例基本上可以将前面介绍的基于Java的电子商务开发技术串接起来,指导读者进行电子商务应用开发。 如何在JSP中实现分页显示?   分页显示是Web数据库应用中经常需要遇到的问题,当用户的数据库查询结果远远超过了计算机屏幕的显示能力的时候,我们该如何合理的将数据呈现给用户呢?答案就是数据库分页显示,可以完美的解决上述问题。下面是一个数据库分页操作的通用实例,对任何数据库平台上的分页功能都有很好的借鉴意义。 <%@ page contentType="text/html;charset=8859_1" %> <% //变量声明 Java.sql.Connection sqlCon; //数据库连接对象 Java.sql.Statement sqlStmt; //SQL语句对象 Java.sql.ResultSet sqlRst; //结果集对象 Java.lang.String strCon; //数据库连接字符串 Java.lang.String strSQL; //SQL语句 int intPageSize; //一页显示的记录数 int intRowCount; //记录总数 int intPageCount; //总页数 int intPage; //待显示页码 Java.lang.String strPage; int i; //设置一页显示的记录数 intPageSize = 2; //取得待显示页码 strPage = request.getParameter("page"); if(strPage==null){//表明在QueryString中没有page这一个参数,此时显示第一页数据 intPage = 1; } else{//将字符串转换成整型 intPage = Java.lang.Integer.parseInt(strPage); if(intPage<1) intPage = 1; } //装载JDBC驱动程序 Java.sql.DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); //设置数据库连接字符串 strCon = "jdbc:oracle:thin:@linux:1521:ora4cweb"; //连接数据库 sqlCon = Java.sql.DriverManager.getConnection(strCon,"hzq","hzq"); //创建一个可以滚动的只读的SQL语句对象 sqlStmt = sqlCon.createStatement(Java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE,Java.sql.ResultSet.CONCUR_READ_ONLY); //准备SQL语句 strSQL = "select name,age from test"; //执行SQL语句并获取结果集 sqlRst = sqlStmt.executeQuery(strSQL); //获取记录总数 sqlRst.last(); intRowCount = sqlRst.getRow(); //记算总页数 intPageCount = (intRowCount+intPageSize-1) / intPageSize; //调整待显示的页码 if(intPage>intPageCount) intPage = intPageCount; %> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=gb2312"> <title>JSP数据库操作例程 - 数据分页显示 - JDBC 2.0 - Oracle</title> </head> <body> <table border="1" cellspacing="0" cellpadding="0"> <tr> <th>姓名</th> <th>年龄</th> </tr> <% if(intPageCount>0){ //将记录指针定位到待显示页的第一条记录上 sqlRst.absolute((intPage-1) * intPageSize + 1); //显示数据 i = 0; while(i<intPageSize && !sqlRst.isAfterLast()){ %> <tr> <td><%=sqlRst.getString(1)%></td> <td><%=sqlRst.getString(2)%></td> </tr> <% sqlRst.next(); i++; } } %> </table> 第<%=intPage%>页 共<%=intPageCount%>页 <%if(intPage<intPageCount){%><a href="jdbc20-oracle.jsp?page=<%=intPage+1%>">下一页 </a><%}%> <%if(intPage>1){%><a href="jdbc20-oracle.jsp?page=<%=intPage-1%>">上一页</a><%}%> </body> </html> <% //关闭结果集 sqlRst.close(); //关闭SQL语句对象 sqlStmt.close(); //关闭数据库 sqlCon.close(); %> 全面解析JDBC 2002-07-20· ·包路跃··Yesky 上一页 1 2 3 4 5 6 7 8   附录:JDBC TM技术解析   1. JDBCTM的定义   JDBCTM 是一种用于执行 SQL 语句的 JavaTM API,它由一组用 Java 编程语言编写的类和接口组成。JDBC 为工具/数据库开发人员提供了一个标准的API,使他们能够用纯 Java API 来编写数据库应用程序。   有了 JDBC,向各种关系数据库发送 SQL 语句就是一件很容易的事。换言之,有了 JDBC API,就不必为访问 Sybase 数据库专门写一个程序,为访问 Oracle 数据库又专门写一个程序,为访问 Informix 数据库又写另一个程序,等等。您只需用 JDBC API 写一个程序就够了它可向相应数据库发送 SQL 语句。而且,使用 Java 编程语言编写的应用程序,就无须去忧虑要为不同的平台编写不同的应用程序。将Java 和 JDBC 结合起来将使程序员只须写一遍程序就可让它在任何平台上运行。   Java 具有坚固、安全、易于使用、易于理解和可从网络上自动下载等特性,是编写数据库应用程序的杰出语言。所需要的只是 Java应用程序与各种不同数据库之间进行对话的方法。而 JDBC 正是作为此种用途的机制。   JDBC 扩展了 Java 的功能。例如,用 Java 和 JDBC API 可以发布含有 applet 的网页,而该 applet 使用的信息可能来自远程数据库企业也可以用 JDBC 通过 Intranet 将所有职员连到一个或多个内部数据库中(即使这些职员所用的计算机有 Windows、 Macintosh 和UNIX 等各种不同的操作系统)。随着越来越多的程序员开始使用Java 编程语言,对从 Java 中便捷地访问数据库的要求也在日益增加。   MIS 管理员们都喜欢 Java 和 JDBC 的结合,因为它使信息传播变得容易和经济。企业可继续使用它们安装好的数据库,并能便捷地存取信息,即使这些信息是储存在不同数据库管理系统上。新程序的开发期很短。安装和版本控制将大为简化。程序员可只编写一遍应用程序或只更新一次,然后将它放到服务器上,随后任何人就都可得到最新版本的应用程序。对于商务上的销售信息服务, Java 和JDBC 可为外部客户提供获取信息更新的更好方法。   2. JDBC 的用途   简单地说,JDBC 可做三件事:与数据库建立连接、发送 SQL 语句并处理结果。下列代码段给出了以上三步的基本示例: Connection con = DriverManager.getConnection("jdbc:odbc:wombat","login", "password"); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1"); while (rs.next()) { int x = rs.getInt("a"); String s = rs.getString("b"); float f = rs.getFloat("c"); }   上述代码对基于JDBC的数据库访问做了经典的总结,当然,在本小节的后续部分会对它做详尽的分析讲解。   3. JDBC API   JDBC 是个"低级"接口,也就是说,它用于直接调用 SQL 命令。在这方面它的功能极佳,并比其它的数据库连接 API 易于使用,但它同时也被设计为一种基础接口,在它之上可以建立高级接口和工具。高级接口是"对用户友好的"接口,它使用的是一种更易理解和更为方便的 API,这种API在幕后被转换为诸如 JDBC 这样的低级接口。   在关系数据库的"对象/关系"映射中,表中的每行对应于类的一个实例,而每列的值对应于该实例的一个属性。于是,程序员可直接对 Java 对象进行操作;存取数据所需的 SQL 调用将在"掩盖下"自动生成。此外还可提供更复杂的映射,例如将多个表中的行结合进一个 Java 类中。   随着人们对 JDBC 的兴趣日益增涨,越来越多的开发人员一直在使用基于 JDBC 的工具,以使程序的编写更加容易。程序员也一直在编写力图使最终用户对数据库的访问变得更为简单的应用程序。例如应用程序可提供一个选择数据库任务的菜单。任务被选定后,应用程序将给出提示及空白供填写执行选定任务所需的信息。所需信息输入应用程序将自动调用所需的 SQL 命令。在这样一种程序的协助下,即使用户根本不懂 SQL 的语法,也可以执行数据库任务。   4. JDBC与ODBC和其它API的比较   目前,Microsoft 的 ODBC API 可能是使用最广的、用于访问关系数据库的编程接口。它能在几乎所有平台上连接几乎所有的数据库。为什么 Java 不使用 ODBC?对这个问题的回答是:Java 可以使用 ODBC,但最好是在 JDBC 的帮助下以 JDBC-ODBC 桥的形式使用,这一点我们稍后再说。现在的问题已变成:"为什么需要 JDBC"?答案是显然的:ODBC 不适合直接在 Java 中使用,因为它使用 C 语言接口。从Java 调用本地 C 代码在安全性、实现、坚固性和程序的自动移植性方面都有许多缺点。从 ODBC C API 到 Java API 的字面翻译是不可取的。例如,Java 没有指针,而 ODBC 却对指针用得很广泛(包括很容易出错的指针"void *")。您可以将 JDBC 想象成被转换为面向对象接口的 ODBC,而面向对象的接口对 Java 程序员来说较易于接收。   ODBC 很难学。它把简单和高级功能混在一起,而且即使对于简单的查询,其选项也极为复杂。相反,JDBC 尽量保证简单功能的简便性,而同时在必要时允许使用高级功能。启用"纯 Java "机制需要象 JDBC 这样的 Java API。如果使用ODBC,就必须手动地将 ODBC 驱动程序管理器和驱动程序安装在每台客户机上。如果完全用 Java 编写 JDBC 驱动程序则 JDBC 代码在所有 Java 平台上(从网络计算机到大型机)都可以自 动安装、移植并保证安全性。   总之,JDBC API 对于基本的 SQL 抽象和概念是一种自然的 Java 接口。它建立在 ODBC 上而不是从零开始。因此,熟悉 ODBC 的程序员将发现 JDBC 很容易使用。JDBC 保留了 ODBC 的基本设计特征;事实上,两种接口都基于 X/Open SQL CLI(调用级接口)。它们之间最大的区别在于:JDBC 以 Java 风格与优点为基础并进行优化,因此更加易于使用。   目前,Microsoft 又引进了 ODBC 之外的新 API: RDO、 ADO 和OLE DB。这些设计在许多方面与 JDBC 是相同的,即它们都是面向对象的数据库接口且基于可在 ODBC 上实现的类。但在这些接口中,我们未看见有特别的功能使我们要转而选择它们来替代 ODBC,尤其是在 ODBC 驱动程序已建立起较为完善的市场的情况下。它们最多也就是在 ODBC 上加了一种装饰而已。   5. JDBC对B/S和C/S模式的支持   JDBC API 既支持数据库访问的两层模型(C/S),同时也支持三层模型(B/S)。在两层模型中,Java applet或应用程序将直接与数据库进行对话。这将需要一个JDBC驱动程序来与所访问的特定数据库管理系统进行 通讯。用户的SQL语句被送往数据库中,而其结果将被送回给用户。数据库可以位于另一台计算机上,用户通过网络连接到上面。这就叫做客户机/服务器配置,其中用户的计算机为客户机,提供数据库的计算机为服务器。网络可以是 Intranet(它可将公司职员连接起来),也可以是 Internet。   在三层模型中,命令先是被发送到服务的"中间层",然后由它将SQL 语句发送给数据库。数据库对 SQL 语句进行处理并将结果送回到中间层,中间层再将结果送回给用户。MIS 主管们都发现三层模型很吸引人,因为可用中间层来控制对公司数据的访问和可作的的更新的种类。中间层的另一个好处是,用户可以利用易于使用的高级API,而中间层将把它转换为相应的低级调用。最后,许多情况下三层结构可提供一些性能上的好处。   到目前为止,中间层通常都用 C 或 C++ 这类语言来编写,这些语言执行速度较快。然而,随着最优化编译器(它把 Java 字节代码转换为高效的特定于机器的代码)的引入,用 Java 来实现中间层将变得越来越实际。这将是一个很大的进步,它使人们可以充分利用 Java 的诸多优点(如坚固、多线程和安全等特征)。JDBC 对于从Java的中间层来访问数据库非常重要。   6. SQL 的一致性   结构化查询语言 (SQL) 是访问关系数据库的标准语言。困难之处在于:虽然大多数的 DBMS (数据库管理系统)对其基本功能都使用了标准形式的 SQL,但它们却不符合最近为更高级的功能定义的标准 SQL 语法或语义。例如,并非所有的数据库都支持储存程序或外部连接,那些支持这一功能的数据库又相互不一致。人们希望 SQL 中真正标准的那部份能够进行扩展以包括越来越多的功能。但同时 JDBC API 又必须支持现有的 SQL。   JDBC API 解决这个问题的一种方法是允许将任何查询字符串一直传到所涉及的 DBMS 驱动程序上。这意味着应用程序可以使用任意多的 SQL 功能,但它必须冒这样的风险:有可能在某些 DBMS 上出错。事实上,应用程序查询甚至不一定要是 SQL,或者说它可以是个为特定的 DBMS 设计的 SQL 的专用派生物(例如,文档或图象查询)。   JDBC 处理 SQL 一致性问题的第二种方法是提供 ODBC 风格的转义子句,这将在后续部分中讨论。转义语法为几个常见的 SQL 分歧提供了一种标准的 JDBC 语法。例如,对日期文字和已储存过程的调用都有转义语法。   对于

2009-12-11

JSP数据库编程指南

这本书主要讲述基于oracle的jsp编码查询实现。有目录清晰字体哦。

2009-12-11

arm-linux-gcc3.4.1

玩开发板的都应该知道基于arm的linux内核编译器。该版本为arm3.4.1版本交叉编译器,适用于2.4-2.6的内核

2011-10-21

Verilog的135个经典设计实例

Verilog的135个经典设计实例.源代码文档

2011-06-28

Verilog+HDL数字设计与综合课件与课本

这个是教学用的集成电路设计的配套ppt和课本。讲授vhdl语言,芯片电子电路类专业适用。

2011-06-24

数据结构和算法动画演示

数据结构和算法动画演示.全部是flash动画

2011-06-23

ibm 2010 求职大礼包

想去ibm求职的童鞋看过来。这里有你要的ibm内幕知识。

2011-06-22

100个C#初学者编程实例

非常全面的C#入门系列源代码。强烈推荐。

2011-06-22

freescale MC9S12HY64参考手册

freescale MC9S12HY64 参考手册

2011-06-22

java笔试题大集合及答案(另附各大公司笔试题)

60、java中有几种方法可以实现一个线程?用什么关键字修饰同步方法? stop()和suspend()方法为何不推荐使用? 答:有两种实现方法,分别是继承Thread类与实现Runnable接口 用synchronized关键字修饰同步方法 反对使用stop(),是因为它不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时,其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。所以不应该使用suspend(),而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。 61、sleep() 和 wait() 有什么区别? 答:sleep是线程类(Thread)的方法,导致此线程暂停执行指定时间,给执行机会给其他线程,但是监控状态依然保持,到时后会自动恢复。调用sleep不会释放对象锁。 wait是Object类的方法,对此对象调用wait方法导致本线程放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象发出notify方法(或notifyAll)后本线程才进入对象锁定池准备获得对象锁进入运行状态。 62、同步和异步有何异同,在什么情况下分别使用他们?举例说明。 答:如果数据将在线程间共享。例如正在写的数据以后可能被另一个线程读到,或者正在读的数据可能已经被另一个线程写过了,那么这些数据就是共享数据,必须进行同步存取。 当应用程序在对象上调用了一个需要花费很长时间来执行的方法,并且不希望让程序等待方法的返回时,就应该使用异步编程,在很多情况下采用异步途径往往更有效率。 63、启动一个线程是用run()还是start()? 答:启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。 64、当一个线程进入一个对象的一个synchronized方法后,其它线程是否可进入此对象的其它方法? 答:不能,一个对象的一个synchronized方法只能由一个线程访问。 65、请说出你所知道的线程同步的方法。 答:wait():使一个线程处于等待状态,并且释放所持有的对象的lock。 sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用此方法要捕捉InterruptedException异常。 notify():唤醒一个处于等待状态的线程,注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。 Allnotity():唤醒所有处入等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让它们竞争。 66、多线程有几种实现方法,都是什么?同步有几种实现方法,都是什么? 答:多线程有两种实现方法,分别是继承Thread类与实现Runnable接口 同步的实现方面有两种,分别是synchronized,wait与notify 67、线程的基本概念、线程的基本状态以及状态之间的关系

2011-06-22

思科模拟器Boson NetSim for CCNA 6.0 7.06 - 附带NetSim入门教程

资源如题所述。 思科模拟器Boson NetSim for CCNA 6.0 7.06 特别版 - 附带Boson NetSim入门进阶Ⅱ教程(2)

2011-06-22

Bea JRockit j2sdk 1.4.2_05 win32

号称业界最快java虚拟机,可用于规避perm gen异常。本版本为bea被oracle收购之前的版本。

2011-02-08

Cytoscape中文用户手册.pdf

Cytoscape是用于做大规模复杂网络分析与生物信息挖掘的开源中间件,l基于java,gpl方式开源。

2011-01-07

文都考研高等数学公式总结

里面包含微积分,线代,概率的各个章节各种公式。各位需要公式速记的请下载。

2011-01-06

计算机系统结构量化研究方法 第四版 教材+习题解答

这是John L Hennessy 的大作,想必是好多学院的教材。英文版,非扫描,带目录

2011-01-06

自己动手写操作系统。pdf

没什么比自己自己动手写操作系统更带有实践性了。

2010-12-01

140个C语言程式-让你不用买书

140个C语言程式-让你不用买书 福建某学校的教材。

2010-06-03

[模拟电子电路软件].TINA.Pro.V.6.Educational.rar

[模拟电子电路软件].TINA.Pro.V.6.Educational.rar [模拟电子电路软件].TINA.Pro.V.6.Educational.rar

2010-05-22

嵌入式数字信号处理 实验5 实验报告.doc

1. DSP程序优化的方法有哪些? (1) 开启IDE自带的优化选项; (2) 使用硬件循环LSETUP; (3) 使用双乘累加操作,充分利用两个乘累加器和数据总线宽度,如:R3.H=R0.H*R1.H, R3.L=R0.L*R1.L(LS); (4) 使用并行指令,如:mnop||R0=[I0++]||R1=[I2++];R3.H=R0.H*R1.H, R3.L=R0.L*R1.L(LS)||R2=[I2++]; (5) 将并行的数据放到两个数据段; (6) 精简循环,进一步提高指令并行化。 2. 简述汇编代码的优化原理。 (1) 使用硬件循环代替软件循环 使用硬件循环不需要条件转移指令,DSP硬件会更具循环寄存器的值自动执行循环体和提出循环,这样保证了流水线的畅通。而不像软件循环那样,一旦分支预测错误就会浪费9个CPU周期。于是使用硬件循环就会大大提高程序执行的效率。 (2) 充分利用数据总线宽度 本DSP外部数据总线宽度为32位,可以一次存取4字节的数据。这样比起一次取1字节或者2字节的操作,执行速度和效率必然提高。 (3) 使用并行指令 使用并行指令,可以充分利用DSP内部的硬件资源的重复性,减少指令执行次数和提高指令执行的效率。使用一条指令代替二至三条指令的功能。 3. 选做任一实验,总结DSP编程学习过程,得出结论。 (1) DSP学习首先要熟悉书本内容 知道基础的硬件外围接线,基本几个寄存器的配置和基础的代码编写方法; (2) 然后,就可以通过实验平台验证一些实验 通过验证实验,分析代码模板中每条语句的功能,通过这一过程,让自己进一步熟悉DSP实验的编程; (3) 第三,通过自己编写一些简单的程序,来进一步熟悉一种DSP芯片的代码编写方法和运作机理; (4) 第四,做一个项目,在做项目的过程中还会遇到很多的问题有待解决,通过完成一个项目,来把所学的DSP知识综合运用,逐渐融会贯通。

2010-05-22

算法导论 第2版 习题答案

这个是第2版的习题答案。就是国外某计科学生做的那一份。

2010-05-18

flex 基础入门源代码 learningflexbasics.zip

To view these tutorials, expand each zip into its own directory. All images and associated files for a tutorial zip are local to the directory that you unzipped the files to.

2010-05-18

CCNA工程师认证考试电子书.rar

目 录 序言 前言 第1章 网络互连介绍 1 1.1 认证目标1.01:网络互连模型 1 1.1.1 网络的发展 2 1.1.2 OSI模型 2 1.1.3 封装 3 1.2 认证目标1.02:物理层和数据链路层 4 1.2.1 DIX和802.3 Ethernet 5 1.2.2 802.5令牌环网 7 1.2.3 ANSI FDDI 8 1.2.4 MAC地址 9 1.2.5 接口 9 1.2.6 广域网服务 12 1.3 认证目标1.03:网络层和路径确定 17 1.3.1 第3层地址 17 1.3.2 已选择路由协议和路由选择协议 17 1.3.3 路由选择算法和度 18 1.4 认证目标1.04:传输层 18 1.4.1 可靠性 18 1.4.2 窗口机制 18 1.5 认证目标1.05:上层协议 18 1.6 认证目标1.06:Cisco路由器、交换机 和集线器 18 1.7 认证目标1.07:配置Cisco交换机 和集线器 20 1.8 认证总结 20 1.9 2分钟练习 22 1.10 自我测试 23 第2章 从Cisco IOS软件开始 31 2.1 认证目标 2.01:用户界面 31 2.1.1 用户模式和特权模式 31 2.1.2 命令行界面 32 2.2 认证目标2.02:路由器基础 35 2.2.1 路由器元素 35 2.2.2 路由器模式 35 2.2.3 检查路由器状态 37 2.2.4 Cisco发现协议 38 2.2.5 远程访问路由器 39 2.2.6 基本测试 39 2.2.7 调试 40 2.2.8 路由基础 41 2.3 认证目标2.03:初始配置 43 2.3.1 虚拟配置注册表设置 46 2.3.2 启动序列:引导系统命令 47 2.3.3 将配置传送到服务器或从服务器 上复制配置 47 2.4 认证目标2.04:自动安装配置数据 49 2.5 认证总结 49 2.6 2分钟练习 50 2.7 自我测试 51 第3章 IP寻址 58 3.1 认证目标3.01:IP地址类 58 3.1.1 IP地址的结构 58 3.1.2 特殊情况:回路、广播和网 络地址 59 3.1.3 识别地址类 60 3.1.4 子网掩码的重要性 61 3.1.5 二进制和十进制互相转换 62 3.2 认证目标3.02:子网划分和子网掩码 64 3.2.1 子网划分的目的 65 3.2.2 在默认子网掩码中加入位 65 3.3 认证目标3.03:子网规划 66 3.3.1 选择子网掩码 66 3.3.2 主机数目的影响 66 3.3.3 确定每个子网的地址范围 67 3.4 认证目标3.04:复杂子网 68 3.4.1 子网位穿越8位位组边界 68 3.4.2 变长子网掩码 69 3.4.3 超网划分 70 3.5 认证目标 3.05:用Cisco IOS配 置IP地址 71 3.5.1 设置IP地址和参数 71 3.5.2 主机名称到地址的映射 71 3.5.3 使用ping 72 3.5.4 使用IP TRACE和Telnet 73 3.6 认证总结 73 3.7 2分钟练习 74 3.8 自我测试 75 第4章 TCP/IP协议 88 4.1 认证目标 4.01:应用层服务 89 4.2 认证目标 4.02:表示和会话层服务 89 4.2.1 远程过程调用 89 4.2.2 Socket 89 4.2.3 传输层接口 90 4.2.4 NetBIOS 90 4.3 认证目标4.03:协议的详细结构 90 4.3.1 传输层 91 4.3.2 TCP 91 4.3.3 UDP 93 4.4 认证目标4.04:网络层 94 4.4.1 网际协议 94 4.4.2 地址解析协议 95 4.4.3 反向地址解析协议 96 4.4.4 逆向地址解析协议 96 4.4.5 网际控制消息协议 96 4.5 认证目标4.05:操作系统命令 97 4.5.1 UNIX 97 4.5.2 32位Windows 98 4.6 认证总结 98 4.7 2分钟练习 99 4.8 自我测试 100 第5章 IP路由选择协议 108 5.1 认证目标5.01:为什么使用路由 选择协议 108 5.2 认证目标5.02:静态路由和动 态路由 114 5.3 认证目标 5.03:默认路由 117 5.4 认证目标 5.04:链路状态和距 离向量 119 5.4.1 距离向量路由选择协议 119 5.4.2 链路状态路由选择协议 123 5.4.3 内部和外部网关协议 124 5.5 认证目标 5.05:RIP 124 5.6 认证目标 5.06:IGRP 127 5.7 认证目标 5.07:OSPF 129 5.8 认证总结 131 5.9 2分钟练习 132 5.10 自我测试 133 第6章 IP配置 141 6.1 认证目标 6.01:IP配置命令 141 6.2 认证目标 6.02:配置静态路由 141 6.3 认证目标 6.03:配置默认路由 144 6.4 认证目标 6.04:配置RIP路由选择 144 6.5 认证目标 6.05:配置IGRP路由 选择 145 6.6 认证目标 6.06:IP主机表 147 6.7 认证目标 6.07:DNS和DHCP配置 148 6.7.1 DNS配置 148 6.7.2 转发DHCP请求 148 6.8 认证目标 6.08:辅助寻址 150 6.9 认证总结 151 6.10 2分钟练习 151 6.11 自我测试 152 第7章 配置Novell IPX 158 7.1 认证目标 7.01:IPX协议栈 158 7.2 认证目标 7.02:IPX数据报 159 7.2.1 IPX地址编码 159 7.2.2 IPX路由选择 160 7.2.3 内部网络 160 7.3 认证目标 7.03:IPX封装类型 161 7.3.1 Etherent_II 162 7.3.2 Ethernet_802.3 162 7.3.3 Ethernet_802.2 162 7.3.4 Ethernet_SNAP 163 7.3.5 多重帧类型的路由选择 163 7.4 认证目标 7.04:SAP和RIP 165 7.4.1 SAP 165 7.4.2 SAP和RIP操作实例 167 7.5 认证目标 7.05:IPX配置 169 7.5.1 准备 169 7.5.2 启用IPX和配置接口 169 7.5.3 路由选择协议 172 7.6 认证总结 173 7.7 2分钟练习 173 7.8 自我测试 174 第8章 AppleTalk的配置 182 8.1 认证目标 8.01:AppleTalk 协议栈 183 8.1.1 物理层与数据链路层 183 8.1.2 网络层 183 8.1.3 高层协议 183 8.2 认证目标 8.02:AppleTalk服务 185 8.3 认证目标 8.03:AppleTalk寻址 185 8.3.1 地址结构 187 8.3.2 地址分配 187 8.4 认证目标 8.04:AppleTalk区域 188 8.5 认证目标 8.05:AppleTalk 路由选择 189 8.6 认证目标 8.06:AppleTalk 发现模式 190 8.7 认证目标 8.07:AppleTalk配置 191 8.7.1 所需的AppleTalk命令 191 8.7.2 AppleTalk过滤 192 8.7.3 验证和监视AppleTalk的配置 194 8.8 认证总结 195 8.9 2分钟练习 196 8.10 自我测试 196 第9章 用访问列表管理基本通信量 205 9.1 认证目标 9.01:标准IP访问列表 205 9.2 认证目标 9.02:扩展IP访问列表 210 9.3 认证目标 9.03:命名访问列表 211 9.4 认证目标 9.04:标准IPX访问列表 213 9.5 认证目标 9.05:IPX SAP过滤 214 9.6 认证目标 9.06:AppleTalk访问列表 218 9.7 认证总结 220 9.8 2分钟练习 221 9.9 自我测试 222 第10章 广域连网 227 10.1 认证目标10.01:配置ISDN 227 10.1.1 配置ISDN BRI 227 10.1.2 配置ISDN PRI 229 10.2 认证目标10.02:配置X.25 229 10.3 认证目标10.03:配置帧中继 231 10.3.1 虚电路 232 10.3.2 差错校正 233 10.3.3 逻辑接口 233 10.3.4 在Cisco路由器上配置帧中继 233 10.4 认证目标10.04:配置ATM 235 10.5 认证目标10.05:配置PPP和多 链路PPP 238 10.5.1 PPP配置 238 10.5.2 配置多链路PPP 240 10.6 认证总结 241 10.7 2分钟练习 242 10.8 自我测试 243 第11章 虚拟局域网 250 11.1 认证目标11.01:交换和VLAN 250 11.2 认证目标11.02:生成树协议 和VLAN 254 11.3 认证目标11.03:默认VLAN配置 255 11.4 认证目标11.04:跨域配置VLAN 256 11.5 认证目标11.05:到VLAN的分组 交换机端口 259 11.5.1 配置ISL主干 264 11.5.2 IEEE 802.1Q主干 265 11.6 VLAN故障诊断 265 11.7 认证总结 267 11.8 2分钟练习 270 11.9 自我测试 271 附录A 自我测试题答案 278 附录B 关于配套光盘 299 附录C 关于Web站点 300 词汇表 301

2010-05-18

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除