﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>BlogJava-我的小船停在代码的海洋中...-随笔分类-Java</title><link>http://www.blogjava.net/machilansing/category/14204.html</link><description>Lansing--Coding 不是梦
</description><language>zh-cn</language><lastBuildDate>Tue, 27 Feb 2007 08:50:35 GMT</lastBuildDate><pubDate>Tue, 27 Feb 2007 08:50:35 GMT</pubDate><ttl>60</ttl><item><title>Java虚拟机简介</title><link>http://www.blogjava.net/machilansing/archive/2007/01/18/94630.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Thu, 18 Jan 2007 06:27:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2007/01/18/94630.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/94630.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2007/01/18/94630.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/94630.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/94630.html</trackback:ping><description><![CDATA[Java虚拟机<br /><p>一、什么是Java虚拟机</p><br /><p>Java虚拟机是一个想象中的机器,在实际的计算机上通过软件模拟来实现。Java虚拟机有自己想象中的硬件,如处理器、堆栈、寄存器等,还具有相应的指令系统。</p><br /><p>1.为什么要使用Java虚拟机</p><br /><p>Java语言的一个非常重要的特点就是与平台的无关性。而使用Java虚拟机是实现这一特点的关键。一般的高级语言如果要在不同的平台上运行,至少需要编译成不同的目标代码。而引入Java语言虚拟机后,Java语言在不同平台上运行时不需要重新编译。Java语言使用模式Java虚拟机屏蔽了与具体平台相关的信息,使得Java语言编译程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。Java虚拟机在执行字节码时,把字节码解释成具体平台上的机器指令执行。</p><br /><p>2.谁需要了解Java虚拟机</p><br /><p>Java虚拟机是Java语言底层实现的基础,对Java语言感兴趣的人都应对Java虚拟机有个大概的了解。这有助于理解Java语言的一些性质,也有助于使用Java语言。对于要在特定平台上实现Java虚拟机的软件人员,Java语言的编译器作者以及要用硬件芯片实现Java虚拟机的人来说,则必须深刻理解Java虚拟机的规范。另外,如果你想扩展Java语言,或是把其它语言编译成Java语言的字节码,你也需要深入地了解Java虚拟机。</p><br /><p>3.Java虚拟机支持的数据类型</p><br /><p>Java虚拟机支持Java语言的基本数据类型如下:</p><br /><p>byte://1字节有符号整数的补码 <br />short://2字节有符号整数的补码 <br />int://4字节有符号整数的补码 <br />long://8字节有符号整数的补码 <br />float://4字节IEEE754单精度浮点数 <br />double://8字节IEEE754双精度浮点数 <br />char://2字节无符号Unicode字符</p><br /><p>几乎所有的Java类型检查都是在编译时完成的。上面列出的原始数据类型的数据在Java执行时不需要用硬件标记。操作这些原始数据类型数据的字节码(指令)本身就已经指出了操作数的数据类型,例如iadd、ladd、fadd和dadd指令都是把两个数相加,其操作数类型别是int、long、float和double。虚拟机没有给boolean(布尔)类型设置单独的指令。boolean型的数据是由integer指令,包括integer返回来处理的。boolean型的数组则是用byte数组来处理的。虚拟机使用IEEE754格式的浮点数。不支持IEEE格式的较旧的计算机,在运行Java数值计算程序时,可能会非常慢。</p><br /><p>虚拟机支持的其它数据类型包括: <br />object//对一个Javaobject(对象)的4字节引用 <br />returnAddress//4字节,用于jsr/ret/jsr-w/ret-w指令 <br />注:Java数组被当作object处理。</p><br /><p>虚拟机的规范对于object内部的结构没有任何特殊的要求。在Sun公司的实现中,对object的引用是一个句柄,其中包含一对指针:一个指针指向该object的方法表,另一个指向该object的数据。用Java虚拟机的字节码表示的程序应该遵守类型规定。Java虚拟机的实现应拒绝执行违反了类型规定的字节码程序。Java虚拟机由于字节码定义的限制似乎只能运行于32位地址空间的机器上。但是可以创建一个Java虚拟机,它自动地把字节码转换成64位的形式。从Java虚拟机支持的数据类型可以看出,Java对数据类型的内部格式进行了严格规定,这样使得各种Java虚拟机的实现对数据的解释是相同的,从而保证了Java的与平台无关性和可 <br />移植性。</p><br /><p>二、Java虚拟机体系结构</p><br /><p>Java虚拟机由五个部分组成:一组指令集、一组寄存器、一个栈、一个无用单元收集堆(Garbage-collected-heap)、一个方法区域。这五部分是Java虚拟机的逻辑成份,不依赖任何实现技术或组织方式,但它们的功能必须在真实机器上以某种方式实现。</p><br /><p>1.Java指令集</p><br /><p>Java虚拟机支持大约248个字节码。每个字节码执行一种基本的CPU运算,例如,把一个整数加到寄存器,子程序转移等。Java指令集相当于Java程序的汇编语言。 <br />Java指令集中的指令包含一个单字节的操作符,用于指定要执行的操作,还有0个或多个操作数,提供操作所需的参数或数据。许多指令没有操作数,仅由一个单字节的操作符构成。</p><br /><p>虚拟机的内层循环的执行过程如下: </p><br /><p>do{ <br />取一个操作符字节; <br />根据操作符的值执行一个动作; <br />}while(程序未结束)</p><br /><p>由于指令系统的简单性,使得虚拟机执行的过程十分简单,从而有利于提高执行的效率。指令中操作数的数量和大小是由操作符决定的。如果操作数比一个字节大,那么它存储的顺序是高位字节优先。例如,一个16位的参数存放时占用两个字节,其值为:</p><br /><p>第一个字节*256+第二个字节字节码指令流一般只是字节对齐的。指令tabltch和lookup是例外,在这两条指令内部要求强制的4字节边界对齐。</p><br /><p>2.寄存器</p><br /><p>Java虚拟机的寄存器用于保存机器的运行状态,与微处理器中的某些专用寄存器类似。</p><br /><p>Java虚拟机的寄存器有四种: <br />pc:Java程序计数器。 <br />optop:指向操作数栈顶端的指针。 <br />frame:指向当前执行方法的执行环境的指针。 <br />vars:指向当前执行方法的局部变量区第一个变量的指针。</p><br /><p>Java虚拟机</p><br /><p>Java虚拟机是栈式的,它不定义或使用寄存器来传递或接受参数,其目的是为了保证指令集的简洁性和实现时的高效性(特别是对于寄存器数目不多的处理器)。 <br />所有寄存器都是32位的。</p><br /><p>3.栈</p><br /><p>Java虚拟机的栈有三个区域:局部变量区、运行环境区、操作数区。</p><br /><p>(1)局部变量区　每个Java方法使用一个固定大小的局部变量集。它们按照与vars寄存器的字偏移量来寻址。局部变量都是32位的。长整数和双精度浮点数占据了两个局部变量的空间,却按照第一个局部变量的索引来寻址。(例如,一个具有索引n的局部变量,如果是一个双精度浮点数,那么它实际占据了索引n和n+1所代表的存储空间。)虚拟机规范并不要求在局部变量中的64位的值是64位对齐的。虚拟机提供了把局部变量中的值装载到操作数栈的指令,也提供了把操作数栈中的值写入局部变量的指令。</p><br /><p>(2)运行环境区　在运行环境中包含的信息用于动态链接,正常的方法返回以及异常传播。</p><br /><p>·动态链接 <br />运行环境包括对指向当前类和当前方法的解释器符号表的指针,用于支持方法代码的动态链接。方法的class文件代码在引用要调用的方法和要访问的变量时使用符号。动态链接把符号形式的方法调用翻译成实际方法调用,装载必要的类以解释还没有定义的符号,并把变量访问翻译成与这些变量运行时的存储结构相应的偏移地址。动态链接方法和变量使得方法中使用的其它类的变化不会影响到本程序的代码。</p><br /><p>·正常的方法返回<br />如果当前方法正常地结束了,在执行了一条具有正确类型的返回指令时,调用的方法会得到一个返回值。执行环境在正常返回的情况下用于恢复调用者的寄存器,并把调用者的程序计数器增加一个恰当的数值,以跳过已执行过的方法调用指令,然后在调用者的执行环境中继续执行下去。</p><br /><p>·异常和错误传播<br />异常情况在Java中被称作Error(错误)或Exception(异常),是Throwable类的子类,在程序中的原因是:①动态链接错,如无法找到所需的class文件。②运行时错,如对一个空指针的引用</p><br /><p>·程序使用了throw语句。<br />当异常发生时,Java虚拟机采取如下措施:<br />·检查与当前方法相联系的catch子句表。每个catch子句包含其有效指令范围,能够处理的异常类型,以及处理异常的代码块地址。<br />·与异常相匹配的catch子句应该符合下面的条件:造成异常的指令在其指令范围之内,发生的异常类型是其能处理的异常类型的子类型。如果找到了匹配的catch子句,那么系统转移到指定的异常处理块处执行;如果没有找到异常处理块,重复寻找匹配的catch子句的过程,直到当前方法的所有嵌套的catch子句都被检查过。<br />·由于虚拟机从第一个匹配的catch子句处继续执行,所以catch子句表中的顺序是很重要的。因为Java代码是结构化的,因此总可以把某个方法的所有的异常处理器都按序排列到一个表中,对任意可能的程序计数器的值,都可以用线性的顺序找到合适的异常处理块,以处理在该程序计数器值下发生的异常情况。<br />·如果找不到匹配的catch子句,那么当前方法得到一个"未截获异常"的结果并返回到当前方法的调用者,好像异常刚刚在其调用者中发生一样。如果在调用者中仍然没有找到相应的异常处理块,那么这种错误传播将被继续下去。如果错误被传播到最顶层,那么系统将调用一个缺省的异常处理块。 <br />(3)操作数栈区　机器指令只从操作数栈中取操作数,对它们进行操作,并把结果返回到栈中。选择栈结构的原因是:在只有少量寄存器或非通用寄存器的机器(如Intel486)上,也能够高效地模拟虚拟机的行为。操作数栈是32位的。它用于给方法传递参数,并从方法接收结果,也用于支持操作的参数,并保存操作的结果。例如,iadd指令将两个整数相加。相加的两个整数应该是操作数栈顶的两个字。这两个字是由先前的指令压进堆栈的。这两个整数将从堆栈弹出、相加,并把结果压回到操作数栈中。</p><br /><p>每个原始数据类型都有专门的指令对它们进行必须的操作。每个操作数在栈中需要一个存储位置,除了long和double型,它们需要两个位置。操作数只能被适用于其类型的操作符所操作。例如,压入两个int类型的数,如果把它们当作是一个long类型的数则是非法的。在Sun的虚拟机实现中,这个限制由字节码验证器强制实行。但是,有少数操作(操作符dupe和swap),用于对运行时数据区进行操作时是不考虑类型的。</p><br /><p>4.无用单元收集堆</p><br /><p>Java的堆是一个运行时数据区,类的实例(对象)从中分配空间。Java语言具有无用单元收集能力:它不给程序员显式释放对象的能力。Java不规定具体使用的无用单元收集算法,可以根据系统的需求使用各种各样的算法。</p><br /><p>5.方法区</p><br /><p>方法区与传统语言中的编译后代码或是Unix进程中的正文段类似。它保存方法代码(编译后的java代码)和符号表。在当前的Java实现中,方法代码不包括在无用单元收集堆中,但计划在将来的版本中实现。每个类文件包含了一个Java类或一个Java界面的编译后的代码。可以说类文件是Java语言的执行代码文件。为了保证类文件的平台无关性,Java虚拟机规范中对类文件的格式也作了详细的说明。其具体细节请参考Sun公司的Java虚拟机规范。</p><img src ="http://www.blogjava.net/machilansing/aggbug/94630.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2007-01-18 14:27 <a href="http://www.blogjava.net/machilansing/archive/2007/01/18/94630.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java 创建.exe程序</title><link>http://www.blogjava.net/machilansing/archive/2007/01/18/94628.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Thu, 18 Jan 2007 06:21:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2007/01/18/94628.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/94628.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2007/01/18/94628.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/94628.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/94628.html</trackback:ping><description><![CDATA[Sun 提供的标准 Java 开发包（JDK）没有提供创建特定于平台的可执行文件的工具（一点都不吃惊，这是真的）。然而，其实有很多方法能够帮助你实现这一想法。<br />　　<br />　　<b>第三方工具</b><br />　　一种方法是使用第三方商业工具或免费工具将 Java 应用程序打包为一个可执行文件。<br />　　<br />　　下面是价格和特性都不同的两个工具，但是在 Web 上还有其它几个第三方工具可以免费下载。<br />　　<br />　　http://www.bysoft.se/sureshot/exej/ <br />　　http://www.duckware.com/jexepack/ <br />　　使用商业安装程序（installer）<br />　　InstallAnywhere 是一个常用的安装程序，它将管理应用程序的安装过程，并将应用程序打包为可执行程序。<br />　　<br />　　<b>使用 .jar</b><br />　　除了以上方法之外，还可以将应用程序打包为一个可执行的 .jar 文件，而不是一个 .exe 文件。在这篇文章中我将不详细介绍这种方法，你可以在这里找到一个非常棒的在线教程<br />　　<br />　　你需要做的最重要的一件事是指定在 .jar 文件中哪个类是应用程序的入口点。例如，对你的应用程序来说就是具有一个 public static void main(String[] args) 方法的引导类。可以在 .jar 表示文件的 Main-Class 头部信息中提供这些信息。这个头部信息的通用形式为：Main-Class: classname，其中 classname 是应用程序的入口点的类名称。<br />　　<br />　　<b>使用 Java Webstart</b><br />　　Java Webstart 是标准 Java 运行时环境（JRE）的隐藏的宝物，自从版本 1.3 开始，JRE 就包含了 Java Webstart。它是一个简单但功能强大且灵活的将应用程序部署到任何平台的方法。<br />　　<br />　　Webstart 允许应用程序的用户从他们的浏览器、电子邮件或桌面启动和管理应用程序。Java Webstart 的一个主要优点是一旦应用程序被安装，在每次启动它时，它都将会检查用户是否在运行最新版本的应用程序。如果不是，应用程序将通过网络装载新版本到桌面然后执行，因此解决了软件传播问题。<br />　　<br />　　如果你的应用程序已经有很多用户的话，这一点就尤其重要。还有很重要的一点是，它能够检查用户的本地桌面环境，并能保证他们安装了正确的 JRE 版本来运行你的应用程序。<br />　　<br />　　Java Webstart 本身有一系列文章，所以我建议你访问 Java Webstart Web 站点查看更多文档和教程。<br />　　<br />　　<b>结束语</b><br />　　前两种方法可能会满足你对这个问题的需要，但是我强烈建议你仔细看一下 Java Webstart。它是 Java 标准的一部分，并且能够在所有平台下一致工作。我比较喜欢这个应用程序打包方法。 <img src ="http://www.blogjava.net/machilansing/aggbug/94628.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2007-01-18 14:21 <a href="http://www.blogjava.net/machilansing/archive/2007/01/18/94628.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Log4j基本使用方法</title><link>http://www.blogjava.net/machilansing/archive/2006/08/22/65068.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Tue, 22 Aug 2006 06:28:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2006/08/22/65068.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/65068.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2006/08/22/65068.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/65068.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/65068.html</trackback:ping><description><![CDATA[Log4j由三个重要的组件构成：日志信息的优先级，日志信息的输出目的地，日志信息的输出格式。日志信息的优先级从高到低有ERROR、WARN、INFO、DEBUG，分别用来指定这条日志信息的重要程度；日志信息的输出目的地指定了日志将打印到控制台还是文件中；而输出格式则控制了日志信息的显示内容。
<p>　　<strong>一、定义配置文件</strong></p><p>　　其实您也可以完全不使用配置文件，而是在代码中配置Log4j环境。但是，使用配置文件将使您的应用程序更加灵活。Log4j支持两种配置文件格式，一种是XML格式的文件，一种是Java特性文件（键=值）。下面我们介绍使用Java特性文件做为配置文件的方法：</p><p>　　1.配置根Logger，其语法为：</p><p>　　log4j.rootLogger = [ level ] , appenderName, appenderName, … </p><p>　　其中，level 是日志记录的优先级，分为OFF、FATAL、ERROR、WARN、INFO、DEBUG、ALL或者您定义的级别。Log4j建议只使用四个级别，优先级从高到低分别是ERROR、WARN、INFO、DEBUG。通过在这里定义的级别，您可以控制到应用程序中相应级别的日志信息的开关。比如在这里定义了INFO级别，则应用程序中所有DEBUG级别的日志信息将不被打印出来。 appenderName就是指定日志信息输出到哪个地方。您可以同时指定多个输出目的地。 </p><p>　　2.配置日志信息输出目的地Appender，其语法为：</p><p>　　log4j.appender.appenderName = fully.qualified.name.of.appender.class <br />　　log4j.appender.appenderName.option1 = value1 <br />　　… <br />　　log4j.appender.appenderName.option = valueN </p><p>　　其中，Log4j提供的appender有以下几种： <br />　　org.apache.log4j.ConsoleAppender（控制台）， <br />　　org.apache.log4j.FileAppender（文件）， <br />　　org.apache.log4j.DailyRollingFileAppender（每天产生一个日志文件），<br />　　org.apache.log4j.RollingFileAppender（文件大小到达指定尺寸的时候产生一个新的文件）， <br />　　org.apache.log4j.WriterAppender（将日志信息以流格式发送到任意指定的地方） </p><p>　　3.配置日志信息的格式（布局），其语法为：</p><p>　　log4j.appender.appenderName.layout = fully.qualified.name.of.layout.class <br />　　log4j.appender.appenderName.layout.option1 = value1 <br />　　… <br />　　log4j.appender.appenderName.layout.option = valueN </p><p>　　其中，Log4j提供的layout有以下几种： <br />　　org.apache.log4j.HTMLLayout（以HTML表格形式布局）， <br />　　org.apache.log4j.PatternLayout（可以灵活地指定布局模式）， <br />　　org.apache.log4j.SimpleLayout（包含日志信息的级别和信息字符串）， <br />　　org.apache.log4j.TTCCLayout（包含日志产生的时间、线程、类别等等信息） </p><p>　　Log4J采用类似C语言中的printf函数的打印格式格式化日志信息，打印参数如下： %m 输出代码中指定的消息</p><p>　　%p 输出优先级，即DEBUG，INFO，WARN，ERROR，FATAL <br />　　%r 输出自应用启动到输出该log信息耗费的毫秒数 <br />　　%c 输出所属的类目，通常就是所在类的全名 <br />　　%t 输出产生该日志事件的线程名 <br />　　%n 输出一个回车换行符，Windows平台为“\r\n”，Unix平台为“\n” <br />　　%d 输出日志时间点的日期或时间，默认格式为ISO8601，也可以在其后指定格式，比如：%d{yyy MMM dd HH:mm:ss,SSS}，输出类似：2002年10月18日 22：10：28，921 <br />　　%l 输出日志事件的发生位置，包括类目名、发生的线程，以及在代码中的行数。举例：Testlog4.main(TestLog4.java:10) </p><p>　　<strong>二、在代码中使用Log4j</strong></p><p>　　1.得到记录器</p><p>　　使用Log4j，第一步就是获取日志记录器，这个记录器将负责控制日志信息。其语法为： </p><p>　　public static Logger getLogger( String name) </p><p>　　通过指定的名字获得记录器，如果必要的话，则为这个名字创建一个新的记录器。Name一般取本类的名字，比如： </p><p>　　static Logger logger = Logger.getLogger ( ServerWithLog4j.class.getName () )</p><p>　　2.读取配置文件 </p><p>　　当获得了日志记录器之后，第二步将配置Log4j环境，其语法为：</p><p>　　BasicConfigurator.configure ()： 自动快速地使用缺省Log4j环境。<br />　　PropertyConfigurator.configure ( String configFilename) ：读取使用Java的特性文件编写的配置文件。<br />　　DOMConfigurator.configure ( String filename ) ：读取XML形式的配置文件。</p><p>　　3.插入记录信息（格式化日志信息）</p><p>　　当上两个必要步骤执行完毕，您就可以轻松地使用不同优先级别的日志记录语句插入到您想记录日志的任何地方，其语法如下：</p><p>　　Logger.debug ( Object message ) ;<br />　　Logger.info ( Object message ) ;<br />　　Logger.warn ( Object message ) ;<br />　　Logger.error ( Object message ) ;</p><img src ="http://www.blogjava.net/machilansing/aggbug/65068.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2006-08-22 14:28 <a href="http://www.blogjava.net/machilansing/archive/2006/08/22/65068.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>批量处理JDBC语句提高处理速度</title><link>http://www.blogjava.net/machilansing/archive/2006/08/22/64956.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Tue, 22 Aug 2006 01:24:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2006/08/22/64956.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/64956.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2006/08/22/64956.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/64956.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/64956.html</trackback:ping><description><![CDATA[
		<table style="WORD-BREAK: break-all" cellspacing="0" cellpadding="0" width="700" align="center" border="0">
				<tbody>
						<tr>
								<td align="middle" height="25">
										<font face="黑体" size="4">批量处理JDBC语句提高处理速度</font>
								</td>
						</tr>
						<tr bgcolor="#f9f9f9">
								<td id="fontzoom" style="LINE-HEIGHT: 200%">
										<p align="center">作者：佚名    来自：未知</p>
										<p>
										</p>
										<p>　　有时候JDBC运行得不够快，这使得有些程序员使用数据库相关的存储过程。作为一个替代方案，可以试试使用Statement 的批量处理特性看看能否同时执行所有的SQL以提高速度。 </p>
										<p>　　存储过程的最简单的形式就是包含一系列SQL语句的过程，将这些语句放在一起便于在同一个地方管理也可以提高速度。Statement 类可以包含一系列SQL语句，因此允许在同一个数据库事务执行所有的那些语句而不是执行对数据库的一系列调用。 </p>
										<p>　　使用批量处理功能涉及下面的两个方法：<br />　　· addBatch(String) 方法 <br />　　· executeBatch方法 </p>
										<p>　　如果你正在使用Statement 那么addBatch 方法可以接受一个通常的SQL语句，或者如果你在使用PreparedStatement ，那么也可以什么都不向它增加。executeBatch 方法执行那些SQL语句并返回一个int值的数组，这个数组包含每个语句影响的数据的行数。如果将一个SELECT语句或者其他返回一个ResultSet的SQL语句放入批量处理中就会导致一个SQLException异常。 </p>
										<p>　　关于java.sql.Statement 的简单范例可以是： </p>
										<p>　　Statement stmt = conn.createStatement();<br />　　stmt.insert("DELETE FROM Users");<br />　　stmt.insert("INSERT INTO Users VALUES("rod", 37, "circle")");<br />　　stmt.insert("INSERT INTO Users VALUES("jane", 33, "triangle")");<br />　　stmt.insert("INSERT INTO Users VALUES("freddy", 29, "square")");<br />　　int[] counts = stmt.executeBatch(); </p>
										<p>　　PreparedStatement 有些不同，它只能处理一部分SQL语法，但是可以有很多参数，因此重写上面的范例的一部分就可以得到下面的结果： </p>
										<p>　　// 注意这里没有DELETE语句<br />　　PreparedStatement stmt = conn.prepareStatement("INSERT INTO Users VALUES(?,?,?)");</p>
										<p>　　User[ ] users = ...;<br />　　for(int i=0; i&lt;users.length; i++) {<br />　　　stmt.setInt(1, users[i].getName());<br />　　　stmt.setInt(2, users[i].getAge());<br />　　　stmt.setInt(3, users[i].getShape());<br />　　　stmt.addBatch( );<br />　　}<br />　　int[ ] counts = stmt.executeBatch(); </p>
										<p>　　如果你不知道你的语句要运行多少次，那么这是一个很好的处理SQL代码的方法。在不使用批量处理的情况下，如果添加50个用户，那么性能就有影响，如果某个人写了一个脚本添加一万个用户，程序可能变得很糟糕。添加批处理功能就可以帮助提高性能，而且在后面的那种情况下代码的可读性也更好。</p>
								</td>
						</tr>
				</tbody>
		</table>
<img src ="http://www.blogjava.net/machilansing/aggbug/64956.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2006-08-22 09:24 <a href="http://www.blogjava.net/machilansing/archive/2006/08/22/64956.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Apache Avalon简介</title><link>http://www.blogjava.net/machilansing/archive/2006/08/18/64430.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Fri, 18 Aug 2006 12:14:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2006/08/18/64430.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/64430.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2006/08/18/64430.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/64430.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/64430.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: Avalon的简要历史以及创建它所有的设计原则概述																																						事情是从Apache JServ项目开始的。Stefano Mazzocchi和其它协助开发Apache JServ的人员认识到项目中所用到的一些模式很通用，足以用于创建一个服务器框架。 在1999年1月27日，星期三（在JServ ...&nbsp;&nbsp;<a href='http://www.blogjava.net/machilansing/archive/2006/08/18/64430.html'>阅读全文</a><img src ="http://www.blogjava.net/machilansing/aggbug/64430.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2006-08-18 20:14 <a href="http://www.blogjava.net/machilansing/archive/2006/08/18/64430.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>浅析J2EE与.NET平台优劣</title><link>http://www.blogjava.net/machilansing/archive/2006/08/17/64196.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Thu, 17 Aug 2006 11:45:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2006/08/17/64196.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/64196.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2006/08/17/64196.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/64196.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/64196.html</trackback:ping><description><![CDATA[
		<p style="TEXT-INDENT: 2em">一.技术概观 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">在表现形式上，J2EE是一组规范，而.NET更象是一组产品。但它们的目的都是为了企业应用提供分布式的，高可靠性的解决方案.它们在架构上有着很多的相似之处，下表是一个简单对照: 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">J2EE .NET 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">通信协议 Remote Method Invocation over Internet InterOrb Protocol (RMI/IIOP)，XML 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">编程语言 Java C#，VB.NET，COBOL 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">运行时环境 Java Virtual Machine (JVM) Common Language Runtime (CLR) 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">胖客户端 Java Swing Windows Forms 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">目录服务 Java Naming and Directory Interface (JNDI) Active Directory Services Interface (ADSI) 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">数据访问 Java Database Connection (JDBC) ，Java Connectors ADO.NET 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">异步消息处理 Java Message Service (JMS) Microsoft Message Queue 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">表示层技术 Servlets， Java Server Page(JSP) ASP.NET 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">中间层组件模型 EJB，JavaBean COM+，COM 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">安全访问 JAAS COM+ Security 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">Call Context 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">事物处理 Java Transaction Server (JTS) Microsoft Distributed Transaction Coordinator (MS-DTC) 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">开发工具 WebGain Visual Café 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">Borland JBuilder 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">IBM VisualAge 等 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">(第三方提供，规范本身没有定义) Visual Studio.NET 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">J2EE平台的构成 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">EJB - J2EE 中间层，完成商业逻辑； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">JAAS - J2EE 处理认证和授权的API; 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">Java Connectors - J2EE 用于连接异种数据源的API，对上层来讲是透明的; 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">JSP， Java Servlets - J2EE的表示层技术，用于生成用户界面; 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">Java Virtual Machine - Java 语言运行环境； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">JDBC - J2EE数据库访问； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">JMS - J2EE的异步消息队列； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">JNDI - J2EE的名字查找API，独立于目录服务器； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">JTS - J2EE用于处理交易的API； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">RMI/IIOP - J2EE的分布式对象的通讯API，提供了和CORBA交互的能力。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">.NET平台构成 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">.NET Framework - .NET应用运行的基础； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">IL (Intermediary Language) - 所有的.NET语言首先被编译成该中间语言，然后在CLR中运行； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">SOAP - 用于服务访问的工业标准； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">DCOM - 组件间通信协议； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">MS-DTC - 用来在.NET平台上使用两阶段提交协议来处理分布式交易； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">CLR - .NET应用的运行时环境； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">COM+ - .NET的中间层模型，用于构建商务逻辑； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">ADO.NET - .NET 对数据访问的API。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">此外.NET平台还包括其他一些产品象Application Center Server，BizTalk Server ，NLBS (Network Load Balancing Service)，Commerce Server，Enterprise Servers，HIS (Host Integration Server)，ISAS (Internet Security and Acceleration Server)用来提供象防火墙，安全访问，B2B交易，负载平衡等服务.J2EE规范本身没有定义这些服务，但可通过选择第三方产品来满足类似的要求。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">二.技术比较 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">1.一 vs 多 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">一种语言vs多种语言，一个平台vs多个平台.这似乎是大家最喜于津津乐道的话题，也似乎是所有问题的焦点。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">两种平台主流的开发语言Java和C#在架构上有着惊人的相似：虚拟机技术，基于沙箱的安全模型，分层的命名空间，垃圾回收等。所以从第一眼看上去，C#简直就是Java的克隆。但微软并不这样认为，微软的说明是：“它集成了C++， Java，Modula 2，C和Smalltalk等多种语言的精华，对它们共同的核心思想象深度面向对象(deep object-orientation)，对象简化 (object-simplification)等都一一做了参考。”一方面，C#的大多数关键字来源于C++，使它在书写上有别于Java。但另一方面，C#的严格的类型转换等概念却明显来自于Java(当然，它的原始类型的定义更严格，并且据微软声称没有影响到效率.)，使其在内涵上有克隆之嫌.但即是Java，其有些特性也和Smalltalk颇有渊源.所以评价一种开发语言的优劣不仅是看其外在的表现形式，更重要的是其实实在在的功效.作为一种新语言，C#加入了基于XML的标记，可以被编译器用来直接生成文档，C#的另一个特点:一站式软件(one-stop-shopping software)强调了自解释( self-describing) 的编码方式，即头文件，IDL(Interface Definition Language)，GUID和其他复杂的接口无需再被引用.也即是C#，VB.NET等代码片断可以任意的被加入到其他语言中.这无疑在多种语言混合编程的模式中是一次飞跃，但是，其难维护性也是不言而喻的。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">微软的.NET的平台提供了象C#，VB.NET，COBOL等多种开发语言，C#是新的，而其他的每一种语言都是在原有的基础上改造而来.这是微软煞费苦心并且也是不得以的要为习惯于这些语言的程序员铺一条便捷之路.但是，这些语言的改造与其说是整容到不如说是一次开膛破肚的大手术.首先是观念变了，Basic，Cobol等语言先天的缺少面向对象的内涵，现在却变成了面向对象的语言，这就不是要求其传统的程序员仅仅熟悉一些额外的关键字那么简单的问题了.基于面向对象的软件分析设计开发测试是完全不同于基于传统过程性语言的质变，所以这一过程的转变对传统程序员来讲也是一个痛苦和漫长的过程.在传统程序员面前，微软看似提供了丰富多采的解决方法，但对于实际问题而言，却怕是有些力不从心.所以一个简单的办法是:直接使用C#.对于独立软件开发商来讲，其转换成本不容忽视.其次，在一个软件项目中使用多种语言，开发商必须同时拥有多种语言专家和多个独立的难以互相支援的开发小组，无疑的，这也使其软件的维护的成本已非线性的曲线增长.多样性是双韧剑，实施时需仔细斟酌. 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">跨平台是J2EE的最大卖点，也是至今为止还绊住微软的栅栏.当开发商完成了符合J2EE规范的软件时，其客户可以依据其喜好和实力来选择不同应用服务器.从基于open source的免费软件到高端满足B2B需求的商业套件来搭建自己的平台.但是由于J2EE的规范还不完善，各个J2EE服务器的提供商为了使其提供其各自理解的完整的功能，不得不添加一些额外的特性.这就使得使用了这些特别功能的应用软件，绑定到了特定的应用服务器上.随着J2EE规范的发展，这种差别会逐渐减小. 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">微软的跨平台解决方案是Web services，它解决的是异种平台上不同应用之间的连通性问题.从技术角度讲，它除了以XML为介质之外没有什么新意.但它的重要意义在于:它是微软这样一个重量级选手所推出的，前景不容小视.构造和使用 Web services 的过程较为简单: 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">服务提供者用他所选择的语言构造服务; 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">服务提供者用WSDL(the Web Services Description Language)来定义该服务; 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">服务提供者在UDDI (Universal Description， Discovery， and Integration )中注册该服务; 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">使用者的应用程序从 UDDI中查找已注册服务; 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">使用者的应用程序通过 SOAP (the Simple Object Access Protocol )来调用服务.(SOAP使用HTTP来传递基于XML为表现形式的参数) 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">正如我们所讨论的: Web services解决的是异构平台上服务连通性的问题，但在现实中所更迫切需要的是如何在异构的平台上构造具有可扩展性，高可靠性，高可用性，故障冗余，错误恢复能力的企业应用.缺少这一点，从结构上讲，.NET平台还远未完善. 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">2.中间层 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">基于组件的软件开发技术可以在较高的级别上实现软件复用，加快企业软件开发的进程.在J2EE构架中， JavaBean和EJB(Enterprise JavaBeans) 被用来完成事物逻辑.其中EJB和 JavaBean 有着类似的模型，但它被用来创建分布式的企业应用.它定义服务器端组件的模型，具有以下一些特性: 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">生存期模型； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">访问模型； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">安全模型； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">事物处理模型； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">会话处理模型； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">数据封装模型； 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">部署模型 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">根据这些模型，简单的编码就可完成复杂的功能。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">在微软的.NET平台中，旧的COM 和 COM+的组件模型被新的组件模型所代替。增加了象基于沙箱的安全模型和垃圾回收等功能.并且实现了多重接口继承，扩展的元数据和新的代理模型等.旧有的COM和COM+组件也可被映射到新的运行环境中。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">综上所述，两众架构在基于组件的中间层的设计上各有千秋，对于创建分布式的，复杂的，高效的，高可靠性的的应用程序都有着足够的能力。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">3.表示层 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">两种架构都同时支持胖客户端和瘦客户端.即C/S模式和B/S模式.对于C/S模式，J2EE提供了替代Java AWT的Java Swing，同时作为可视化组件的JavaBean也可用来构造系统。对于B/S结构的表示层，J2EE使用 servlet ，JSP(Java Server Page) ，HMTL，WML，XML等工具来实现。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">微软的胖客户端技术则由 Windows Forms代替了MFC.它们起的作用相同，在结构上 Windows Forms 被插入到.NET的运行时框架(runtime framework)和组件模型 (component model)中.在瘦客户模型中， ASP.NET代替了旧有的ASP和 HMTL， WML ，XML作为表示层。在 ASP.NET 中，C#，VB.NET等语言的代码片断可被自由引用.ASP.NET 页面被首先转换成中介语言( Intermediary Language)，然后再被 中介语言及时编译器(just-in-time IL compiler)编译，最后运行于公共语言运行环境中，并且 ASP.NET 提供了页面的缓冲，所以，其运行速度要远远快于ASP。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">大体上，两种架构所使用的表示层的技术非常类似，虽在细节上各有所长，但总体功能当在伯仲之间。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">4.数据访问 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">J2EE 和 .Net 已不同的形式支持数据的访问。JDBC和ADO一样和所连接的数据库无关，并且通过连接，命令语句和结果集来对数据进行操作.所以属于中间层次的 API.更高一级的数据封装和数据管理是通过实体EJB (entity EJB)来完成的.基于容器管理的实体EJB使开发更快捷，管理更方便.事实上，由于实体EJB的load()和store()方法的同步机制，将大大缓解因并发而使数据库产生的瓶颈.也可以采用不属于J2EE规范的第三方数据访问工具，象WebGain的 TopLink。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">而微软的.NET的数据访问工具则由基于XML的ADO.NET代替了基于COM组件的ADO.任何以XML为输出的数据源都可以作为 ADO.NET 的数据源.相应的结果集升级为数据集 (DataSets)，命令语句则升级为数据集命令(DataSetCommands).从形式来看，微软的ADO.NET更新潮和时髦一些，基于XML的特性使其可以处理极其丰富的数据源，并且，因其构架在HTTP协议之上，易于穿透防火墙，使沟通更为便利.但由于XML本身的基于标记的特性，很明显限制了在有超大数据量和有网络瓶颈的应用中的使用.而J2EE的数据访问规则则显得略有单薄，但同时却更简单，更有效.并且通过对应用程序有效的层次的设计，对于数据库和基于XML的数据源的访问，也是可以无缝的整合的。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">三.整体评价 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">在微软还没有足以和Java平台相对抗的产品的时候，微软所乐于做是大声的宣传:"write once， debug everywhere"。而它的对手则更乐于这样评价它:"微软开始也喜欢Java，他们喜欢它的方式是让它死去，他们当然也憎恨它，他们甚至憎恨每一个以J开头的单词。"但是现在，形式不同了，微软有了足以自豪的.NET他们可以已他们自己所喜好的方式来对J2EE和.NET来做各种比较。最热闹的应该算是微软出示的第三方对.NET Pet Shop和J2EE的 Pet Store的综合比较了.有兴趣的读者可以到MSDN，www.onjava.com，IBM开发者原地等网站看到相关评论。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">J2EE .NET 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">易用性 ** *** 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">扩展能力 *** ** 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">多平台支持 **** * 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">多语言支持 * **** 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">可靠性 *** *** 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">性能 *** *** 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">可管理性 *** *** 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">重用性 **** ** 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">负载平衡 *** *** 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">开放标准 ***** * 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">就企业而言，内部众多系统的整合、系统的延展性、安全性是更需要注意的议题，而这些都是J2EE的优势，也是微软的不足处。 在效率方面，J2EE阵营主张通过硬件的效能增加来弥补软件的不足.开放标准，功能强大，易于移植这些都是J2EE的卖点。但让人奇怪的是IBM的WebSphere和BEA的WebLogic在J2EE市场占了大半壁江山，而作为规则制定者的SUN却在做壁上观。 
</p>
		<p style="TEXT-INDENT: 2em">
		</p>
		<p style="TEXT-INDENT: 2em">微软确实提供了从桌面的办公软件，开发工具，到后台服务器数据库的全方位的产品。 但统一平台的使用者可能要牺牲跨平台的好处，并也有可能由此就被无穷无尽的锁定在微软的许可证的汪洋中.更简单，更快捷，更高效是微软的目标，随着时代的发展，我们也许会看到更完美的技术解决方案。 </p>
<img src ="http://www.blogjava.net/machilansing/aggbug/64196.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2006-08-17 19:45 <a href="http://www.blogjava.net/machilansing/archive/2006/08/17/64196.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>创建Web应用和Struts框架的配置文件</title><link>http://www.blogjava.net/machilansing/archive/2006/08/17/64195.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Thu, 17 Aug 2006 11:43:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2006/08/17/64195.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/64195.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2006/08/17/64195.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/64195.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/64195.html</trackback:ping><description><![CDATA[
		<p>
				<b>创建Web应用的配置文件</b>
		</p>
		<p>对于Struts应用，它的配置文件web.xml应该对ActionServlet类进行配置，此外，还应该声明Web应用所使用的Struts标签库，本例中声明使用了三个标签库: Struts Bean、Struts HTML和Struts Logic标签库。例程1为web.xml的源代码。</p>
		<table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
				<tbody>
						<tr>
								<td class="code" bgcolor="#e6e6e6">例程1　web.xml<br /><br />&lt;?xml version="1.0" encoding="UTF-8"?&gt;<br /><br />&lt;!DOCTYPE web-app<br />PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"<br />"http://java.sun.com/j2ee/dtds/web-app_2_2.dtd"&gt;<br /><br />&lt; web-app &gt;<br /><br />&lt; display-name &gt; <br />HelloApp Struts Application<br />&lt;/display-name &gt;<br /><br />&lt;!-- Standard Action Servlet Configuration --&gt;<br /><br />&lt; servlet &gt;<br /><br />&lt; servlet-name &gt; action &lt;/servlet-name &gt;<br /><br />&lt; servlet-class &gt; <br />org.apache.struts.action.ActionServlet<br />&lt; /servlet-class &gt; <br /><br />&lt; init-param &gt; <br />&lt; param-name&gt; config&lt; /param-name &gt; <br />&lt; param-value&gt;<br />/WEB-INF/struts-config.xml<br />&lt;/param-value &gt;<br />&lt;/init-param &gt;<br /><br />&lt; load-on-startup&gt;2&lt;/load-on-startup &gt;<br /><br />&lt;/servlet&gt;<br /><br />&lt;!-- Standard Action Servlet Mapping --&gt;<br /><br />&lt; servlet-mapping&gt;<br /><br />&lt; servlet-name &gt; action&lt;/servlet-name&gt;<br /><br />&lt; url-pattern&gt;*.do&lt;/url-pattern&gt;<br /><br />&lt;/servlet-mapping&gt;<br /><br />&lt;!-- The Usual Welcome File List --&gt;<br /><br />&lt; welcome-file-list&gt;<br /><br />&lt; welcome-file &gt; hello.jsp&lt;/welcome-file&gt;<br /><br />&lt;/welcome-file-list&gt;<br /><br />&lt;!-- Struts Tag Library Descriptors --&gt;<br /><br />&lt; taglib &gt;<br /><br />&lt; taglib-uri &gt;<br />/WEB-INF/struts-bean.tld<br />&lt;/taglib-uri&gt;<br /><br />&lt; taglib-location&gt;<br />/WEB-INF/struts-bean.tld<br />&lt;/taglib-location&gt;<br /><br />&lt;/taglib&gt;<br /><br />&lt; taglib &gt;<br /><br />&lt; taglib-uri &gt;<br />/WEB-INF/struts-html.tld<br />&lt;/taglib-uri &gt;<br /><br />&lt; taglib-location &gt;<br />/WEB-INF/struts-html.tld<br />&lt;/taglib-location &gt;<br /><br />&lt;/taglib &gt;<br /><br />&lt; taglib &gt;<br /><br />&lt; taglib-uri &gt;<br />/WEB-INF/struts-logic.tld<br />&lt;/taglib-uri &gt;<br /><br />&lt; taglib-location &gt;<br />/WEB-INF/struts-logic.tld<br />&lt;/taglib-location &gt;<br /><br />&lt;/taglib &gt;<br /><br />&lt;/web-app &gt;</td>
						</tr>
				</tbody>
		</table>
		<center>
		</center>
		<p>
				<b>创建Struts框架的配置文件</b>
		</p>
		<p>正如前面提及的，Struts框架允许把应用划分成多个组件，提高开发速度。而Struts框架的配置文件struts-config.xml可以把这些组件组装起来，决定如何使用它们。例程2是helloapp应用的struts-config.xml文件的源代码。</p>
		<table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1">
				<tbody>
						<tr>
								<td class="code" bgcolor="#e6e6e6">
										<pre>例程2  struts-config.xml<br />&lt;?xml version="1.0" encoding="ISO-8859-1" ?&gt;<br />&lt;!DOCTYPE struts-config<br /> PUBLIC"-//Apache Software Foundation<br />//DTD Struts Configuration 1.1//EN"<br /> "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd"&gt;<br /><br />&lt;!--This is the Struts configuration file <br />for the "Hello!" sample application--&gt;<br />&lt; struts-config&gt;<br />&lt;!-- ===== Form Bean Definitions ====== --&gt;<br />&lt; form-beans&gt;<br />&lt; form-bean name="HelloForm" type="hello.HelloForm"/&gt;<br />&lt;/form-beans&gt;<br />&lt;!-- ====== Action Mapping Definitions ====== --&gt;<br />  &lt; action-mappings&gt;<br />    &lt;!-- Say Hello! --&gt;<br />    &lt; action path="/HelloWorld" <br /> type="hello.HelloAction"<br /> name="HelloForm"<br /> scope="request"<br /> validate="true"<br /> input="/hello.jsp"<br />&gt;<br />&lt; forward name="SayHello" path="/hello.jsp" /&gt;<br />&lt;/action &gt;<br />&lt;/action-mappings &gt;<br />&lt;!-- ===== Message Resources Definitions ===== --&gt;<br />&lt; message-resources parameter="hello.application"/&gt;<br />&lt;/struts-config &gt;</pre>
								</td>
						</tr>
				</tbody>
		</table>
		<br />
		<br />以上代码对helloapp应用的HelloForm、HelloAction和消息资源文件进行了配置，首先通过<form-bean>元素配置了一个ActionForm Bean，名叫HelloForm，它对应的类为hello.HelloForm：<br /><br /><form-bean name="HelloForm" type="hello.HelloForm" /><br /><br />接着通过元素配置了一个Action组件:　 
<table cellspacing="0" bordercolordark="#ffffff" cellpadding="2" width="400" align="center" bordercolorlight="black" border="1"><tbody><tr><td class="code" bgcolor="#e6e6e6"><pre>&lt; action<br /> path = "/HelloWorld"<br /> type ="hello.HelloAction"<br /> name = "HelloForm"<br /> scope = "request"<br /> validate = "true"<br /> input = "/hello.jsp"<br />&gt;<br />&lt; forward name="SayHello" path="/hello.jsp" /&gt;<br />&lt;/action &gt;</pre></td></tr></tbody></table><p><action>元素的path属性指定请求访问Action的路径，type属性指定Action的完整类名，name属性指定需要传递给Action的ActionForm Bean，scope属性指定ActionForm Bean的存放范围，validate属性指定是否执行表单验证，input属性指定当表单验证失败时的转发路径。<action>元素还包含一个<forward>子元素，它定义了一个请求转发路径。<br /><br />本例中的 <action>元素配置了HelloAction组件，对应的类为hello.HelloAction，请求访问路径为"HelloWorld"，当Action类被调用时，Struts框架应该把已经包含表单数据的HelloForm Bean传给它。HelloForm Bean存放在request范围内，并且在调用Action类之前，应该进行表单验证。如果表单验证失败，请求将被转发到接收用户输入的网页hello.jsp，让用户纠正错误。</action></forward></action></action></p><p>struts-config.xml文件最后通过元素定义了一个Resource Bundle：元素的parameter属性指定Resource Bundle使用的消息资源文件。本例中parameter属性为"hello.application"，表明消息资源文件名为"application.properties"，它的存放路径为WEB-INF/classes/hello/application.properties。</p></form-bean><img src ="http://www.blogjava.net/machilansing/aggbug/64195.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2006-08-17 19:43 <a href="http://www.blogjava.net/machilansing/archive/2006/08/17/64195.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Struts框架技术在J2EE中的研究和应用</title><link>http://www.blogjava.net/machilansing/archive/2006/08/17/Struts.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Thu, 17 Aug 2006 11:36:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2006/08/17/Struts.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/64193.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2006/08/17/Struts.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/64193.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/64193.html</trackback:ping><description><![CDATA[
		<p>
				<span class="top11">
						<strong>J2EE简介</strong>
				</span>
		</p>
		<p>
				<span class="top11">
						<strong>
								<br />
								<br />
						</strong>J2EE是一个开放的、基于标准的平台，可以开发、部署和管理N层结构的、面向Web的、以服务器为中心的企业级应用，它是利用Java 2 平台来简化与多级企业解决方案的开发、部署和管理相关的诸多复杂问题的应用体系结构。<br /><br />J2EE平台采用一个多层次分布式的应用模式。这意味着应用逻辑根据功能被划分成组件，组成J2EE应用的不同应用组件安装在不同的服务器上，这种划分是根据应用组件属于多层次J2EE环境中的哪一个层次来决定的。如图1所示，J2EE应用可以由三或四个层次组成，J2EE多层次应用一般被认为是三层应用，因为它们是被分布在三个不同的地点：客户端机器、J2EE服务器和数据库或后端的传统系统服务器。三层架构应用是对标准的客户端/服务器应用架构的一种扩展， 即在客户端应用和后台存储之间增加一个多线程应用服务器。 <br /><br /></span>
		</p>
		<center>
				<img style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-BOTTOM: black 1px solid" src="http://java.ccidnet.com/col/attachment/2006/4/663945.gif" />
		</center>
		<p>
				<br />
				<br />J2EE体系包括JSP、Servlet、EJB、WEB SERVICE等多项技术。这些技术的出现给电子商务时代的WEB应用开发提供了一个非常有竞争力的选择。怎样把这些技术组合起来，形成一个适应项目需要的稳定架构是项目开发过程中一个非常重要的步骤。<br /><br />一个成功的软件需要有一个成功的架构，但软件架构的建立是一个复杂而又持续改进的过程，软件开发者们不可能对每个不同的项目做不同的架构，而总是尽量重用以前的架构，或开发出尽量通用的架构方案，Struts就是流行的基于J2EE的架构方案之一，其他常用的基于J2EE的架构方案还有Turbine、RealMothods等。本文主要探讨Struts框架技术的应用。<br /><br /><b>J2EE应用程序架构的发展</b><br /><br />在J2EE应用程序架构的发展路程中，主要经历了两个大的阶段：<br /><br />1、Model 1<br /><br />在JSP页面中结合业务逻辑、服务器端处理程序和HTML，在JSP页面中同时实现显示、业务逻辑和流程控制，从而快速的完成Web应用开发。这种模型的不足之处：1）不利于应用扩展和更新。2）业务逻辑和表示逻辑混合在JSP页面中没有进行抽象和分离，不利于应用系统业务的重用和改动。<br /><br />2、Model 2<br /><br />表示的是基于MVC模式的框架。根据Model 2，servlet 处理数据存取和导航流， JSP处理表现。Model 2 使Java 工程师和HTML设计者分别工作于它们所擅长和负责的部分。Model 2应用的一部分发生改变并不强求其他部分也跟着发生改变。HTML 开发人员可以改变程序的外观和感觉，并不需要改变后端servlet的工作方式。把应用逻辑、处理过程和显示逻辑分成不同的组件实现。弥补了Model1的不足。<br /><br /><strong>Struts框架技术</strong><br /><br />Struts 框架就是基于Model 2 的架构，也就是基于MVC模式的框架技术。它是一个免费的开源的WEB层的应用框架,具有很高的可配置性，和有一个不断增长的特性列表。一个前端控制组件，一系列动作类，动作映射，处理XML的实用工具类，服务器端java bean 的自动填充，支持验证的WEB 表单，国际化支持，生成HTML，实现表现逻辑和模板组成了struts的灵魂。图2显示了Struts组件是如何一起工作的。<br /><br /></p>
		<center>
				<img style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-BOTTOM: black 1px solid" src="http://java.ccidnet.com/col/attachment/2006/4/663947.gif" />
		</center>
		<p>
				<br />
				<br />Struts 的ActionServlet 控制导航流。其他Struts 类，比如Action, 用来访问业务逻辑类。当 ActionServlet 从容器接收到一个请求，它使用URI (或者路径“path”) 来决定哪个Action 将用来处理请求。一个 Action可以校验输入，并且访问业务层以从数据库或其他数据服务中检索信息。<br /><br />为校验输入或者使用输入来更新数据库， Action 需要知道什么被提交上来。并不是强制每个Action 从请求中抓取这些值，而是由 ActionServlet 将输入绑定到JavaBean中。输入 bean是Struts ActionForm c类的子类。ActionServlet 通过查找请求的路径可以决定使用哪个ActionForm，Action 也是通过同样的方法选取的。每个Action都必须以HTTP 响应进行应答。 通常, Struts Action 并不自行加工响应信息，而是将请求转发到其他资源，比如JSP 页面。Struts 提供一个ActionForward 类，用来将一个页面的路径存储为逻辑名称。当完成业务逻辑后，Action 选择并向Servlet返回一个ActionForward。Servlet 然后使用存储在ActionForward 对象中的路径来调用页面完成响应。<br /><br />Struts 将这些细节都绑定在一个ActionMapping 对象中。每个ActionMapping 相对于一个特定的路径。当某个路径被请求时，Servlet 就查询ActionMapping 对象。ActionMapping对象告诉servlet哪个Actions、 ActionForms 和 ActionForwards 将被使用。<br /><br />所有这些细节，关于Action， ActionForm， ActionForward， ActionMapping，以及其他一些东西，都在struts-config.xml 文件中定义。 ActionServlet 在启动时读取这个配置文件，并创建一个配置对象数据库。在运行时，Struts 应用根据的是文件创建的配置对象，而不是文件本身。<br /><br /><b>基于Struts框架的应用设计实例</b><br /><br />本文以“面向铸造行业的网络化制造ASP平台开发”项目中的软件租用模块为例，来说明如何设计基于Struts框架的Web应用。在该模块中，用户合法登陆网站后，可以根据需要选择所要租用的软件类型及软件中的功能模块，确认信息提交服务器后，用户将收到系统给予的登陆密码，用户即可登陆网站，在线使用租用软件，实行业务托管。<br /><br />根据项目需求分析,确定该系统必须具备的性能有:1)良好的交互性:工作内容中有相当大的部分是人机交流,这就要求系统的交互性要强。2)较好的可扩展性:工作的内容和形式具有多变性,要求系统具有良好的可扩展性。3)良好的可维护性:系统投入使用后,主要是由管理员承担系统维护的工作,维护人员不定期变动,这就要求系统的可维护性强。4)具有较好的跨平台性:用户可能使用各种不同的操作系统,而且为了适应今后可能的变化,系统应具有较好的跨平台性。基于以上四点,在开发软件租用模块时,采用J2EE编程环境,并相应采用了专为J2EE定制的Struts框架。<br /><br />做基于Struts框架的项目开发,关键是要有一个好的整体模型,计划好系统中包括哪几个模块,每个模块各需要什么样的FormBean、JavaBean,各种处理结果都通过哪些JSP页面来展现,同时配置好struts-config.xml文件。本系统的设计模型如图3所示。<br /><br /></p>
		<center>
				<img style="BORDER-RIGHT: black 1px solid; BORDER-TOP: black 1px solid; BORDER-LEFT: black 1px solid; BORDER-BOTTOM: black 1px solid" src="http://java.ccidnet.com/col/attachment/2006/4/663949.gif" />
		</center>
		<p>
				<br />
				<br />ActionServlet接受所有的HTTP请求,然后根据配置文件的内容,决定将请求映射到哪一个Action对象,本系统中有两个Action对象,分别对应着登陆远程软件(LogonAction)和系统反馈密码(MailAction)。<br /><br />LogonAction首先会验证用户是否已经登录,如果没有登录则重定向到登录页面(Logon.jsp),验证通过后根据请求参数决定下一步的处理,如果用户还没有选择租用软件，则转到软件介绍租用界面（Query.jsp），选择需要租用的软件或软件的某些模块，提交信息后，MailAction使服务器向用户提交密码，用户接收到密码后，登陆运行软件。<br /><br />如果用户登陆软件成功，则通过配置文件struts-config.xml中的ActionForward，通过GetInfo对象把该用户租用的软件信息读取道FormBean中，然后调用JSP页面显示Bean里的数据。如果是保存数据信息,则调SaveInfo对象将FormBean里保持的信息存入数据库；如果是修改信息,则调ModifyInfo对象将FormBean里保持的修改后的信息存入数据库；如果是删除数据信息,则调用DeleteInfo对象将FormBean里保持的信息从数据库中删除。<br /><br />经过这样设计的系统,用户界面和数据处理已经完全分离,再加上在JSP页面中使用了自定义标记,使页面中没有了Java的脚本代码,这样Web界面的设计和后端程序的编写就有了清晰的界线,便于开发团队的分工,并且维护起来也很方便。<br /><br /><b>结束语</b><br /><br />Struts是一种非常优秀的基于J2EE的MVC应用框架,虽然从正式发布到现在也只有两年多的时间,但它已经越来越多地运用于企业平台之上,许多大型网站已成功地应用了Struts框架。本文在总结了Struts框架技术及其工作原理的基础上，结合“面向铸造行业的网络化制造ASP平台开发”项目，提出了在线租用模块的设计思路,这为今后更好的应用采用Struts框架提供了参考。</p>
<img src ="http://www.blogjava.net/machilansing/aggbug/64193.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2006-08-17 19:36 <a href="http://www.blogjava.net/machilansing/archive/2006/08/17/Struts.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java多线程－－BusyFlag或Lock</title><link>http://www.blogjava.net/machilansing/archive/2006/08/17/BusyFlag_Lock.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Thu, 17 Aug 2006 11:30:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2006/08/17/BusyFlag_Lock.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/64190.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2006/08/17/BusyFlag_Lock.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/64190.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/64190.html</trackback:ping><description><![CDATA[
		<p>Java语言内置了synchronized关键字用于对多线程进行同步，大大方便了Java中多线程程序的编写。但是仅仅使用synchronized关键字还不能满足对多线程进行同步的所有需要。大家知道，synchronized仅仅能够对方法或者代码块进行同步，如果我们一个应用需要跨越多个方法进行同步，synchroinzed就不能胜任了。在C++中有很多同步机制，比如信号量、互斥体、临届区等。在Java中也可以在synchronized语言特性的基础上，在更高层次构建这样的同步工具，以方便我们的使用。<br />    当前，广为使用的是由Doug Lea编写的一个Java中同步的工具包，可以在这儿了解更多这个包的详细情况：<br />    <a class="l2" href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html" target="_blank">http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html</a><br />    该工具包已经作为JSR166正处于JCP的控制下，即将作为JDK1.5的正式组成部分。本文并不打算详细剖析这个工具包，而是对多种同步机制的一个介绍，同时给出这类同步机制的实例实现，这并不是工业级的实现。但其中会参考Doug Lea的这个同步包中的工业级实现的一些代码片断。<br />    本例中还沿用上篇中的Account类，不过我们这儿编写一个新的ATM类来模拟自动提款机，通过一个ATMTester的类，生成10个ATM线程，同时对John账户进行查询、提款和存款操作。Account类做了一些改动，以便适应本篇的需要：<br /><br /></p>
		<div class="codeStyle">
				<ol>
						<li>
								<b>
										<font color="#0000ff">import</font>
								</b> java.util.<b><a href="http://www.javaresearch.org/source/jdk142/java/util/HashMap.java.html" target="_blank"><font class="classLink"><u>HashMap</u></font></a></b>; 
</li>
						<li>
								<b>
										<font color="#0000ff">import</font>
								</b> java.util.<b><a href="http://www.javaresearch.org/source/jdk142/java/util/Map.java.html" target="_blank"><font class="classLink"><u>Map</u></font></a></b>; 
</li>
						<li>
						</li>
						<li>
								<b>
										<font color="#0000ff">class</font>
								</b> Account { 
</li>
						<li>    <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/String.java.html" target="_blank"><font class="classLink"><u>String</u></font></a></b> name; 
</li>
						<li>    <i><font color="#339900">//float amount;</font></i></li>
						<li>     
</li>
						<li>    <i><font color="#339900">//使用一个Map模拟持久存储</font></i></li>
						<li>    <b><font color="#0000ff">static</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/util/Map.java.html" target="_blank"><font class="classLink"><u>Map</u></font></a></b> storage = <b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/util/HashMap.java.html" target="_blank"><font class="classLink"><u>HashMap</u></font></a></b>(); 
</li>
						<li>    <b><font color="#0000ff">static</font></b> { 
</li>
						<li>        storage.put(<font color="#ff33ff">"John"</font>, <b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Float.java.html" target="_blank"><font class="classLink"><u>Float</u></font></a></b>(1000.0f)); 
</li>
						<li>        storage.put(<font color="#ff33ff">"Mike"</font>, <b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Float.java.html" target="_blank"><font class="classLink"><u>Float</u></font></a></b>(800.0f)); 
</li>
						<li>    }     
</li>
						<li>     
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> Account(<b><a href="http://www.javaresearch.org/source/jdk142/java/lang/String.java.html" target="_blank"><font class="classLink"><u>String</u></font></a></b> name) { 
</li>
						<li>        <i><font color="#339900">//System.out.println("new account:" + name);</font></i></li>
						<li>        <b><font color="#0000ff">this</font></b>.name = name; 
</li>
						<li>        <i><font color="#339900">//this.amount = ((Float)storage.get(name)).floatValue();</font></i></li>
						<li>    } 
</li>
						<li>
						</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">synchronized</font></b> <b><font color="#0000ff">void</font></b> deposit(<b><font color="#0000ff">float</font></b> amt) { 
</li>
						<li>        <b><font color="#0000ff">float</font></b> amount = ((<b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Float.java.html" target="_blank"><font class="classLink"><u>Float</u></font></a></b>)storage.get(name)).floatValue(); 
</li>
						<li>        storage.put(name, <b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Float.java.html" target="_blank"><font class="classLink"><u>Float</u></font></a></b>(amount + amt)); 
</li>
						<li>    } 
</li>
						<li>
						</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">synchronized</font></b> <b><font color="#0000ff">void</font></b> withdraw(<b><font color="#0000ff">float</font></b> amt) <b><font color="#0000ff">throws</font></b> InsufficientBalanceException { 
</li>
						<li>        <b><font color="#0000ff">float</font></b> amount = ((<b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Float.java.html" target="_blank"><font class="classLink"><u>Float</u></font></a></b>)storage.get(name)).floatValue(); 
</li>
						<li>        <b><font color="#0000ff">if</font></b> (amount &gt;= amt) 
</li>
						<li>            amount -= amt; 
</li>
						<li>        <b><font color="#0000ff">else</font></b>  
</li>
						<li>            <b><font color="#0000ff">throw</font></b> <b><font color="#0000ff">new</font></b> InsufficientBalanceException(); 
</li>
						<li>                 
</li>
						<li>        storage.put(name, <b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Float.java.html" target="_blank"><font class="classLink"><u>Float</u></font></a></b>(amount)); 
</li>
						<li>    } 
</li>
						<li>
						</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">float</font></b> getBalance() { 
</li>
						<li>        <b><font color="#0000ff">float</font></b> amount = ((<b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Float.java.html" target="_blank"><font class="classLink"><u>Float</u></font></a></b>)storage.get(name)).floatValue(); 
</li>
						<li>        <b><font color="#0000ff">return</font></b> amount; 
</li>
						<li>    } 
</li>
						<li>} </li>
				</ol>
		</div>
		<p>
				<br />
				<br />在新的Account类中，我们采用一个HashMap来存储账户信息。Account由ATM类通过login登录后使用：<br /><br /></p>
		<div class="codeStyle">
				<ol>
						<li>
								<b>
										<font color="#0000ff">public</font>
								</b> <b><font color="#0000ff">class</font></b> ATM { 
</li>
						<li>    Account acc; 
</li>
						<li>     
</li>
						<li>    <i><font color="#339900">//作为演示，省略了密码验证</font></i></li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">boolean</font></b> login(<b><a href="http://www.javaresearch.org/source/jdk142/java/lang/String.java.html" target="_blank"><font class="classLink"><u>String</u></font></a></b> name) { 
</li>
						<li>        <b><font color="#0000ff">if</font></b> (acc != <b><font color="#0000ff">null</font></b>) 
</li>
						<li>            <b><font color="#0000ff">throw</font></b> <b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/IllegalArgumentException.java.html" target="_blank"><font class="classLink"><u>IllegalArgumentException</u></font></a></b>(<font color="#ff33ff">"Already logged in!"</font>); 
</li>
						<li>        acc = <b><font color="#0000ff">new</font></b> Account(name); 
</li>
						<li>        <b><font color="#0000ff">return</font></b> <b><font color="#0000ff">true</font></b>; 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">void</font></b> deposit(<b><font color="#0000ff">float</font></b> amt) { 
</li>
						<li>        acc.deposit(amt); 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">void</font></b> withdraw(<b><font color="#0000ff">float</font></b> amt) <b><font color="#0000ff">throws</font></b> InsufficientBalanceException  { 
</li>
						<li>            acc.withdraw(amt); 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">float</font></b> getBalance() { 
</li>
						<li>        <b><font color="#0000ff">return</font></b> acc.getBalance(); 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">void</font></b> logout () { 
</li>
						<li>        acc = <b><font color="#0000ff">null</font></b>; 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>} 
</li>
						<li>
								<p style="TEXT-INDENT: 2em">下面是ATMTester，在ATMTester中首先生成了10个ATM实例，然后启动10个线程，同时登录John的账户，先查询余额，然后，再提取余额的80％，然后再存入等额的款（以维持最终的余额的不变）。按照我们的预想，应该不会发生金额不足的问题。首先看代码：<br /><br /></p>
								<div class="codeStyle">
										<ol>
												<li>
														<b>
																<font color="#0000ff">public</font>
														</b> <b><font color="#0000ff">class</font></b> ATMTester { 
</li>
												<li>    <b><font color="#0000ff">private</font></b> <b><font color="#0000ff">static</font></b> <b><font color="#0000ff">final</font></b> <b><font color="#0000ff">int</font></b> NUM_OF_ATM = 10; 
</li>
												<li>
												</li>
												<li>
												</li>
												<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">static</font></b> <b><font color="#0000ff">void</font></b> main(<b><a href="http://www.javaresearch.org/source/jdk142/java/lang/String.java.html" target="_blank"><font class="classLink"><u>String</u></font></a></b>[] args) { 
</li>
												<li>        ATMTester tester = <b><font color="#0000ff">new</font></b> ATMTester(); 
</li>
												<li>         
</li>
												<li>        <b><font color="#0000ff">final</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Thread.java.html" target="_blank"><font class="classLink"><u>Thread</u></font></a></b> thread[] = <b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Thread.java.html" target="_blank"><font class="classLink"><u>Thread</u></font></a></b>[NUM_OF_ATM]; 
</li>
												<li>        <b><font color="#0000ff">final</font></b> ATM atm[] = <b><font color="#0000ff">new</font></b> ATM[NUM_OF_ATM]; 
</li>
												<li>        <b><font color="#0000ff">for</font></b> (<b><font color="#0000ff">int</font></b> i=0; i<num_of_atm;&nbsp;i++)&nbsp;{><li>            atm[i] = <b><font color="#0000ff">new</font></b> ATM(); 
</li><li>            thread[i] = <b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Thread.java.html" target="_blank"><font class="classLink"><u>Thread</u></font></a></b>(tester.<b><font color="#0000ff">new</font></b> Runner(atm[i])); 
</li><li>            thread[i].start(); 
</li><li>        }     
</li><li>         
</li><li>    } 
</li><li>     
</li><li>    <b><font color="#0000ff">class</font></b> Runner <b><font color="#0000ff">implements</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Runnable.java.html" target="_blank"><font class="classLink"><u>Runnable</u></font></a></b> { 
</li><li>        ATM atm; 
</li><li>         
</li><li>        Runner(ATM atm) { 
</li><li>            <b><font color="#0000ff">this</font></b>.atm = atm; 
</li><li>        } 
</li><li>         
</li><li>        <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">void</font></b> run() { 
</li><li>            atm.login(<font color="#ff33ff">"John"</font>); 
</li><li>            <i><font color="#339900">//查询余额</font></i></li><li>            <b><font color="#0000ff">float</font></b> bal = atm.getBalance(); 
</li><li>            <b><font color="#0000ff">try</font></b> { 
</li><li>                <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Thread.java.html" target="_blank"><font class="classLink"><u>Thread</u></font></a></b>.sleep(1); <i><font color="#339900">//模拟人从查询到取款之间的间隔</font></i></li><li>            } <b><font color="#0000ff">catch</font></b> (<b><a href="http://www.javaresearch.org/source/jdk142/java/lang/InterruptedException.java.html" target="_blank"><font class="classLink"><u>InterruptedException</u></font></a></b> e) { 
</li><li>                <i><font color="#339900">// ignore it</font></i></li><li>            }  
</li><li>             
</li><li>            <b><font color="#0000ff">try</font></b> { 
</li><li>                <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/System.java.html" target="_blank"><font class="classLink"><u>System</u></font></a></b>.out.println(<font color="#ff33ff">"Your balance is:"</font> + bal); 
</li><li>                <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/System.java.html" target="_blank"><font class="classLink"><u>System</u></font></a></b>.out.println(<font color="#ff33ff">"withdraw:"</font> + bal * 0.8f); 
</li><li>                atm.withdraw(bal * 0.8f); 
</li><li>                <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/System.java.html" target="_blank"><font class="classLink"><u>System</u></font></a></b>.out.println(<font color="#ff33ff">"deposit:"</font> + bal * 0.8f); 
</li><li>                atm.deposit(bal * 0.8f); 
</li><li>            } <b><font color="#0000ff">catch</font></b> (InsufficientBalanceException e1) { 
</li><li>                <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/System.java.html" target="_blank"><font class="classLink"><u>System</u></font></a></b>.out.println(<font color="#ff33ff">"余额不足！"</font>); 
</li><li>            } <b><font color="#0000ff">finally</font></b> { 
</li><li>                                    atm.logout(); 
</li><li>                           } 
</li><li></li><li>        } 
</li><li>    } 
</li><li>} </li></num_of_atm;&nbsp;i++)&nbsp;{></li>
										</ol>
								</div>
								<br />
								<br />运行ATMTester，结果如下（每次运行结果都有所差异）：<br /><br />Your balance is:1000.0<br />withdraw:800.0<br />deposit:800.0<br />Your balance is:1000.0<br />Your balance is:1000.0<br />withdraw:800.0<br />withdraw:800.0<br />余额不足！<br />Your balance is:200.0<br />Your balance is:200.0<br />Your balance is:200.0<br />余额不足！<br />Your balance is:200.0<br />Your balance is:200.0<br />Your balance is:200.0<br />Your balance is:200.0<br />withdraw:160.0<br />withdraw:160.0<br />withdraw:160.0<br />withdraw:160.0<br />withdraw:160.0<br />withdraw:160.0<br />withdraw:160.0<br />deposit:160.0<br />余额不足！<br />余额不足！<br />余额不足！<br />余额不足！<br />余额不足！<br />余额不足！<br /><br />为什么会出现这样的情况？因为我们这儿是多个ATM同时对同一账户进行操作，比如一个ATM查询出了余额为1000，第二个ATM也查询出了余额1000，然后两者都期望提取出800，那么只有第1个用户能够成功提出，因为在第1个提出800后，账户真实的余额就只有200了，而第二个用户仍认为余额为1000。这个问题是由于多个ATM同时对同一个账户进行操作所不可避免产生的后果。要解决这个问题，就必须限制同一个账户在某一时刻，只能由一个ATM进行操作。如何才能做到这一点？直接通过synchronized关键字可以吗？非常遗憾！因为我们现在需要对整个Account的多个方法进行同步，这是跨越多个方法的，而synchronized仅能对方法或者代码块进行同步。在下一篇我们将通过编写一个锁对象达到这个目的。 </li>
				</ol>
		</div>
		<p>我们首先开发一个BusyFlag的类，类似于C++中的Simaphore。<br /><br /></p>
		<div class="codeStyle">
				<ol>
						<li>
								<b>
										<font color="#0000ff">public</font>
								</b> <b><font color="#0000ff">class</font></b> BusyFlag { 
</li>
						<li>    <b><font color="#0000ff">protected</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Thread.java.html" target="_blank"><font class="classLink"><u>Thread</u></font></a></b> busyflag = <b><font color="#0000ff">null</font></b>; 
</li>
						<li>    <b><font color="#0000ff">protected</font></b> <b><font color="#0000ff">int</font></b> busycount = 0; 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">synchronized</font></b> <b><font color="#0000ff">void</font></b> getBusyFlag() { 
</li>
						<li>        <b><font color="#0000ff">while</font></b> (tryGetBusyFlag() == <b><font color="#0000ff">false</font></b>) { 
</li>
						<li>            <b><font color="#0000ff">try</font></b> { 
</li>
						<li>                wait(); 
</li>
						<li>            } <b><font color="#0000ff">catch</font></b> (<b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Exception.java.html" target="_blank"><font class="classLink"><u>Exception</u></font></a></b> e) {}             
</li>
						<li>        } 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">private</font></b> <b><font color="#0000ff">synchronized</font></b> <b><font color="#0000ff">boolean</font></b> tryGetBusyFlag() { 
</li>
						<li>        <b><font color="#0000ff">if</font></b> (busyflag == <b><font color="#0000ff">null</font></b>) { 
</li>
						<li>            busyflag = <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Thread.java.html" target="_blank"><font class="classLink"><u>Thread</u></font></a></b>.currentThread(); 
</li>
						<li>            busycount = 1; 
</li>
						<li>            <b><font color="#0000ff">return</font></b> <b><font color="#0000ff">true</font></b>; 
</li>
						<li>        } 
</li>
						<li>         
</li>
						<li>        <b><font color="#0000ff">if</font></b> (busyflag == <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Thread.java.html" target="_blank"><font class="classLink"><u>Thread</u></font></a></b>.currentThread()) { 
</li>
						<li>            busycount++; 
</li>
						<li>            <b><font color="#0000ff">return</font></b> <b><font color="#0000ff">true</font></b>; 
</li>
						<li>        } 
</li>
						<li>        <b><font color="#0000ff">return</font></b> <b><font color="#0000ff">false</font></b>;         
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">synchronized</font></b> <b><font color="#0000ff">void</font></b> freeBusyFlag() { 
</li>
						<li>        <b><font color="#0000ff">if</font></b>(getOwner()== <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Thread.java.html" target="_blank"><font class="classLink"><u>Thread</u></font></a></b>.currentThread()) { 
</li>
						<li>            busycount--; 
</li>
						<li>            <b><font color="#0000ff">if</font></b>(busycount==0) { 
</li>
						<li>                busyflag = <b><font color="#0000ff">null</font></b>; 
</li>
						<li>                                     notify(); 
</li>
						<li>                            } 
</li>
						<li>        } 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">synchronized</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Thread.java.html" target="_blank"><font class="classLink"><u>Thread</u></font></a></b> getOwner() { 
</li>
						<li>        <b><font color="#0000ff">return</font></b> busyflag; 
</li>
						<li>    } 
</li>
						<li>} </li>
				</ol>
		</div>
		<p>
				<br />注：参考Scott Oaks &amp; Henry Wong《Java Thread》<br /><br />BusyFlag有3个公开方法：getBusyFlag, freeBusyFlag, getOwner，分别用于获取忙标志、释放忙标志和获取当前占用忙标志的线程。使用这个BusyFlag也非常地简单，只需要在需要锁定的地方，调用BusyFlag的getBusyFlag()，在对锁定的资源使用完毕时，再调用改BusyFlag的freeBusyFlag()即可。下面我们开始改造上篇中的Account和ATM类，并应用BusyFlag工具类使得同时只有一个线程能够访问同一个账户的目标得以实现。首先，要改造Account类，在Account中内置了一个BusyFlag对象，并通过此标志对象对Account进行锁定和解锁：<br /><br /></p>
		<div class="codeStyle">
				<ol>
						<li>
								<b>
										<font color="#0000ff">import</font>
								</b> java.util.<b><a href="http://www.javaresearch.org/source/jdk142/java/util/Collections.java.html" target="_blank"><font class="classLink"><u>Collections</u></font></a></b>; 
</li>
						<li>
								<b>
										<font color="#0000ff">import</font>
								</b> java.util.<b><a href="http://www.javaresearch.org/source/jdk142/java/util/HashMap.java.html" target="_blank"><font class="classLink"><u>HashMap</u></font></a></b>; 
</li>
						<li>
								<b>
										<font color="#0000ff">import</font>
								</b> java.util.<b><a href="http://www.javaresearch.org/source/jdk142/java/util/Map.java.html" target="_blank"><font class="classLink"><u>Map</u></font></a></b>; 
</li>
						<li>
						</li>
						<li>
								<b>
										<font color="#0000ff">class</font>
								</b> Account { 
</li>
						<li>    <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/String.java.html" target="_blank"><font class="classLink"><u>String</u></font></a></b> name; 
</li>
						<li>    <i><font color="#339900">//float amount;</font></i></li>
						<li>     
</li>
						<li>    BusyFlag flag = <b><font color="#0000ff">new</font></b> BusyFlag(); 
</li>
						<li>     
</li>
						<li>    <i><font color="#339900">//使用一个Map模拟持久存储</font></i></li>
						<li>    <b><font color="#0000ff">static</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/util/Map.java.html" target="_blank"><font class="classLink"><u>Map</u></font></a></b> storage = <b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/util/HashMap.java.html" target="_blank"><font class="classLink"><u>HashMap</u></font></a></b>(); 
</li>
						<li>    <b><font color="#0000ff">static</font></b> { 
</li>
						<li>        storage.put(<font color="#ff33ff">"John"</font>, <b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Float.java.html" target="_blank"><font class="classLink"><u>Float</u></font></a></b>(1000.0f)); 
</li>
						<li>        storage.put(<font color="#ff33ff">"Mike"</font>, <b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Float.java.html" target="_blank"><font class="classLink"><u>Float</u></font></a></b>(800.0f)); 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">static</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/util/Map.java.html" target="_blank"><font class="classLink"><u>Map</u></font></a></b> accounts = <b><a href="http://www.javaresearch.org/source/jdk142/java/util/Collections.java.html" target="_blank"><font class="classLink"><u>Collections</u></font></a></b>.synchronizedMap(<b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/util/HashMap.java.html" target="_blank"><font class="classLink"><u>HashMap</u></font></a></b>());     
</li>
						<li>     
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">private</font></b> Account(<b><a href="http://www.javaresearch.org/source/jdk142/java/lang/String.java.html" target="_blank"><font class="classLink"><u>String</u></font></a></b> name) { 
</li>
						<li>        <b><font color="#0000ff">this</font></b>.name = name; 
</li>
						<li>        <i><font color="#339900">//this.amount = ((Float)storage.get(name)).floatValue();</font></i></li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">synchronized</font></b> <b><font color="#0000ff">static</font></b> Account getAccount (<b><a href="http://www.javaresearch.org/source/jdk142/java/lang/String.java.html" target="_blank"><font class="classLink"><u>String</u></font></a></b> name) { 
</li>
						<li>        <b><font color="#0000ff">if</font></b> (accounts.get(name) == <b><font color="#0000ff">null</font></b>) 
</li>
						<li>            accounts.put(name, <b><font color="#0000ff">new</font></b> Account(name)); 
</li>
						<li>        <b><font color="#0000ff">return</font></b> (Account) accounts.get(name); 
</li>
						<li>    } 
</li>
						<li>
						</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">synchronized</font></b> <b><font color="#0000ff">void</font></b> deposit(<b><font color="#0000ff">float</font></b> amt) { 
</li>
						<li>        <b><font color="#0000ff">float</font></b> amount = ((<b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Float.java.html" target="_blank"><font class="classLink"><u>Float</u></font></a></b>)storage.get(name)).floatValue(); 
</li>
						<li>        storage.put(name, <b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Float.java.html" target="_blank"><font class="classLink"><u>Float</u></font></a></b>(amount + amt)); 
</li>
						<li>    } 
</li>
						<li>
						</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">synchronized</font></b> <b><font color="#0000ff">void</font></b> withdraw(<b><font color="#0000ff">float</font></b> amt) <b><font color="#0000ff">throws</font></b> InsufficientBalanceException { 
</li>
						<li>        <b><font color="#0000ff">float</font></b> amount = ((<b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Float.java.html" target="_blank"><font class="classLink"><u>Float</u></font></a></b>)storage.get(name)).floatValue(); 
</li>
						<li>        <b><font color="#0000ff">if</font></b> (amount &gt;= amt) 
</li>
						<li>            amount -= amt; 
</li>
						<li>        <b><font color="#0000ff">else</font></b>  
</li>
						<li>            <b><font color="#0000ff">throw</font></b> <b><font color="#0000ff">new</font></b> InsufficientBalanceException(); 
</li>
						<li>                 
</li>
						<li>        storage.put(name, <b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Float.java.html" target="_blank"><font class="classLink"><u>Float</u></font></a></b>(amount)); 
</li>
						<li>    } 
</li>
						<li>
						</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">float</font></b> getBalance() { 
</li>
						<li>        <b><font color="#0000ff">float</font></b> amount = ((<b><a href="http://www.javaresearch.org/source/jdk142/java/lang/Float.java.html" target="_blank"><font class="classLink"><u>Float</u></font></a></b>)storage.get(name)).floatValue(); 
</li>
						<li>        <b><font color="#0000ff">return</font></b> amount; 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">void</font></b> lock() { 
</li>
						<li>        flag.getBusyFlag(); 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">void</font></b> unlock() { 
</li>
						<li>        flag.freeBusyFlag(); 
</li>
						<li>    } 
</li>
						<li>} </li>
				</ol>
		</div>
		<p style="TEXT-INDENT: 2em">新的Account提供了两个用于锁定的方法：lock()和unlock()，供Account对象的客户端在需要时锁定Account和解锁Account，Account通过委托给BusyFlag来提供这个机制。另外，大家也发现了，新的Account中提供了对Account对象的缓存，同时去除了public的构造方法，改为使用一个静态工厂方法供用户获取Account的实例，这样做也是有必要的，因为我们希望所有的ATM机同时只能有一个能够对同一个Account进行操作，我们在Account上的锁定是对一个特定Account对象进行加锁，如果多个ATM同时实例化多个同一个user的Account对象，那么仍然可以同时操作同一个账户。所以，要使用这种机制就必须保证Account对象在系统中的唯一性，所以，这儿使用一个Account的缓存，并将Account的构造方法变为私有的。你也可以说，通过在Account类锁上进行同步，即将Account中的BusyFlag对象声明为static的，但这样就使同时只能有一台ATM机进行操作了。这样，在一台ATM机在操作时，全市其它的所有的ATM机都必须等待。<br />另外必须注意的一点是：Account中的getAccount()方法必须同步，否则，将有可能生成多个Account对象，因为可能多个线程同时到达这个方法，并监测到accounts中没有“John”的Account实例，从而实例化多个John的Account实例。s<br /><br />ATM类只需作少量改动，在login方法中锁定Account，在logout方法中解锁：<br /><br /></p>
		<div class="codeStyle">
				<ol>
						<li>
								<b>
										<font color="#0000ff">public</font>
								</b> <b><font color="#0000ff">class</font></b> ATM { 
</li>
						<li>    Account acc; 
</li>
						<li>     
</li>
						<li>    <i><font color="#339900">//作为演示，省略了密码验证</font></i></li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">synchronized</font></b> <b><font color="#0000ff">boolean</font></b> login(<b><a href="http://www.javaresearch.org/source/jdk142/java/lang/String.java.html" target="_blank"><font class="classLink"><u>String</u></font></a></b> name) { 
</li>
						<li>        <b><font color="#0000ff">if</font></b> (acc != <b><font color="#0000ff">null</font></b>) 
</li>
						<li>            <b><font color="#0000ff">throw</font></b> <b><font color="#0000ff">new</font></b> <b><a href="http://www.javaresearch.org/source/jdk142/java/lang/IllegalArgumentException.java.html" target="_blank"><font class="classLink"><u>IllegalArgumentException</u></font></a></b>(<font color="#ff33ff">"Already logged in!"</font>); 
</li>
						<li>        acc = Account.getAccount(name); 
</li>
						<li>        acc.lock(); 
</li>
						<li>        <b><font color="#0000ff">return</font></b> <b><font color="#0000ff">true</font></b>; 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">void</font></b> deposit(<b><font color="#0000ff">float</font></b> amt) { 
</li>
						<li>        acc.deposit(amt); 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">void</font></b> withdraw(<b><font color="#0000ff">float</font></b> amt) <b><font color="#0000ff">throws</font></b> InsufficientBalanceException  { 
</li>
						<li>            acc.withdraw(amt); 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">float</font></b> getBalance() { 
</li>
						<li>        <b><font color="#0000ff">return</font></b> acc.getBalance(); 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>    <b><font color="#0000ff">public</font></b> <b><font color="#0000ff">synchronized</font></b> <b><font color="#0000ff">void</font></b> logout () { 
</li>
						<li>        acc.unlock(); 
</li>
						<li>        acc = <b><font color="#0000ff">null</font></b>; 
</li>
						<li>    } 
</li>
						<li>     
</li>
						<li>} </li>
				</ol>
		</div>
		<p>
				<br />
				<br />ATMTester类不需要做任何修改即可同样运行，同时保证同一个Account同时只能由一个ATM进行操作。解决了上篇提到的多个ATM同时对同一个Account进行操作造成的问题。<br /><br />在最新的Doug Lea的util.concurrent工具包中（现处于JSR166）提供了类似的并发实用类：ReentrantLock，它实现了java .util.concurrent.locks.Lock接口（将在JDK1.5中发布），它的作用也类似于我们这儿的BusyFlag，实现机制、使用方法也相似。但这是一个工业强度的可重入锁的实现类。在ReentrantLock的API文档中有它的使用示例：<br /><br /></p>
		<div class="codeStyle">
				<ol>
						<li>     Lock l = ...;  
</li>
						<li>     l.lock(); 
</li>
						<li>     <b><font color="#0000ff">try</font></b> { 
</li>
						<li>         <i><font color="#339900">// access the resource protected by this lock</font></i></li>
						<li>     } <b><font color="#0000ff">finally</font></b> { 
</li>
						<li>         l.unlock(); 
</li>
						<li>     } </li>
				</ol>
		</div>
<img src ="http://www.blogjava.net/machilansing/aggbug/64190.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2006-08-17 19:30 <a href="http://www.blogjava.net/machilansing/archive/2006/08/17/BusyFlag_Lock.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Java企业应用－Hibernate实战全解</title><link>http://www.blogjava.net/machilansing/archive/2006/08/17/Java_Hibernate.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Thu, 17 Aug 2006 11:26:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2006/08/17/Java_Hibernate.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/64189.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2006/08/17/Java_Hibernate.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/64189.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/64189.html</trackback:ping><description><![CDATA[对象关系映射(Object Relative Mapping)简称ORM，是面向对象开发的一个热点，用来解决JDBC开发中手动进行OR映射的繁杂与不便。EJB中的实体Bean在这个领域是很著名的——既因为它的先进而著名，也因为它的低效而著名。有过实体Bean开发经验的人可能都会为实现远程接口造成的效率低下而头痛，在很多不大不小的项目中，使用实体Bean是否得不偿失，争论很大。一个轻量级的持久化方案也许能够解决一些问题，Hibernate应此而生。
<p><font face="Times New Roman" size="3"> 　　Hibernate是一个中间层，它的目的是把数据库中的关系通过一定的规则映射成为对象，让Java开发人员不用太多的考虑底层数据库的问题，只需要像通常情况下管理对象一样的管理数据。在关系数据库仍将持续占据市场的情况下，它很可观。在数据持久化领域，即便是轻量级的方案也会是复杂饶舌的，也许如同周杰伦的音乐一样不知所云。在学习它之前，最好先回想一下以前进行数据库开发中遇到的问题和不便，想想为什么需要一个持久化层，才能知道很多操作的目的是什么，以及为什么要这么干，在这个问题上我不想做更多的叙述，因为“长久以来……”这样的句式通常long（不好意思，打不出来）长，会对我的键盘和热情造成很大的磨损。如果让我写一本书，那么我会乐意去叙述什么是数据持久化，它有什么好处等等。废话少说，来了。</font></p><p><font face="Times New Roman" size="3"> 　　首先需要配置环境，下载Hibernate 2.1(www.hibernate.org)，把lib下的*.jar添加到classpath，你的数据库JDBC驱动程序也应该在classpath中。打开hibernate.properties，针对你使用的数据库，配置相应的信息，比如我使用的是MS SQL Server，配置如下：</font></p><p><font face="Times New Roman" size="3"> ## MS SQL Server</font></p><p><font face="Times New Roman" size="3"> hibernate.dialect net.sf.hibernate.dialect.SQLServerDialect<br /> hibernate.connection.driver_class com.microsoft.jdbc.sqlserver.SQLServerDriver<br /> hibernate.connection.url jdbc:microsoft:sqlserver://localhost:1433;DatabaseName=zizz<br /> hibernate.connection.username sa<br /> hibernate.connection.password</font></p><p><font face="Times New Roman" size="3"> 　　其中很大部分是已经写好的，只需要取掉注释即可，我自己只是修改了数据库名称、帐号、密码。建立一个名为zizz的数据库备用。</font></p><p><font face="Times New Roman" size="3"> 　　然后把这个文件拷贝到你的应用的根目录下。</font></p><p><font face="Times New Roman" size="3"> 　　我们谈论了很多次映射，应该首先来看看这个映射是如何完成的。假设一个最简单的应用，写一个功能最单一的留言板，设计的数据有留言的编号、留言者名称、留言内容，还有留言时间。足够简单吧，换做是你打算怎么干？我猜你要首先建立一个数据库表格，名字也许叫做guestbook。No，这不是面向对象的方式，不妨首先从对象的角度来考虑。我们当然希望每一条留言都以对象的方式呈现，每个对象应该具有的属性有：id、author、content、time。偷个懒，没有画UML。下面这个类应该是很容易理解的：</font></p><p><font face="Times New Roman" size="3"> //GuestBook.java<br /> package org.bromon.zizz;</font></p><p><font face="Times New Roman" size="3"> import java.util.*;</font></p><p><font face="Times New Roman" size="3"> public class GuestBook<br /> {<br /> private int id;<br /> private String author;<br /> private String content;<br /> private Calendar time;</font></p><p><font face="Times New Roman" size="3"> private void setId(int id)<br /> {<br />  this.id=id;<br /> }<br /> public int getId()<br /> {<br />  return(id);<br /> }</font></p><p><font face="Times New Roman" size="3"> public void setAuthor(String author)<br /> {<br />  this.author=author;<br /> }<br /> public String getAuthro()<br /> {<br />  return(author);<br /> }</font></p><p><font face="Times New Roman" size="3"> public void setContent(String content)<br /> {<br />  this.content=content;<br /> }<br /> public String getContent()<br /> {<br />  return(content);<br /> }</font></p><p><font face="Times New Roman" size="3"> public void setTime(Calendar time)<br /> {<br />  this.time=time;<br /> }<br /> public Calendar getTime()<br /> {<br />  return(time);<br /> }<br /> } </font></p><font face="Times New Roman" size="3"><p><br /> 　　基本上是最简单的Bean了，如果觉得困难的话，请你先回火星等我。</p><p> 　　需要注意的是setId方法被指定为private，这是因为我希望用这个字段做主键，它最好由系统自动生成，所以不应该由用户来指定，这个方法专为Hibernate准备，所以是私有的。</p><p> 　　如何把这个类与数据库映射起来？看看Hibernate的魔法，使用一个XML文件来描述，它应该被命名为GuestBook.hbm.xml：</p><p> &amp;lt ?xml version="1.0"? &amp;gt<br /> &amp;lt !DOCTYPE hibernate-mapping PUBLIC <br />        "-//Hibernate/Hibernate Mapping DTD 2.0//EN"<br />        "' target=_blank &amp;gthttp://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" &amp;gt </p><p> &amp;lt hibernate-mapping package="org.bromon.zizz" &amp;gt<br />    &amp;lt class name="GuestBook" table=”guestbook" lazy="true" &amp;gt<br />        &amp;lt id name="id" type="integer" unsaved-value="null" &amp;gt<br />   &amp;lt column name="id" sql-type="int" not-null="true"/ &amp;gt<br />   &amp;lt generator class="identity"/ &amp;gt<br />  &amp;lt /id &amp;gt<br />        <br />  &amp;lt property name="author" column="author" not-null="true" unique="false"/ &amp;gt<br /> &amp;lt property name="content" column="content" not-null="true"/ &amp;gt<br />  &amp;lt property name="time" column="time" not-null="true"/ &amp;gt<br />    &amp;lt /class &amp;gt <br /> &amp;lt /hibernate-mapping &amp;gt </p><p> 虽然有点陌生，但是很易读，仔细琢磨一下。</p><p> 下面来编写我们的应用，它的功能是插入数据：</p><p> //Operate.java<br /> package org.bromon.zizz;<br /> import net.sf.hibernate.*;<br /> import net.sf.hibernate.cfg.*;<br /> import net.sf.hibernate.tool.hbm2ddl.*;<br /> import java.util.*;</p><p> public class Operate<br /> {<br /> public static void main(String args[])<br /> {<br />  try<br />  {<br />   Configuration cfg=new Configuration().addClass(GuestBook.class);<br />   SessionFactory sessions=cfg.buildSessionFactory();<br />   new SchemaExport(cfg).create(true,true);<br />   Session session=sessions.openSession();<br />   <br />   GuestBook gb=new GuestBook();<br />   gb.setAuthor(“Bromon”);<br />   gb.setContent(“留言的内容”);<br />   gb.setTime(Calendar.getInstance());<br />   <br />   Transaction ts=session.beginTransaction();<br />   session.save(gb);<br />   ts.commit();<br />   session.close();<br />  }catch(Exception e)<br />  {<br />   System.out.println(e);<br />  }<br /> }<br /> } <br /> 　　编译吧：javac –d . *.java<br /> 　　执行一下：java org.bromon.zizz.Operate</p><p> 到数据库里面看看，表格已经建立好了，并且数据也已经保存。如果把</p><p> new SchemaExport().create(true,true);</p><p> 注释掉，那么系统不会创建表格，而只是在已有的表格中添加新的记录，当然，如果表格不存在的话，会产生异常。</p><p> 你已经看到了Hibernate神奇魔法的5%，它足够的复杂强大，可以让你应付复杂的应用。<br /></p><p><font face="Times New Roman" size="3">one-to-one关系<br /> 在绝大多数系统当中不可能只存在一个数据表格，否则就违背了关系数据库的初衷。表与表的关系比较复杂，可以分为几种情况： </font></p><p><font face="Times New Roman" size="3"> ● 一对一关联(one to one)<br /> ● 一对多关联(one to many)<br /> ● 多对一关联(many to one)<br /> ● 多对多关联(many to many)</font></p><p><font face="Times New Roman" size="3"> 按顺序来讲。假设一个一对一关联的例子是：<br /> 表格：person<br /> id 编号（主键）<br /> name 姓名<br /> email email地址</font></p><p><font face="Times New Roman" size="3"> 表格：spouse<br /> id 编号（外键）<br /> name 姓名</font></p><p><font face="Times New Roman" size="3"> person这个表保存用户信息，而spouse保存用户配偶的信息。在一般情况下一个人只有一个配偶，这很适合我们一对一的情况。如果你对婚外恋感兴趣的话，我们可以在一对多和多对一的关联中讨论这个问题，也许还可以在多对多中^_^（禽兽!）。</font></p><p><font face="Times New Roman" size="3"> OK，下面设计POJO：<br /> Person这个类非常简单：</font></p><p><font face="Times New Roman" size="3"> /*<br /> * Created on 2004-4-19<br /> */<br /> package org.bromon.zizz;</font></p><p><font face="Times New Roman" size="3"> /**<br /> * @author Bromon<br /> */<br /> public class Person<br /> {<br /> private int id;<br /> private String name;<br /> private String email;</font></p><p><font face="Times New Roman" size="3"> public void setId(int id)<br /> {<br />  this.id=id;<br /> }<br /> public int getId()<br /> {<br />  return(id);<br /> }</font></p><p><font face="Times New Roman" size="3"> public void setName(String name)<br /> {<br />  this.name=name;<br /> }<br /> public String getName()<br /> {<br />  return(name);<br /> }</font></p><p><font face="Times New Roman" size="3"> public void setEmail(String email)<br /> {<br />  this.email=email;<br /> }<br /> public String getEmail()<br /> {<br />  return(email);<br /> }<br /> } </font></p><font face="Times New Roman" size="3"><p><br /> 然后编写它的映射规则，这个应该能够理解了：<br /> &amp;lt ?xml version="1.0"? &amp;gt<br /> &amp;lt !DOCTYPE hibernate-mapping PUBLIC <br /> "-//Hibernate/Hibernate Mapping DTD 2.0//EN"<br /> "' target=_blank &amp;gthttp://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" &amp;gt  </p><p> &amp;lt hibernate-mapping package="org.bromon.zizz" &amp;gt<br /> &amp;lt class name="Person" table="person" lazy="true" &amp;gt<br /> &amp;lt id name="id" type="integer" unsaved-value="null" &amp;gt<br /> &amp;lt column name="id" sql-type="int" not-null="true"/ &amp;gt<br /> &amp;lt generator class="identity"/ &amp;gt<br /> &amp;lt /id &amp;gt</p><p> &amp;lt property name="name" column="name" not-null="true" unique="false"/ &amp;gt<br /> &amp;lt property name="email" column="email" not-null="false"/ &amp;gt<br /> &amp;lt /class &amp;gt <br /> &amp;lt /hibernate-mapping &amp;gt </p><p> so easy是不是？一切都按部就班。下面是Souse类：</p><p> /*<br /> * Created on 2004-4-20<br /> */<br /> package org.bromon.zizz;</p><p> /**<br /> * @author Bromon<br /> */<br /> public class Spouse<br /> {<br /> private int id;<br /> private String name;<br /> private Person person;</p><p> public void setId(int id)<br /> {<br />  this.id=id;<br /> }<br /> public int getId()<br /> {<br />  return(id);<br /> }</p><p> public void setName(String name)<br /> {<br />  this.name=name;<br /> }<br /> public String getName()<br /> {<br />  return(name);<br /> }</p><p> public void setPerson(Person person)<br /> {<br />  this.person=person;<br /> }<br /> public Person getPerson()<br /> {<br />  return(person);<br /> }<br /> } </p><p><br /> 注意里面的域person。它的映射文件：</p><p> &amp;lt ?xml version="1.0"? &amp;gt<br /> &amp;lt !DOCTYPE hibernate-mapping PUBLIC <br /> "-//Hibernate/Hibernate Mapping DTD 2.0//EN"<br /> "' target=_blank &amp;gthttp://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" &amp;gt  </p><p> &amp;lt hibernate-mapping package="org.bromon.zizz" &amp;gt<br /> &amp;lt class name="Spouse" table="spouse" lazy="true" &amp;gt<br /> &amp;lt id name="id" type="integer" unsaved-value="null" &amp;gt<br /> &amp;lt column name="id" sql-type="int" not-null="true"/ &amp;gt<br /> &amp;lt generator class="foreign" &amp;gt <br /> &amp;lt param name="property" &amp;gtperson&amp;lt /param &amp;gt <br /> &amp;lt /generator &amp;gt <br /> &amp;lt /id &amp;gt</p><p> &amp;lt property name="name" column="name" not-null="true" unique="false"/ &amp;gt<br /> &amp;lt one-to-one name="person" class="Person" cascade="all" constrained="true" / &amp;gt<br /> &amp;lt /class &amp;gt <br /> &amp;lt /hibernate-mapping &amp;gt </p><p> 这里指明了id的generator是一个外键，和person相关联。然后指定一个one-to-one关系，不难理解是不是？Hibernate的确很符合我们的思维习惯。需要提醒的是，这种关联关系是单向的，Person并不需要去指定Spouse。</p><p> 下面来操作这两个类：</p><p> /*<br /> * Created on 2004-4-20<br /> */<br /> package org.bromon.zizz;<br /> import net.sf.hibernate.*;<br /> import net.sf.hibernate.cfg.*;<br /> import net.sf.hibernate.tool.hbm2ddl.*;<br /> /**<br /> * @author Bromon<br /> */<br /> public class OperateSpouse<br /> {<br /> public static void main(String args[])<br /> {<br />  try<br />  {<br />   Configuration cfg=new Configuration().addClass(Spouse.class);<br />   cfg.addClass(Person.class);<br />   SessionFactory factory=cfg.buildSessionFactory();<br />   new SchemaExport(cfg).create(true,true);<br />   Session session=factory.openSession();<br />  <br />   Person person=new Person();<br />   person.setName("bromon");<br />   person.setEmail("bromon@163.com");<br />  <br />   Spouse spouse=new Spouse();<br />   spouse.setName("who");<br />   spouse.setPerson(person);<br />   <br />   Transaction ts=session.beginTransaction();<br />   session.save(person);<br />   session.save(spouse);<br />   ts.commit();<br />   session.close();<br />  }catch(Exception e)<br />  {<br />   System.out.println(e);<br />  }<br /> } <br /> } </p><p><br /> 这个例子和第一篇中的例子非常相似。OK，执行一下，然后看看zizz数据库，搞掂。<br /></p><p><font face="Times New Roman" size="3">Many-to-One关系</font></p><p><font face="Times New Roman" size="3"> 很明显一对多或者多对一关系是关系数据库中非常常见的现象，下面通过父亲-儿子的例子来演示一对多关系，多对一关系是类似的，不过在我们的这个例子中不宜采用，否则会带来伦理学上的问题。 </font></p><p><font face="Times New Roman" size="3"> 首先定义Child类：<br /> /*<br />  * Created on 2004-5-8<br />  */<br /> package org.bromon.zizz;</font></p><p><font face="Times New Roman" size="3"> /**<br />  * @author Bromon<br />  */<br /> public class Child<br /> {<br />  private int id;<br />  private String name;<br />  private int fatherId;<br />  private Person father;</font></p><p><font face="Times New Roman" size="3">  public Child(){}<br />  <br />  /**<br />   * @return<br />   */<br />  public Person getFather()<br />  {<br />   return father;<br />  }</font></p><p><font face="Times New Roman" size="3">  /**<br />   * @return<br />   */<br />  public int getFatherId()<br />  {<br />   return fatherId;<br />  }</font></p><p><font face="Times New Roman" size="3">  /**<br />   * @return<br />   */<br />  public int getId()<br />  {<br />   return id;<br />  }</font></p><p><font face="Times New Roman" size="3">  /**<br />   * @return<br />   */<br />  public String getName()<br />  {<br />   return name;<br />  }</font></p><p><font face="Times New Roman" size="3">  /**<br />   * @param person<br />   */<br />  public void setFather(Person p)<br />  {<br />   father = p;<br />  }</font></p><p><font face="Times New Roman" size="3">  /**<br />   * @param i<br />   */<br />  public void setFatherId(int i)<br />  {<br />   fatherId = i;<br />  }</font></p><p><font face="Times New Roman" size="3">  /**<br />   * @param i<br />   */<br />  public void setId(int i)<br />  {<br />   id = i;<br />  }</font></p><p><font face="Times New Roman" size="3">  /**<br />   * @param string<br />   */<br />  public void setName(String string)<br />  {<br />   name = string;<br />  }</font></p><p><font face="Times New Roman" size="3"> }</font></p><p><font face="Times New Roman" size="3"> 这里的fatherId是外键，关联person表的id字段。</font></p><p><font face="Times New Roman" size="3"> 下面是映射文件Child.hbm.xml：<br /> &amp;lt ?xml version="1.0"? &amp;gt<br /> &amp;lt !DOCTYPE hibernate-mapping PUBLIC <br />        "-//Hibernate/Hibernate Mapping DTD 2.0//EN"<br />        "' target=_blank &amp;gthttp://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd" &amp;gt  </font></p><p><font face="Times New Roman" size="3"> &amp;lt hibernate-mapping package="org.bromon.zizz" &amp;gt<br />  &amp;lt class name="Child" table="child" lazy="true" &amp;gt<br />   &amp;lt id name="id" type="integer" unsaved-value="null" &amp;gt<br />    &amp;lt column name="id" sql-type="int" not-null="true"/ &amp;gt<br />    &amp;lt generator class="identity"/ &amp;gt<br />   &amp;lt /id &amp;gt<br />        <br />   &amp;lt property name="name" column="name" not-null="true" unique="false"/ &amp;gt<br />   &amp;lt many-to-one name="father" column="fatherid" / &amp;gt<br />       <br />  &amp;lt /class &amp;gt <br /> &amp;lt /hibernate-mapping &amp;gt<br /> 需要注意的是fatherId并没有做为一个property被映射，而是在many-to-one声明中使用。</font></p><p><font face="Times New Roman" size="3"> 需要对Person..java做修改，添加以下代码：</font></p><p><font face="Times New Roman" size="3"> import java.util.*;</font></p><p><font face="Times New Roman" size="3"> private Set children=new HashSet();<br /> /**<br /> * @return<br /> */<br /> public Set getChildren()<br /> {<br />  return children;<br /> }<br /> /**<br /> * @param set<br /> */<br /> public void setChildren(Set set)<br /> {<br />  children = set;<br /> }</font></p><p><font face="Times New Roman" size="3"> 然后修改Person.hbm.xml，对添加的代码做映射：</font></p><p><font face="Times New Roman" size="3"> &amp;lt set name="books" lazy="true" inverse="true" cascade="all"  &amp;gt <br />  &amp;lt key column="fatherid"/ &amp;gt <br />  &amp;lt one-to-many class="Child" / &amp;gt <br /> &amp;lt /set &amp;gt</font></p><p><font face="Times New Roman" size="3"> 这里的key column是child表的外键，inverse需要指定为true。</font></p><p><font face="Times New Roman" size="3"> 下面做操作一下，功能是查询person表中id=1的记录，作为小孩的父亲，然后给child表添加一条新记录。</font></p><p><font face="Times New Roman" size="3"> /*<br />  * Created on 2004-5-8<br />  */<br /> package org.bromon.zizz;<br /> import net.sf.hibernate.*;<br /> import net.sf.hibernate.cfg.*;<br /> import net.sf.hibernate.tool.hbm2ddl.*;<br /> /**<br />  * @author Bromon<br />  */<br /> public class OperateChild<br /> {<br />  /**<br />   * @param args<br />   */<br />  public static void main(String args[])<br />  {<br />   try<br />   {<br />    Configuration cfg = new Configuration().addClass(Person.class);<br />    cfg.addClass(Child.class);<br />    SessionFactory sessions = cfg.buildSessionFactory();<br />    new SchemaExport(cfg).create(true, true);<br />    Session session = sessions.openSession();<br />    <br />    Child c=new Child();<br />    <br />    /*Query q=session.createQuery("from org.bromon.zizz.Person as p where p.id=1");<br />    Person p=(Person)q.list().get(0);*/<br />    <br />    Person p=(Person)session.find("from org.bromon.zizz.Person as p where p.id=?",new Integer(1),Hibernate.INTEGER).get(0);<br />    System.out.println(p.getName());<br />    c.setName("andy");<br />    c.setFather(p);<br />    <br />    Transaction ts = session.beginTransaction();<br />    session.save(c);<br />    ts.commit();<br />    session.close();<br />   } catch (Exception e)<br />   {<br />    System.out.println(e);<br />   }<br />  }<br /> }</font></p><p><font face="Times New Roman" size="3"> 被注释掉的部分是HQL的另外一种查询方法。在这个例子中可以看出对象的查询非常容易，不需要自己再去封装数据，修改和删除对象也很容易：</font></p><p><font face="Times New Roman" size="3"> //得到一个对象<br /> Query q=session.createQuery("from org.bromon.zizz.Person as p where p.id=1");<br /> Person p=(Person)q.list().get(0);</font></p><p><font face="Times New Roman" size="3"> //修改数据<br /> p.setName(“Mr Smith”);</font></p><p><font face="Times New Roman" size="3"> //保存数据<br /> session.save(p);<br /> session.flush();</font></p><p><font face="Times New Roman" size="3"> //删除数据<br /> session.delete(p);<br /> session.flush();</font></p></font></font><img src ="http://www.blogjava.net/machilansing/aggbug/64189.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2006-08-17 19:26 <a href="http://www.blogjava.net/machilansing/archive/2006/08/17/Java_Hibernate.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Oracle 10g TO_DATE() ora-01830 领悟共勉</title><link>http://www.blogjava.net/machilansing/archive/2006/08/10/62857.html</link><dc:creator>Lansing</dc:creator><author>Lansing</author><pubDate>Thu, 10 Aug 2006 13:03:00 GMT</pubDate><guid>http://www.blogjava.net/machilansing/archive/2006/08/10/62857.html</guid><wfw:comment>http://www.blogjava.net/machilansing/comments/62857.html</wfw:comment><comments>http://www.blogjava.net/machilansing/archive/2006/08/10/62857.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.blogjava.net/machilansing/comments/commentRss/62857.html</wfw:commentRss><trackback:ping>http://www.blogjava.net/machilansing/services/trackbacks/62857.html</trackback:ping><description><![CDATA[
		<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">今天在 DRM中报错ora-01830 </font>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">把sql语句输出作了以下的实验，发现是时间多了一个.0</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">后来的办法是先把这个时间转成to_char，再转成to_date</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">SQL&gt; select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:ss') from dual;</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:ss') from dual</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">ORA-01830: 日期格式图片在转换整个输入字符串之前结束</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">SQL&gt; select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:sssss') from dual;</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:sssss') from dual</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">ORA-01836: 小时与日中的秒发生冲突</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">SQL&gt; select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:ss.sssss') from dual;</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:ss.sssss') from dual</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">ORA-01836: 小时与日中的秒发生冲突</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">SQL&gt; select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:ff') from dual;</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">select to_date('2005-10-01 12:01:01.0','yyyy-mm-dd hh24:mi:ff') from dual</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">ORA-01821: 日期格式无法识别</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">------------------------------------------------------------------</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">必须保证传入的字符串和要转换的格式精确匹配</font>
		</p>
		<p>
				<font style="BACKGROUND-COLOR: #d3d3d3" face="Courier" color="#0000ff">SQL&gt; SELECT TO_DATE('11-10-1996-13:51:21','DD/MM/YYYY-HH24') A FROM dual; <br /><br />ERROR: <br />ORA-01830: date format picture ends before converting entire input string.</font>
		</p>
		<p>
				<font face="Courier">
						<font style="BACKGROUND-COLOR: #d3d3d3" color="#0000ff">SQL&gt; SELECT TO_DATE('11-10-1996-13:51:21','DD/MM/YYYY-HH24:MI:SS') B FROM dual; <br />－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－－<br /></font>以上是转载的<br />后来我是这么做的哈：<br /><br />SELECT中将其他表的日期TO_CHAR下，然后再将值在INSERT时TO_DATE!<br />具体的做法如下：<br /><br />SELECT TO_CHAR(parameter,'YYYY-MM-DD HH24:MI:SS') AS TIME<br />FROM TABLE_NAME_1;<br /><br />...<br />...<br /><br />INSERT INTO TABLE_NAME_2<br />(COLUME_NAME_1)<br />VALUE (TO_DATE('"+TIME+"','YYYY-MM-DD HH24:MI:SS'));<br /><br />然后就OK了，呵呵，看来要学的还真多！</font>
		</p>
<img src ="http://www.blogjava.net/machilansing/aggbug/62857.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.blogjava.net/machilansing/" target="_blank">Lansing</a> 2006-08-10 21:03 <a href="http://www.blogjava.net/machilansing/archive/2006/08/10/62857.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>