??xml version="1.0" encoding="utf-8" standalone="yes"?>亚洲精品视频在线看,亚洲人成网站在线观看青青,亚洲成A人片在线观看无码不卡http://www.tkk7.com/William/archive/2006/08/25/65804.htmlWilliamWilliamFri, 25 Aug 2006 07:05:00 GMThttp://www.tkk7.com/William/archive/2006/08/25/65804.htmlhttp://www.tkk7.com/William/comments/65804.htmlhttp://www.tkk7.com/William/archive/2006/08/25/65804.html#Feedback5http://www.tkk7.com/William/comments/commentRss/65804.htmlhttp://www.tkk7.com/William/services/trackbacks/65804.html阅读全文

William 2006-08-25 15:05 发表评论
]]>
中远公司JAVA面试题目http://www.tkk7.com/William/archive/2006/07/22/59601.htmlWilliamWilliamSat, 22 Jul 2006 15:33:00 GMThttp://www.tkk7.com/William/archive/2006/07/22/59601.htmlhttp://www.tkk7.com/William/comments/59601.htmlhttp://www.tkk7.com/William/archive/2006/07/22/59601.html#Feedback4http://www.tkk7.com/William/comments/commentRss/59601.htmlhttp://www.tkk7.com/William/services/trackbacks/59601.html一、Java语言
1、面向对象的三个基本特征
2、方法重载和Ҏ(gu)重写的概念和区别
 (tng)3、接口和内部cR抽象类的特?br />4、文件读写的基本c?br />5、串行化的注意事以?qing)如何实C行化
 (tng)6、线E的基本概念、线E的基本状态以?qing)状态之间的关系
 (tng)7、线E的同步、如何实现线E的同步
8、几U常用的数据l构?qing)内部实现原理?br />9、Socket通信(TCP、UDP区别?qing)Java实现方式)
10、Java的事件委托机制和垃圾回收机制
11、JDBC调用数据库的基本步骤
12、解析XML文g的几U方式和区别
13、Java四种基本权限的定?br />14、Java的国际化
二、JSP
 (tng)1、至要能说?个隐含对象以?qing)他们的区?br /> (tng)2、forward 和redirect的区?br /> (tng)3、JSP的常用指?br />三、servlet
1、什么情况下调用doGet()和doPost()Q?br />2、servlet的init()Ҏ(gu)和service()Ҏ(gu)的区?br />3、servlet的生命周?br />4、如何现实servlet的单U程模式
5、servlet的配|?br />6、四U会(x)话跟t技?br />四、EJB
1、EJB容器提供的服?br />主要提供声明周期理、代码生、持l性管理、安全、事务管理、锁和ƈ发行理{服务?br /> (tng)2、EJB的角色和三个对象
EJB角色主要包括Bean开发?应用l装?部v?pȝ理?EJB容器提供?EJB服务器提供?br />三个对象是RemoteQLocalQ接口、HomeQLocalHomeQ接口,Beanc?br />2、EJB的几U类?br />?x)话QSessionQBean Q实体(EntityQBean 消息驱动的(Message DrivenQBean
?x)话Bean又可分ؓ(f)有状态(StatefulQ和无状态(StatelessQ两U?br />实体Bean可分为Bean理的持l性(BMPQ和容器理的持l性(CMPQ两U?br /> (tng)3、bean 实例的生命周?br />对于Stateless Session Bean、Entity Bean、Message Driven Bean一般存在缓冲池理Q而对于Entity Bean和Statefull Session Bean存在Cache理Q通常包含创徏实例Q设|上下文、创建EJB ObjectQcreateQ、业务方法调用、remove{过E,对于存在~冲池管理的BeanQ在create之后实例q不从内存清除,而是采用~冲池调度机制不断重用实例,而对于存在Cache理的Bean则通过ȀzdLzL制保持Bean的状态ƈ限制内存中实例数量?br />4、激zL?br />以Statefull Session Bean ZQ其Cache大小军_?jin)内存中可以同时存在的Bean实例的数量,Ҏ(gu)MRU或NRU法Q实例在ȀzdLzȝ态之间迁U,ȀzL制是当客L(fng)调用某个EJB实例业务Ҏ(gu)Ӟ如果对应EJB Object发现自己没有l定对应的Bean实例则从其去ȀzBean存储中(通过序列化机制存储实例)(j)回复Q激z)(j)此实例。状态变q前?x)调用对应的ejbActive和ejbPassivateҎ(gu)?br /> (tng)5、remote接口和home接口主要作用
remote接口定义?jin)业务方法,用于EJB客户端调用业务方?br />;home接口是EJB工厂用于创徏和移除查找EJB实例
6、客服端调用EJB对象的几个基本步?br />一?讄JNDI服务工厂以及(qing)JNDI服务地址pȝ属?br />二?查找Home接口
三?从Home接口调用CreateҎ(gu)创徏Remote接口
四?通过Remote接口调用其业务方?br />五、数据库
1、存储过E的~写
2、基本的SQL语句
六、weblogic
1?如何lweblogic指定大小的内?
在启动Weblogic的脚本中Q位于所在Domian对应服务器目录下的startServerNameQ,增加set MEM_ARGS=-Xms32m -Xmx200mQ可以调整最内存ؓ(f)32MQ最?00M
2?如何讑֮的weblogic的热启动模式(开发模?与品发布模?
可以在管理控制台中修改对应服务器的启动模式ؓ(f)开发或产品模式之一。或者修Ҏ(gu)务的启动文g或者commenv文gQ增加set PRODUCTION_MODE=true?br />3?如何启动时不需输入用户名与密码?
修改服务启动文gQ增?WLS_USER和W(xu)LS_PWV也可以在boot.properties文g中增加加密过的用户名和密?
4?在weblogic理制台中对一个应用域(或者说是一个网?Domain)q行jms?qing)ejb或连接池{相关信息进行配|后,实际保存在什么文件中?
保存在此Domain的config.xml文g中,它是服务器的核心(j)配置文g?br />5?说说weblogic中一个Domain的缺省目录结?比如要将一个简单的helloWorld.jsp攑օ何目录下,然的在浏览器上就可打入http://L:端口?/helloword.jsp可以看到运行结果了(jin)? 又比如这其中用到?jin)一个自己写的javaBean该如何办?
Domain目录\服务器目录\applicationsQ将应用目录攑֜此目录下可以作为应用访问,如果是Web应用Q应用目录需要满Web应用目录要求Qjsp文g可以直接攑֜应用目录中,Javabean需要放在应用目录的WEB-INF目录的classes目录中,讄服务器的~省应用可以实现在览器上无需输入应用名?br />6?如何查看在weblogic中已l发布的EJB?
可以使用理控制収ͼ在它的Deployment中可以查看所有已发布的EJB
7?如何在weblogic中进行ssl配置与客L(fng)的认证配|或说说j2ee(标准)q行ssl的配|?br />~省安装中用DemoIdentity.jks和DemoTrust.jks KeyStore实现SSLQ需要配|服务器使用Enable SSLQ配|其端口Q在产品模式下需要从CA获取U有密钥和数字证书,创徏identity和trust keystoreQ装载获得的密钥和数字证书。可以配|此SSLq接是单向还是双向的?br /> (tng)8、在weblogic中发布ejb需涉及(qing)到哪些配|文?br />不同cd的EJB涉及(qing)的配|文件不同,都涉?qing)到的配|文件包括ejb-jar.xml,weblogic-ejb-jar.xmlCMP实体Bean一般还需要weblogic-cmp-rdbms-jar.xml
9、EJB需直接实现它的业务接口或Home接口?L(fng)q理?
q程接口和Home接口不需要直接实玎ͼ他们的实C码是由服务器产生的,E序q行中对应实现类?x)作为对应接口类型的实例被用?br />10、说说在weblogic中开发消息Bean时的persistent与non-persisten的差?br />persistent方式的MDB可以保证消息传递的可靠?也就是如果EJB容器出现问题而JMS服务器依然会(x)消息在此MDB可用的时候发送过来,而nonQpersistent方式的消息将被丢弃?br />11、说说你所熟?zhn)或听说过的j2ee中的几种常用模式??qing)对设计模式的一些看?br />Session Facade PatternQ用SessionBean讉KEntityBean
Message Facade PatternQ实现异步调?br />EJB Command PatternQ用Command JavaBeans取代SessionBeanQ实现轻量讉K
Data Transfer Object FactoryQ通过DTO Factory化EntityBean数据提供Ҏ(gu)?br />Generic Attribute AccessQ通过AttibuteAccess接口化EntityBean数据提供Ҏ(gu)?br />Business InterfaceQ通过q程Q本圎ͼ(j)接口和Beancd现相同接口规范业务逻辑一致?br />QJQ架构的设计好坏直接媄(jing)响系l的性能、可扩展性、可l护性、组件可重用性及(qing)开发效率。项目越复杂Q项目队伍越庞大则越能体现良好设计的重要?img src ="http://www.tkk7.com/William/aggbug/59601.html" width = "1" height = "1" />

William 2006-07-22 23:33 发表评论
]]>
Java面试?/title><link>http://www.tkk7.com/William/archive/2006/07/22/59599.html</link><dc:creator>William</dc:creator><author>William</author><pubDate>Sat, 22 Jul 2006 15:28:00 GMT</pubDate><guid>http://www.tkk7.com/William/archive/2006/07/22/59599.html</guid><wfw:comment>http://www.tkk7.com/William/comments/59599.html</wfw:comment><comments>http://www.tkk7.com/William/archive/2006/07/22/59599.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/William/comments/commentRss/59599.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/William/services/trackbacks/59599.html</trackback:ping><description><![CDATA[1. (tng)<a target="_blank">Java</a>中的异常处理机制的简单原理和应用。?<br /><br />当JavaE序q反?jin)Java的语义规则时QJava虚拟机就?x)将发生的错误表CZؓ(f)一个异常。违反语义规则包?U情c(din)一U是Javacd内置的语义检查。例如数l下标越??x)引发IndexOutOfBoundsException;讉Knull的对象时?x)引发NullPointerException。另一U情况就是Java允许E序员扩展这U语义检查,E序员可以创q异常Qƈ自由选择在何时用throw关键字引发异常。所有的异常都是java.lang.Thowable的子cR?<br /><br />2. (tng)Java的接口和C++的虚cȝ相同和不同处。?<br /><br />׃Java不支持多l承Q而有可能某个cL对象要用分别在几个cL对象里面的方法或属性,现有的单l承机制׃能满求。与l承相比Q接口有更高的灵zL,因ؓ(f)接口中没有Q何实C码。当一个类实现?jin)接口以后,该类要实现接口里面所有的Ҏ(gu)和属性,q且接口里面的属性在默认状态下面都是public (tng)static,所有方法默认情况下是public.一个类可以实现多个接口。?<br /><br />3. (tng)垃圾回收的优点和原理。ƈ考虑2U回收机制。?<br /><br />Java语言中一个显著的特点是引入?jin)垃圑֛收机Ӟ使c++E序员最头疼的内存管理的问题q刃而解Q它使得JavaE序员在~写E序的时候不再需要考虑内存理。由于有个垃圑֛收机ӞJava中的对象不再有“作用域”的概念Q只有对象的引用才有“作用域”。垃圑֛收可以有效的防止内存泄露Q有效的使用可以使用的内存。垃圑֛收器通常是作Z个单独的低别的U程q行Q不可预知的情况下对内存堆中已经M的或者长旉没有使用的对象进行清除和回收Q程序员不能实时的调用垃圑֛收器Ҏ(gu)个对象或所有对象进行垃圑֛收。回收机制有分代复制垃圾回收和标记垃圑֛Ӟ增量垃圾回收。?<br /><br />4.U程同步的方法。?<br /><br />wait():使一个线E处于等待状态,q且释放所持有的对象的lock。?<br /><br />sleep():使一个正在运行的U程处于睡眠状态,是一个静(rn)态方法,调用此方法要捕捉InterruptedException异常。?<br /><br />notify():唤醒一个处于等待状态的U程Q注意的是在调用此方法的时候,q不能确切地唤醒某一个等待状态的U程Q而是由JVM定唤醒哪个U程Q而且不是按优先。?<br /><br />Allnotity():唤醒所有处入等待状态的U程Q注意ƈ不是l所有唤醒线E一个对象的锁,而是让它们竞争。?<br /><br />5. (tng)Error与Exception有什么区别? (tng) <br /><br />Error表示pȝU的错误和程序不必处理的异常Q?<br /><br />Exception表示需要捕捉或者需要程序进行处理的异常。?<br />6. (tng)在java中一个类被声明ؓ(f)finalcdQ表CZ(jin)什么意思? (tng) <br /><br /> (tng) (tng) (tng)表示该类不能被承,是顶U类?<br />7 (tng)heap和stack有什么区别。?<br /> (tng) (tng) (tng)栈是一U线形集合,其添加和删除元素的操作应在同一D完成。栈按照后进先出的方式进行处理。堆是栈的一个组成元素。?<br />8谈谈final, (tng)finally, (tng)finalize的区别。?<br />  final—修饰符Q关键字Q如果一个类被声明ؓ(f)finalQ意味着它不能再z出新的子c,不能作ؓ(f)父类被ѝ因此一个类不能既被声明为?tng)abstract的,又被声明为final的。将变量或方法声明ؓ(f)finalQ可以保证它们在使用中不被改变。被声明为final的变量必d声明时给定初|而在以后的引用中只能dQ不可修攏V被声明为final的方法也同样只能使用Q不能重载。?<br />  finally—异常处理时提供 (tng)finally (tng)块来执行M清除操作。如果抛Z个异常,那么相匹配的 (tng)catch (tng)子句׃(x)执行Q然后控制就?x)进入 (tng)finally (tng)块(如果有的话)(j)。?<br />  finalize—方法名?a target="_blank">Java</a> (tng)技术允怋用?tng)finalize() (tng)Ҏ(gu)在垃圾收集器对象从内存中清除出M前做必要的清理工作。这个方法是由垃圾收集器在确定这个对象没有被引用时对q个对象调用的。它是在 (tng)Object (tng)cM定义的,因此所有的c都l承?jin)它。子c覆盖?tng)finalize() (tng)Ҏ(gu)以整理系l资源或者执行其他清理工作。finalize() (tng)Ҏ(gu)是在垃圾攉器删除对象之前对q个对象调用的?<br />9 (tng) (tng)Anonymous (tng)I(yng)nner (tng)Class (tng)(匿名内部c? (tng)是否可以extends(l承)其它c,是否可以implements(实现)interface(接口)? (tng) <br />  匿名的内部类是没有名字的内部cR不能extends(l承) (tng)其它c,但一个内部类可以作ؓ(f)一个接口,由另一个内部类实现?<br />10 (tng) (tng)Static (tng)Nested (tng)Class (tng)和?tng)I(yng)nner (tng)Class的不?<br />Nested (tng)Class (tng)Q一般是C++的说法)(j)QInner (tng)Class (tng)(一般是JAVA的说?。Java内部cMC++嵌套cL大的不同在于是否有指向外部的引用上?<br />  注:(x) (tng)?rn)态内部类QInner (tng)ClassQ意味着1创徏一个static内部cȝ对象Q不需要一个外部类对象Q?不能从一个static内部cȝ一个对象访问一个外部类对象 (tng) <p></p><p>11 (tng) (tng) (tng)&?amp;&的区别。?<br />  &是位q算W?amp;&是布?yu)(dng)逻辑q算W。?<br />12 (tng) (tng)HashMap和Hashtable的区别。?<br />  都属于Map接口的类Q实C(jin)惟一键映到特定的g。?<br />  HashMap (tng)cL有分cL者排序。它允许一个?tng)null (tng)键和多个 (tng)null (tng)倹{?<br /></p><p></p><p>  Hashtable (tng)cM于?tng)HashMapQ但是不允许 (tng)null (tng)键和 (tng)null (tng)倹{它也比 (tng)HashMap (tng)慢,因ؓ(f)它是同步的?<br />13 (tng)Collection (tng)和?tng)Collections的区别。?<br /> (tng) (tng) (tng) (tng)Collection是个java.util下的接口Q它是各U集合结构的父接口?<br />  Collections是个java.util下的c,它包含有各种有关集合操作的静(rn)态方法。?<br />14 (tng)什么时候用assert。?<br />  断言是一个包含布?yu)(dng)表辑ּ的语句,在执行这个语句时假定该表辑ּ为 (tng)true。?<br />如果表达式计ؓ(f) (tng)falseQ那么系l会(x)报告一个?tng)Assertionerror。它用于调试目的Q?<br />assert(a (tng)> (tng)0); (tng)// (tng)throws (tng)an (tng)Assertionerror (tng)if (tng)a (tng)<= (tng)0 (tng) <br />断言可以有两UŞ式:(x) (tng) <br />assert (tng)Expression1 (tng); (tng) <br />assert (tng)Expression1 (tng): (tng)Expression2 (tng); (tng) <br />  Expression1 (tng)应该L产生一个布?yu)(dng)倹{?<br />  Expression2 (tng)可以是得Z个值的L表达式。这个值用于生成显C更多调试?<br />信息的?tng)String (tng)消息。?<br />  断言在默认情况下是禁用的。要在编译时启用断言Q需要用?tng)source (tng)1.4 (tng)标记Q?<br />  javac (tng)-source (tng)1.4 (tng)Test.java (tng) <br />  要在q行时启用断aQ可使用 (tng)-enableassertions (tng)或者?ea (tng)标记。?<br />  要在q行旉择用断言Q可使用 (tng)-da (tng)或者?disableassertions (tng)标记。?<br />  要系l类中启用断aQ可使用 (tng)-esa (tng)或者?dsa (tng)标记。还可以在包的基上启用或者禁用断a。?<br />  可以在预计正常情况下不会(x)到达的Q何位|上攄断言。断a可以用于验证传递给U有Ҏ(gu)的参数。不q,断言不应该用于验证传递给公有Ҏ(gu)的参敎ͼ因ؓ(f)不管是否启用?jin)断aQ公有方法都必须(g)查其参数。不q,既可以在公有Ҏ(gu)中,也可以在非公有方法中利用断言试后置条g。另外,断言不应该以M方式改变E序的状态。?<br />15 (tng)GC是什? (tng)Z么要有GC? (tng)(基础)。?<br />  GC是垃圾收集器?a target="_blank">Java</a> (tng)E序员不用担?j)内存管理,因?f)垃圾攉器会(x)自动q行理。要h垃圾攉Q可以调用下面的Ҏ(gu)之一Q?System.gc() (tng) <br />Runtime.getRuntime().gc() (tng) <br />16 (tng)String (tng)s (tng)= (tng)new (tng)String("xyz");创徏?jin)几个String (tng)Object? (tng) <br />  两个对象Q一个是“xyz?一个是指向“xyz”的引用对象s。?<br />17 (tng)Math.round(11.5){於多少? (tng)Math.round(-11.5){於多少? (tng) <br />  Math.round(11.5)q回QlongQ?2QMath.round(-11.5)q回QlongQ?11; (tng) <br />18 (tng)short (tng)s1 (tng)= (tng)1; (tng)s1 (tng)= (tng)s1 (tng)+ (tng)1;有什么错? (tng)short (tng)s1 (tng)= (tng)1; (tng)s1 (tng)+= (tng)1;有什么错? (tng) <br />  short (tng)s1 (tng)= (tng)1; (tng)s1 (tng)= (tng)s1 (tng)+ (tng)1;有错Qs1是short型,s1+1是int?不能昑ּ转化为short型。可修改为s1 (tng)=(short)(s1 (tng)+ (tng)1) (tng)。short (tng)s1 (tng)= (tng)1; (tng)s1 (tng)+= (tng)1正确。?<br />19 (tng)sleep() (tng)和?tng)wait() (tng)有什么区? (tng)搞线E的最?<br />  sleep()Ҏ(gu)是ɾU程停止一D|间的Ҏ(gu)。在sleep (tng)旉间隔期满后,U程不一定立x复执行。这是因为在那个时刻Q其它线E可能正在运行而且没有被调度ؓ(f)攑ּ执行Q除?a)“醒来”的U程h更高的优先 (tng)(b)正在q行的线E因为其它原因而阻塞。?<br />  wait()是线E交互时Q如果线E对一个同步对象x (tng)发出一个wait()调用Q该U程?x)暂停执行,被调对象q入{待状态,直到被唤醒或{待旉到。?<br />20 (tng)<a target="_blank">Java</a>有没有goto? (tng) <br />  Goto—java中的保留字,现在没有在java中用。?<br />21 (tng)数组有没有length()q个Ҏ(gu)? (tng)String有没有length()q个Ҏ(gu)Q?<br />  数组没有length()q个Ҏ(gu)Q有length的属性。?<br />  String有有length()q个Ҏ(gu)。?</p><p></p><p>22 (tng)Overload和Override的区别。Overloaded的方法是否可以改变返回值的cd? (tng) <br />  Ҏ(gu)的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父cM子类之间多态性的一U表玎ͼ重蝲Overloading是一个类中多态性的一U表现。如果在子类中定义某Ҏ(gu)与其父类有相同的名称和参敎ͼ我们说该Ҏ(gu)被重写?Overriding)。子cȝ对象使用q个Ҏ(gu)Ӟ调用子cM的定义,对它而言Q父cM的定义如同被“屏蔽”了(jin)。如果在一个类中定义了(jin)多个同名的方法,它们或有不同的参C数或有不同的参数cdQ则UCؓ(f)Ҏ(gu)的重?Overloading)。?<br />Overloaded的方法是可以改变q回值的cd。?br />23 (tng)Set里的元素是不能重复的Q那么用什么方法来区分重复与否? (tng)是用==q是e (tng) <br />quals()? (tng)它们有何区别? (tng) <br />  Set里的元素是不能重复的Q那么用iterator()Ҏ(gu)来区分重复与否。equals( (tng) <br />)是判M个Set是否相等。?tng)equals()?=Ҏ(gu)军_引用值是否指向同一对象equals()在类中被覆盖Qؓ(f)的是当两个分ȝ对象的内容和cd盔R的话Q返回真倹{?<br /><br />24最常见到的runtime (tng)exception。?<br />ArithmeticException, (tng)ArrayStoreException, (tng)BufferOverflowException, (tng)BufferUnderflowException, (tng)CannotRedoException, (tng)CannotUndoException, (tng)ClassCastException, (tng)CMMException, (tng)ConcurrentModificationException, (tng)DOMException,EmptyStackException, (tng)I(yng)llegalArgumentException, (tng)I(yng)llegalMonitorStateException, (tng)I(yng)llegalPathStateException, (tng)I(yng)llegalStateException,ImagingOpException, (tng)I(yng)ndexOutOfBoundsException, (tng)MissingResourceException, (tng)NegativeArraySizeException, (tng)NoSuchElementException, (tng)NullPointerException, (tng)ProfileDataException, (tng)ProviderException, (tng)RasterFORMatException, (tng)Secur (tng) <br />ityException, (tng)SystemException, (tng)UndeclaredThrowableException, (tng)UnmodifiableSetException, (tng)UnsupportedOperationException (tng) <br />25 (tng)error和exception有什么区? (tng) <br />  error (tng)表示恢复不是不可能但很困隄情况下的一U严重问题。比如说内存溢出。不可能指望E序能处理这L(fng)情况。?<br />  exception (tng)表示一U设计或实现问题。也是_(d)它表C如果程序运行正常,从不?x)发生的情况。?<br />26 (tng)List, (tng)Set, (tng)Map是否l承自Collection接口? (tng) <br /> (tng) (tng) (tng) (tng) (tng)ListQSet是?<br /> (tng) (tng) (tng) (tng) (tng)Map不是 (tng) <br />27 (tng)abstract (tng)class和interface有什么区? (tng) <br />  声明Ҏ(gu)的存在而不d现它的类被叫做抽象类Qabstract (tng)classQ,它用于要创徏一个体现某些基本行为的c,qؓ(f)该类声明Ҏ(gu)Q但不能在该cM实现该类的情c(din)不能创建abstract (tng)cȝ实例。然而可以创Z个变量,其类型是一个抽象类Qƈ让它指向具体子类的一个实例。不能有抽象构造函数或抽象?rn)态方法。Abstract (tng)cȝ子类为它们父cM的所有抽象方法提供实玎ͼ否则它们也是抽象cMؓ(f)。取而代之,在子cM实现该方法。知道其行ؓ(f)的其它类可以在类中实现这些方法。?<br />接口QinterfaceQ是抽象cȝ变体。在接口中,所有方法都是抽象的。多l承性可通过实现q样的接口而获得。接口中的所有方法都是抽象的Q没有一个有E序体。接口只可以定义static (tng)final成员变量。接口的实现与子cȝ|除了(jin)该实现类不能从接口定义中l承行ؓ(f)。当cd现特D接口时Q它定义Q即程序体l予Q所有这U接口的Ҏ(gu)。然后,它可以在实现?jin)该接口的类的Q何对象上调用接口的方法。由于有抽象c,它允怋用接口名作ؓ(f)引用变量的类型。通常的动态联~将生效。引用可以{换到接口cd或从接口cd转换Qinstanceof (tng)q算W可以用来决定某对象的类是否实现?jin)接口。?<br /><br />28 (tng)abstract的method是否可同时是static,是否可同时是nativeQ是否可同时是synchronized? (tng) <br />  都不q?<br />29 (tng)接口是否可承接? (tng)抽象cL否可实现(implements)接口? (tng)抽象cL否可l承实体c?concrete (tng)class)? (tng) <br />  接口可以l承接口。抽象类可以实现(implements)接口Q抽象类可承实体类Q但前提是实体类必须有明的构造函数。?<br />30 (tng)启动一个线E是用run()q是start()? (tng) <br />  启动一个线E是调用start()Ҏ(gu)QɾU程所代表的虚拟处理机处于可运行状态,q意味着它可以由JVM调度q执行。这q不意味着U程׃(x)立即q行。run()Ҏ(gu)可以产生必须退出的标志来停止一个线E。?<br />31 (tng)构造器Constructor是否可被override? (tng) <br />  构造器Constructor不能被承,因此不能重写OverridingQ但可以被重载Overloading。?<br />32 (tng)是否可以l承Stringc? (tng) <br />  StringcLfinalcL不可以ѝ?<br />33 (tng)当一个线E进入一个对象的一个synchronizedҎ(gu)后,其它U程是否可进入此对象的其它方? (tng) <br />  不能Q一个对象的一个synchronizedҎ(gu)只能׃个线E访问。?<br />33 (tng) (tng)try (tng){}里有一个return语句Q那么紧跟在q个try后的finally (tng){}里的code?x)不?tng) <br />?x)被执行Q什么时候被执行Q在return前还是后? (tng) <br />  ?x)执行,在return前执行。?<br />34 (tng)~程? (tng)用最有效率的Ҏ(gu)出2乘以8{於? (tng) <br />  2 (tng)<< (tng)3 (tng) <br />35 (tng)两个对象值相?x.equals(y) (tng)== (tng)true)Q但却可有不同的hash (tng)codeQ这句话对不? (tng) <br />  不对Q有相同的hash (tng)code。?<br />36 (tng) (tng)当一个对象被当作参数传递到一个方法后Q此Ҏ(gu)可改变这个对象的属性,q?tng)可q回变化后的l果Q那么这里到底是g递还是引用传? (tng) <br />  是g递?a target="_blank">Java</a> (tng)~程语言只由g递参数。当一个对象实例作Z个参数被传递到Ҏ(gu)中时Q参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变Q但对象的引用是永远不会(x)改变的。?<br />37 (tng) (tng)swtich是否能作用在byte上,是否能作用在long上,是否能作用在String? (tng) <br />  switchQexpr1Q中Qexpr1是一个整数表辑ּ。因此传递给 (tng)switch (tng)和?tng)case (tng)语句的参数应该是 (tng)int、?tng)short、?tng)char (tng)或者?tng)byte。long,string (tng)都不能作用于swtich。?<br />38 Hashtable和HashMap (tng) <br />  Hashtablel承自Dictionaryc,而HashMap是Java1.2引进的Map (tng)interface的一个实玊W?<br />  HashMap允许null作ؓ(f)一个entry的key或者valueQ而Hashtable不允?<br />q有是QHashMap把Hashtable的containsҎ(gu)L?jin),?gu)containsvalue和containsKey。因为containsҎ(gu)Ҏ(gu)让h引v误解?<br />  最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是Q在 <br />多个U程讉KHashtableӞ不需要自׃ؓ(f)它的Ҏ(gu)实现同步Q而HashMap必Mؓ(f)之提供外同步。?<br />Hashtable和HashMap采用的hash/rehash法都大概一P所以性能不会(x)有很大的差异?</p><img src ="http://www.tkk7.com/William/aggbug/59599.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/William/" target="_blank">William</a> 2006-07-22 23:28 <a href="http://www.tkk7.com/William/archive/2006/07/22/59599.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>JAVA相关基础知识http://www.tkk7.com/William/archive/2006/07/22/59597.htmlWilliamWilliamSat, 22 Jul 2006 15:21:00 GMThttp://www.tkk7.com/William/archive/2006/07/22/59597.htmlhttp://www.tkk7.com/William/comments/59597.htmlhttp://www.tkk7.com/William/archive/2006/07/22/59597.html#Feedback0http://www.tkk7.com/William/comments/commentRss/59597.htmlhttp://www.tkk7.com/William/services/trackbacks/59597.html阅读全文

William 2006-07-22 23:21 发表评论
]]>
Java思想http://www.tkk7.com/William/archive/2006/07/22/59592.htmlWilliamWilliamSat, 22 Jul 2006 14:53:00 GMThttp://www.tkk7.com/William/archive/2006/07/22/59592.htmlhttp://www.tkk7.com/William/comments/59592.htmlhttp://www.tkk7.com/William/archive/2006/07/22/59592.html#Feedback13http://www.tkk7.com/William/comments/commentRss/59592.htmlhttp://www.tkk7.com/William/services/trackbacks/59592.html其实学习(fn)Java对于我来说也是很H然Q由于来中兴通讯实习(fn)Q工作用的语a是JavaQ所以我开始学?fn)Java?jin),q好Java的语法跟CQ+语言很像Q所以入门Java个h感觉不是很难Q而且开始看?jin)几乎有几万行的Java代码Q所以对于学?fn)Java的环境还是很不错的环境吧Q实?fn)生的工作不是很J忙Q自由支配的旉q是比较多的Q我基本上把所有的自由旉都放到的学习(fn)Java上,刚开始对Java有一个误解,以后跟学CQ+语言一P学会(x)语言Q再用好一个开发工P基本上也可以处理问题了(jin)Q可是隐藏在Java后面的J2EEQ现在叫Java EE?jin)吧Q确实让我大开的眼界?br />刚开始学?fn)Java可以说是热情高涨的,应ؓ(f)相对于CQ+语言来说QJava的易用性以?qing)特别好的面向对象思想的实现让我觉得,是Java?jin)。可是接触的多了(jin)Q发现的也就多了(jin)Q问题也多?jin),从来没有一下子接触q那么多的概念,J2EE学习(fn)让我一下子感觉Java的庞大和复杂Q好像一下子有点找不到北?jin),我该先学什么呢Q学什么好呢,{等{等。。。。好像开始有炚w闷了(jin)Q那个ؕ啊,有时候学着学着学岔了(jin)Q呵c(din)?br />׃感觉自己现在像进入了(jin)一个迷宫,感觉怎么J2EE东西怎么那么多啊Q一个东西还没有学会(x)呢,另外一个新技术就又出来了(jin)Q你说这个什么事啊,q不明摆着把我们这些JavaE序员往死里整呢吗,一度都有放弃Java的念_(d)不过׃工作的关pM(jin)Q不学不行,所以就l箋?jin)坚持,也就是因个坚持,让我对Java有了(jin)新的认识Q对自己的学?fn)方法也有?jin)新的认识?br />前一阵子׃感觉自己的学?fn)特别ؕQ东一榔头西一的Q不着辚wQ压根就学不到真正的东西Q于是就l自己定?jin)个学?fn)计划Q从现在开始的W一个月研究HibernateQ然后研IStrutsQ然后研IspringQ最后ȝ一下自q学习(fn)成果Q用自己学的东西做一个基于StrutsQHibernateQspring的论坛出来,q自己的学?fn)成果?jin)吧,然而不能说的计划没有用吧,虽然没有真正的坚持我的计划,不过是应ؓ(f)q个计划让我对Java的学?fn)有了(jin)新的看法。我们知道J2EE的企业架构的WebE序开发主要是q样发展q来的:(x)首先是ZJSPQJavaBeanQ然后有?jin)StrutsQSpringQ对于数据库的访问从刚开始的JDBC发展到现在ORMQ确实让我们q些E序员的应用开发省?jin)不麻烦(ch),不过有一个问题,q些架构的出现是Z(jin)什么呢Q其实很单,是Z(jin)减轻我们的工作量Q让我们更关注于应用。可是,我不知道别h是怎么看的Q至对于我来说Q对于我一个初学Java不到半年的h来说Q早早知道这些架构看来是没有什么好处的Q学?fn)的急功q利让我q逐的永远都是q些架构Q这些ؓ(f)?jin)减d作量的架构,而对于Java基础的学?fn)则撂倒了(jin)一边,有点可?zhn)Q基q没有牢固的情况下就去追求那些时髦的架构Q再来看看我定的学习(fn)计划Q好像有点可W了(jin)Q甚xq稚的?br />现在我觉得有必要端正一下我的思想?jin),重新制定一个学?fn)计划,毕?0月分C(jin)我还要凭着q玩意找工作呢。其实现在想惌׃的确犯了(jin)E序员最严重的错误:(x)不研I最基本的东西,而去q逐那些花哨的技术,其实那些东西也都是这些最基本的东西开发出来的。所以从现在开始重新回到Java语言本n上来Q好好研IJava语言的一些技巧,强烈地提高一下自qJava基本功,免得回头跟别人热烈地讨论spring的时候说到语a本n的IO操作一脸茫然了(jin)?br />说实话,我现在也想通了(jin)Q就是说的俗一点,扑ַ作的时候面试官的大部分问题应该是关于Java基本功的Q面试题也基本上是关于Java语言以及(qing)数据l构{方面的Q对于HibernateQspringQ我觉得他肯定不?x)问你某个配|文件怎么写吧Q问得也是思想Q比如ORM是什么概念,核心(j)内容是什么等{,所以对于这些框架来_(d)我觉得会(x)用就_?jin),再说Q基本概忉|握以后,学习(fn)q些架构才能真正学到_֍Q学到这些架构的思想Q只有这P我觉得才有可能真正成Z名架构师吧,呵呵Q理惻I奋斗ing?br />
从基本学期,摆脱躁Q摆脱开始?img src ="http://www.tkk7.com/William/aggbug/59592.html" width = "1" height = "1" />

William 2006-07-22 22:53 发表评论
]]>
谈Hibernate的flush机制(ZT)http://www.tkk7.com/William/archive/2006/07/02/56206.htmlWilliamWilliamSun, 02 Jul 2006 14:09:00 GMThttp://www.tkk7.com/William/archive/2006/07/02/56206.htmlhttp://www.tkk7.com/William/comments/56206.htmlhttp://www.tkk7.com/William/archive/2006/07/02/56206.html#Feedback0http://www.tkk7.com/William/comments/commentRss/56206.htmlhttp://www.tkk7.com/William/services/trackbacks/56206.html (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng)q是在一ơ事务提交时遇到的异常?br /> (tng) (tng) (tng) (tng) (tng) (tng) (tng)an (tng)assertion (tng)failure (tng)occured (tng)(this (tng)may (tng)indicate (tng)a (tng)bug (tng)in (tng)Hibernate, (tng)but (tng)is (tng)more (tng)likely (tng)due (tng)to (tng)unsafe (tng)use (tng)of (tng)the (tng)session)
net.sf.hibernate.AssertionFailure: (tng)possible (tng)nonthreadsafe (tng)access (tng)to (tng)session
注:(x)非possible (tng)non-threadsafe (tng)access (tng)to (tng)the (tng)session (tng)Q那是另外的错误Q类g不一P(j)
 (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng)q个异常应该很多的朋友都遇到q,原因可能各不相同。但所有的异常都应该是在flush或者事务提交的q程中发生的。这一般由我们在事务开始至事务提交的过E中q行?jin)不正确的操作导_(d)也会(x)在多U程同时操作一个Session时发生,q里我们仅仅讨论单线E的情况Q多U程除了(jin)U程同步外基本与此相同?br /> (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng)至于具体是什么样的错误操作那Q我l大家看一个例子(假设Hibernate配置正确Qؓ(f)保持代码z,不引入包?qing)处理Q何异常)(j)
 (tng) (tng)

SessionFactory (tng)sf (tng)= (tng)new (tng)Configuration().configure().buildSessionFactory() (tng);
Session (tng)s (tng)= (tng)sf.openSession();
Cat (tng)cat (tng)= (tng)new (tng)Cat();

Transaction (tng)tran (tng)= (tng)s.beginTransaction(); (tng)(1)
s.save(cat); (tng)(2)Q此处同样可以ؓ(f)update (tng)deleteQ?br />s.evict(cat); (tng)(3)
tran.commit(); (tng)(4)
s.close();(5)


 (tng) (tng) (tng) (tng) (tng) (tng) (tng)q就是引h异常的典型错误。我当时遇C(jin)q个异常Q检查代码时Ҏ(gu)没感觉到q段代码Z(jin)问题Q想当然的认为在Session上开始一个事务,通过Session对象存入数据库Q再这个对象从Session上拆,提交事务Q这是一个很正常的流E。如果这里正常的话,那问题一定在别处?br /> (tng)
 (tng) (tng) (tng) (tng) (tng) (tng) (tng) (tng)问题恰恰在q里Q我的想法也许没有错Q但是一个错误的论据所引出的观Ҏ(gu)q都不可能是正确的。因为我一直以为直接在Ҏ(gu)据库q行操作Q忘C(jin)在我与数据库之间隔了(jin)一个HibernateQHibernate在ؓ(f)我们提供持久化服务的同时Q也改变?jin)我们对数据库的操作方式Q这U方式与我们直接的数据库操作有着很多的不同,正因为我们对q种方式没有一个大致的?jin)解造成?jin)我们的应用q未得到预先设想的结果?br /> (tng)
那Hibernate的持久化机制到底有什么不同那Q简单的_(d)Hibernate在数据库层之上实C(jin)一个缓存区Q当应用save或者update一个对象时QHibernateq未这个对象实际的写入数据库中Q而仅仅是在缓存中Ҏ(gu)应用的行为做?jin)登讎ͼ在真正需要将~存中的数据flush入数据库时才执行先前登记的所有行为?br /> (tng)
在实际执行的q程中,每个Session是通过几个映射和集合来l护所有与该Session建立?jin)关联的对象以?qing)应用对这些对象所q行的操作的Q与我们q次讨论有关的有entityEntriesQ与Session相关联的对象的映)(j)、insertionsQ所有的插入操作集合Q、deletionsQ删除操作集合)(j)、updatesQ更新操作集合)(j)。下面我开始解释在最开始的例子中,Hibernate到底是怎样q作的?br />(1)生成一个事务的对象Qƈ标记当前的Session处于事务状态(注:(x)此时q未启动数据库事务Q?br />(2)应用使用s.save保存cat对象Q这个时候Sessioncatq个对象攑օentityEntriesQ用来标记cat已经和当前的?x)话建立了(jin)关联,׃应用对cat做了(jin)保存的操作,Sessionq要在insertions中登记应用的q个插入行ؓ(f)Q行为包括:(x)对象引用、对象id、Session、持久化处理c)(j)?br />(3)s.evict(cat)cat对象从s?x)话中拆,q时s?x)从entityEntries中将catq个对象Ud?br />(4)事务提交Q需要将所有缓存flush入数据库QSession启动一个事务,q按照insert,update,…?delete的顺序提交所有之前登记的操作Q注意:(x)所有insert执行完毕后才?x)执行updateQ这里的Ҏ(gu)处理也可能会(x)你的程序搞得一团糟Q如需要控制操作的执行序Q要善于使用flushQ,现在cat不在entityEntries中,但在执行insert的行为时只需要访问insertionsp够了(jin)Q所以此时不?x)有M的异常。异常出现在插入后通知Session该对象已l插入完毕这个步骤上Q这个步骤中需要将entityEntries中cat的existsInDatabase标志|ؓ(f)trueQ由于catq不存在于entityEntries中,此时Hibernatep为insertions和entityEntries可能因ؓ(f)U程安全的问题生了(jin)不同步(也不知道Hibernate的开发者是否考虑C子中的处理方式,如果没有的话Q这也许是一个bug吧)(j)Q于是一个net.sf.hibernate.AssertionFailurep抛出Q程序终止?br /> (tng)
我想现在大家应该明白例子中的E序到底哪里有问题了(jin)吧,我们的错误的认ؓ(f)s.save?x)立即的执行Q而将cat对象q早的与Session拆离Q造成?jin)Session的insertions和entityEntries中内容的不同步。所以我们在做此cL作时一定要清楚Hibernate什么时候会(x)数据flush入数据库Q在未flush之前不要已q行操作的对象从Session上拆R?br /> (tng)
对于q个错误的解x法是Q我们可以在(2)?3)之间插入一个s.flush()强制Session缓存中的数据flush入数据库Q此时Hibernate?x)提前启动事务,?2)中的save登记的insert语句登记在数据库事务中,q将所有操作集合清I)(j)Q这样在(4)事务提交时insertions集合已l是I的?jin),即我们拆离了(jin)cat也不?x)有M的异怺(jin)?br />前面单的介绍?jin)一下Hibernate的flush机制和对我们E序可能带来的媄(jing)响以?qing)相应的解决?gu)QHibernate的缓存机制还?x)在其他的方面给我们的程序带来一些意想不到的影响。看下面的例子:(x)
 (tng) (tng)

Qname为cat表的主键Q?br />Cat (tng)cat (tng)= (tng)new (tng)Cat();
cat.setName(“tom?;
s.save(cat);

cat.setName(“mary?;
s.update(cat);(6)

Cat (tng)littleCat (tng)= (tng)new (tng)Cat();
littleCat.setName(“tom?;
s.save(littleCat);

s.flush();


q个例子看v来有什么问题?估计不了(jin)解Hibernate~存机制的h多半?x)说没有问题Q但它也一样不能按照我们的思\正常q行Q在flushq程中会(x)产生主键冲突Q可能你想问Q“在save(littleCat)之前不是已经更改cat.nameq已l更C(jin)么?Z么还?x)发生主键冲H那Q”这里的原因是我在解释W一个例子时所提到的缓存flush序的问题,Hibernate按照insert,update,…?delete的顺序提交所有登记的操作Q所以你的s.update(cat)虽然在程序中出现在s.save(littleCat)之前Q但是在flush的过E中Q所有的save都将在update之前执行Q这造成?jin)主键冲H的发生?br /> (tng)
q个例子中的更改Ҏ(gu)一h?6)之后加入s.flush()强制Session在保存littleCat之前更新cat的name。这样在W二ơflush时就只会(x)执行s.save(littleCat)q次登记的动作,q样׃?x)出C键冲H的状况?br /> (tng)
再看一个例子(很奇怪的例子Q但是能够说明问题)(j)

Cat (tng)cat (tng)= (tng)new (tng)Cat();
cat.setName(“tom?;
s.save(cat); (tng)(7)
s.delete(cat);(8)

cat.id=null;(9)
s.save(cat);(10)
s.flush();

 (tng)
q个例子在运行时?x)生异常net.sf.hibernate.HibernateException: (tng)identifier (tng)of (tng)an (tng)instance (tng)of (tng)Cat (tng)altered (tng)from (tng)8b818e920a86f038010a86f03a9d0001 (tng)to (tng)null
 (tng)
q里例子也是有关于缓存的问题Q但是原因稍有不同:(x)
Q?Q和Q?Q的处理相同?br />Q?QSession?x)在deletions中登记这个删除动作,同时更新entityEntries中该对象的登记状态ؓ(f)DELETED?br />Q?QCatcȝ标识W字Dؓ(f)id,其|ؓ(f)null便于重新分配idq保存进数据库?br />Q?0Q此时Session?x)首先在entityEntries查找cat对象是否曄与Session做过兌Q因为cat只改变了(jin)属性|引用q未改变Q所以会(x)取得状态ؓ(f)DELETED的那个登记对象。由于第二次保存的对象已l在当前Session中删除,save?x)强制Session缓存flush才会(x)l箋Qflush的过E中首先要执行最开始的save动作Q在q个save中检查了(jin)catq个对象的id是否与原来执行动作时的id相同。不q的是,此时cat的id被赋为nullQ异常被抛出Q程序终止(此处要注意,我们在以后的开发过E尽量不要在flush之前改变已经q行?jin)操作的对象的idQ?br /> (tng)
q个例子中的错误也是׃~存的g时更新造成的(当然Q与不正规的使用Hibernate也有关系Q,处理Ҏ(gu)有两U:(x)
1、在Q?Q之后flushQ这样就可以保证Q?0Q处savecat作ؓ(f)一个全新的对象q行保存?br />2、删除(9Q,q样W二ơsave所引v的强制flush可以正常的执行,在数据库中插入cat对象后将其删除,然后l箋W二ơsave重新插入cat对象Q此时cat的id仍与从前一致?br /> (tng)
q两U方法可以根据不同的需要来使用Q呵呵,总觉得好像是很不正规的方式来解决问题Q但是问题本w也不够正规Q只希望能够在应用开发中l大家一些帮助,不对的地方也希望各位l与指正?br /> (tng)
  ȝ来说Q由于Hibernate的flush处理机制Q我们在一些复杂的对象更新和保存的q程中就要考虑数据库操作顺序的改变以及(qing)延时flush是否对程序的l果有媄(jing)响。如果确实存在着影响Q那可以在需要保持这U操作顺序的位置加入flush强制Hibernate缓存中记录的操作flush入数据库Q这L(fng)h也许不太观Q但很有效?br />

William 2006-07-02 22:09 发表评论
]]>
JDBC事务优化http://www.tkk7.com/William/archive/2006/06/30/56053.htmlWilliamWilliamFri, 30 Jun 2006 14:44:00 GMThttp://www.tkk7.com/William/archive/2006/06/30/56053.htmlhttp://www.tkk7.com/William/comments/56053.htmlhttp://www.tkk7.com/William/archive/2006/06/30/56053.html#Feedback2http://www.tkk7.com/William/comments/commentRss/56053.htmlhttp://www.tkk7.com/William/services/trackbacks/56053.htmlJDBC事务优化

作者:(x)Jack Shirazi

开发通过ACID试的应用程?/em>

事务使得开发h员的工作变得单多?jin)。通过在JDBC API和诸如Oracle9i的关pL据库中用事务功能,在更新多用户应用E序Ӟ你可以把数据遭破坏的可能性降到最低。然而,事务需要处理开销Q与免费事务应用E序Q更Ҏ(gu)被破坏)(j)相比较,它会(x)降低pȝ的性能。那么,当用事务时Q什么才是保持性能的最好方法?

最佳的性能调优是避免做那些没必要做的事情。事务处理是数据库的大量工作Q而且数据库默认地l护多种资源以确保事务具有ACIDQ原子性,一致性,隔离性和持箋性)(j)属性(查看"ACID Transaction Properties"工具栏获取详l信息)(j)。这些数据库资源理多个数据q发操作以及(qing)提交和回滚操作,从而保证ACID事务属性。如果你能减数据库的此cL作,将提高应用E序的性能。让我们看一些避免处理开销q提高事务性能的方法?/font>

自动提交模式

最大限度减事务开销的第一个方法是通过把多个操作移C个单一事务中来合ƈ事务。默认情况下QJDBCq接工作在自动提交模式下Q这意味着每个发送到数据库的操作都会(x)作ؓ(f)独立事务自动执行。在q种情况下,每个Statement.executeQ)(j)Ҏ(gu)调用都如同由一条BEGIN TRANSACTION命o(h)开始,q由一条COMMIT命o(h)l束?

关闭自动提交模式q且明确定义事务需要进行大量额外的工作Q因Z必须手动d事务划分语句QCOMMIT和ROLLBACKQ。但是合q事务可以减性能开销Q特别是当你对你的系l进行׾~时。(下面?span class="bodycopy">"部分?x)涉及(qing)到合ƈ更新事务的技术细节。)(j)在重负荷pȝ中,事务开销意义重大。开销低Q系l的可׾~性就好?/font>

单地使用Connection.setAutoCommit(false)命o(h)来关闭自动提交模式?

JDBC APIq提供了(jin)一个Connection.getAutoCommit()Ҏ(gu)来返回当前的自动提交模式。当你关闭了(jin)自动提交模式Q你需要用两个事务划分方法:(x)Connection.commit()和Connection.rollback()?

当h工控制事务时Q需要遵循以下几条原则:(x)使事务尽可能保持短,不要在一个事务中包含很多操作使它们变得非常冗ѝ(使事务打开q保持行开锁状态,?x)?jing)响其他事务ƈ降低可׾~性。)(j)然而,如果几项操作可以一Ҏ(gu)一地执行Q那么就把它们合q到一个事务中?

合ƈ操作可能需要在你的SQL语句中增加额外的条g逻辑Qƈ且可能需要(f)时表。不这个开销Q合q事务会(x)更加有效Q因为数据库可以在一个步骤内获得所有需要的锁,q在一个步骤内释放它们?

当自动提交模式没有关闭时Q它所引v的更多事务会(x)产生更多的通信开销Q更多的锁定和释放时_(d)以及(qing)与其他会(x)话发生冲H的更大可能性?/font>

扚w更新

扚w更新单地说就是在一个事务和一个数据库调用中将多个DML语句Q例如插入、更新和删除Q发送到数据库。JDBC通过Statement.addBatch()和Statement.executeBatch()Ҏ(gu)支持q项功能。批量更新的技巧相当简单,在下文中?x)加以说明。记住关闭自动提交模式(保一个批处理作ؓ(f)一个事务执行)(j)Qƈ且当你完成后q一切后Q明提交批事务?/font>

清单 1 中的CZ使用?jin)普通的JDBC Statement对象。另外,JDBC API提供?jin)一个PreparedStatementc,它也可以用参数表CSQL语句?

此外Q当你用PreparedStatement 对象来代替Statement对象ӞOracle的JDBC批处理实施就可以得到优化。在Oracle JDBC中,Statement对象不会(x)在一ơ网l传输中传送所有成批的SQL语句。由于这个限Ӟ当成批传送语句时可以使用PreparedStatement对象Q因为PreparedStatement在一ơ批处理中会(x)传送所有的语句?

清单 2 l出?jin)用参数语句和PreparedStatement对象的相同批处理技巧?

借助于所有批处理语句相同的查询计划,在PreparedStatement对象中利用参数语句数据库进一步优化批处理。如果没有参数设定,语句׃(x)各不相同Q因而数据库׃能重复用查询计划?

虽然q种Ҏ(gu)l常可以提高性能Q但应注意以下几点:(x)处理开销与创建查询计划的联合导致第一ơ执行SQL语句时会(x)比用普通Statement对象时运行得更慢Q而随后准备好的执行语句将?x)快很多。(开发h员经常把首次PreparedStatement批处理移动到应用E序中对旉要求低的部分加以执行。)(j)使用PreparedStatement对象比使用Statement对象更有效,特别是当使用过50条语句的大批量处理时?br />
以上的示例用了(jin)JDBC规范所定义的标准批处理模式。Oracle的JDBC实施提供?jin)一U可选择的批处理模式Q它使用?jin)一U被UCOraclePreparedStatement.setExecuteBatch(int)的新Ҏ(gu)。在q种模式下,预设的语句被自动保存在客L(fng)Q直到语句的数量与setExecuteBatch(int)中的参数所定义?扚w?相等。这样一来,U篏的语句在一ơ传送中被发送到数据库。Oracle所推荐的这U模式在某些情况下会(x)比标准的批处理模式更快。当使用它的时候,调整扚w值来优化你的应用E序中事务的性能。Oracle模式惟一需要注意的一Ҏ(gu)Q它不是标准?-它用官方JDBC规范所不支持的扩展功能?br />

事务隔离U别

事务被定义ؓ(f)全有或全无操作。一个事务的ACID属性确保每件事情都发生在一个事务,如同在事务期间在数据库中没有发生其他操作。由此可见,Ҏ(gu)据库来说Q确保ACID属性有很多工作要做?/font>

JDBC Connection界面定义?jin)五U事务隔ȝ别(在下面说明)(j)。ƈ不是所有的数据库都支持所有的U别。例如,Oracle9i只支持TRANSACTION_READ_COMMITTED和TRANSACTION_ SERIALIZABLEq两个别?/font>

许多数据库,例如Oracle9iQ提供了(jin)其他事务U别支持。这些别不提供"真正?事务Q因为它们不完全W合ACID属性。然而,它们通过可接受的事务功能提供更好的性能Q因此它们对很多操作cd是非常有用的?/font>

在JDBC中定义的U别包括Q?

TRANSACTION_NONE。正式地ԌTRANSACTION_NONE不是一个有效的事务U别。根据java.sql Connection API文gQ这个别表CZ务是不被支持的,因此理论上说你不能用TRANSACTION_NONE作ؓ(f)一个自变量赋给C(j)onnection.setTransactionIsolation()Ҏ(gu)。事实上Q虽然一些数据库实施?jin)这个事务别,但是Oracle9i却没有实施?/font>

TRANSACTION_READ_UNCOMMITTED。这是最快的完全有效的事务别。它允许你读取其他还没有被提交到数据库的q发事务做出的修攏V这个API文g指出Q脏dQdirty readsQ、不可重复读取(non-repeatable readsQ和错误dQphantom readsQ都可以在这个事务别发生(参阅" 一些非ACID事务问题 "部分Q。这个别意在支持ACID?原子性(AtomicQ?部分Q在q个U别中,你的修改如果被提交,被认ؓ(f)是同时发生的Q如果被撤销Q就被当作什么也没发生。Oracle9i不支持这个别?/font>

TRANSACTION_READ_UNCOMMITTED。这是最快的完全有效的事务别。它允许你读取其他还没有被提交到数据库的q发事务做出的修攏V这个API文g指出Q脏dQdirty readsQ、不可重复读取(non-repeatable readsQ和错误dQphantom readsQ都可以在这个事务别发生(参阅" 一些非ACID事务问题 "部分Q?/font> q个U别意在支持ACID?原子性(AtomicQ?部分Q在q个U别中,你的修改如果被提交,被认ؓ(f)是同时发生的Q如果被撤销Q就被当作什么也没发生。Oracle9i不支持这个别?/span>

TRANSACTION_READ_COMMITTED。这是TRANSACTION_READ_UNCOMMITTED之后最快的完全有效的别。在此别中Q你可以d已经被提交到数据库中的其他ƈ发事务所做出的修攏VAPI文g指出Q脏d在这个别中是被止的,但是不可重复d和错误读取都可以发生。这个别是Oracle9i默认的别?

TRANSACTION_REPEATABLE_READ。这个别比TRANSACTION_SERIALIZABLE快,但是比其他的事务U别要慢。读取操作可以重复进行,q意味着两次d同样的域应该L得到同样的|除非事务本n改变?jin)这个倹{API文g指出Q脏d和不可重复读取在q个事务U别中是被禁止的Q但是错误读取可以发生?

从技术上Ԍ数据库通过在被d或写入的行上加锁来实施这个别,q且保持锁定状态直C务结束。这防止了(jin)q些行被修改或删除,但是不能防止额外的行被添?-因此Q就可能产生错误d。Oracle9i不支持这个别?/span>

TRANSACTION_SERIALIZABLE。这是最慢的事务U别Q但是它完全与ACID兼容?单词可串行化QserializableQ?指的是ACID兼容Q其中你的事务被认ؓ(f)在整体上已经发生Q就如同其他所有已提交的事务在q个事务之前或之后全部发生。换句话_(d)事务被串行执行?/span>

ACID事务属?/font>

ACID指的时数据库事务的基本属性:(x)原子性,一致性,隔离性和持箋性。所有的Oracle事务全部W合q些属性,虽然你可以在数据库系l中q行手动讄U别来加强各个属性(参阅"事务隔离U别"部分Q?/font>

原子性指的是事务中的整个zd序列必须被全部完成或全部攑ּ。事务不能部分地完成。与隔离性相l合后(见表1Q,原子性指的是L一个事务将查看M其他同时或以原子形式发生的事务所采取的所有活动?/font>

一致性指的是事务既可以徏立一个新的、有效的数据状态(在这U状态中可以q行所有的改动Q,它可以在操作p|的情况下Q把所有的数据q回C务发生之前已有的状态?

隔离性指在一个事务中发生的所有活动对其他事务来说都是不可见的Q直到该事务被提交?/font>

持箋性指的是事务成功做出q提交的所有改动是不变的,q且必须克服pȝ故障。比如说Q如果发生了(jin)故障或者系l重新启动,数据在最后提交事务之后所存在的状态下是可用的?

脏读取、不可重复读取和错误d在TRANSACTION_SERIALIZABLEU别是全部被止的。从技术上Ԍ数据库通过锁定在事务中使用的表来实施这个别。Oracle9i支持q个U别Q正如每个与W合ACID的数据库那样Q?

开发通过ACID试的应用程?/em>

选择正确的?/font>

你可以通过使用Connection.setTransactionIsolation()Ҏ(gu)讑֮一个连接的事务U别。类似地Q你可以通过使用Connection.getTransactionIsolation()Ҏ(gu)获得q接的当前事务别。你可以通过使用DatabaseMetaData.supportsTransaction IsolationLevel()Ҏ(gu)定׃的数据库驱动E序所支持的事务别,?/font> 清单3 所C?/font>

事务U别高Q数量越多、限制性更强的锁就?x)被q用到数据库记录或者表中。同Ӟ更多的锁被运用到数据库和它们的覆盖面宽QQ意两个事务冲H的可能性就大?/font>

如果有一个冲H(例如两个事务试图获取同一个锁Q,W一个事务必会(x)成功Q然而第二个事务被L直到W一个事务释放该锁(或者是试获取该锁的行时导致操作失败)(j)?

更多的冲H发生时Q事务的执行速度会(x)变慢Q因为它们将p更多的时间用于解军_H({待锁被释放Q?

最大限度地增加应用E序的可伸羃性需要^衡地理解事务执行Ҏ(gu)。一斚wQ你可以通过在事务中所执行的操作数量减到最来优化应用E序Q从而减了(jin)单个事务所p的时间。但是这样就增加?jin)事务的L量,q可能增加冲H的风险。用批量操作,你可以最大限度地减少所执行事务的数量?

然而,q增加了(jin)单个事务的长度,也可能增加冲H的风险。在L一U情况下Q当你降低事务隔ȝ别时Q事务用的锁就少Q因此越不会(x)引v性能的下降。这样做的风险是因ؓ(f)没有使用完全W合ACID的事务,从而损׃(jin)功能性?/font>

如果你需要把事务执行旉减到最的话,在你的整个应用程序中使用一个事务别好像ƈ不是很理惟뀂在应用E序中查找读取查询,对于每个查询Q考虑在下? 一些非ACID事务问题 "部分列出的Q何问题是否会(x)对给定数据的查询或数据更新模式生负面媄(jing)响。读取静(rn)态表Q或者只被读取它们的同一事务所更新的表Q可以安全地使用最低的事务U别。在那些不可能进行ƈ发更新的事务中,你可以安全、高效地使用诸如TRANSACTION_ READ_COMMITTEDq样的别?

一些非ACID事务问题

当一个连接用了(jin)不完全符合ACID的TRANSATION_SERIALIZABLE事务U别Ӟ׃(x)发生很多问题。下面的例子使用?jin)一个名为table_sizes的表Q它有两个字D,tablename和tablesize。这个例子还使用?jin)两个事务,T1和T2Q其中T1使用TRANSACTION_SERIALIZABLEU别?/font>

脏读取。当一个事务能发现一行中有未提交的更Ҏ(gu)Q就发生?jin)一ơ脏d。如果另一个事务改变了(jin)一个|你的事务可以d那个改变的|但其他的事务回滚其事务Qɘq个值无效或成ؓ(f)脏倹{例如,q里l出?jin)当T2使用事务U别TRANSACTION_ READ_UNCOMMITTED时发生的情况Q其中记录ؓ(f)tablename=usersQtablesize=11?

?Q每个事务问题在每个允许的事务隔ȝ别中发生的可能性?/font>
隔离U别 脏读? 不可重复d 错误插入
d未提交数?/font> ?/font> ?/font> ?/font>
d已提交数?/font> ? ?/font> ?/font>
可重复读? ? ? ?/font>
可串行化 ? ? ?

1. T1和T2启动它们的事务?br />2. T1记录更Cؓ(f)tablename=usersQtablesize=12?br />3. T2dT1未提交的修改Q读取记录tablename=userQtablesize=12Q因为T2的事务别意味着未提交的修改有时可以被读取?br />4. T1回滚事务Q因此tablename=users行中tablesize=11?br />5. T2仍有无效的记录|(x)记录tablename=usersQtablesize=12。但是它可以通过脏表寸值工作,q且能在脏值的基础上成功地提交修改?/font>

不可重复d。当事务内一条记录在事务被两ơ读取而没有更新时Q就发生?jin)不可重复读取,而且Q从两次d中可以看C同的l果。如果你的事务读取一个|q且另一事务提交?jin)对q个值的一ơ修改(或删除了(jin)q条记录Q,然后你的事务便可以读取这个修改后的|或发现这条记录丢失)(j)Q尽你的事务还没有提交或回滚。例如,q里l出?jin)当T2使用事务U别TRANSACTION_READ_COMMITTED时发生的情况Q其中记录ؓ(f)tablename=usersQtablesize=11?

1. T1和T2启动它们的事务?br />2. T2d记录tablename=usersQtablesize=11?br />3. T1记录更Cؓ(f)tablename=usersQtablesize=12q提交修攏V?br />4. T2重新d记录tablename=usersQƈ且现在看到tablesize=12Q因为T2的事务别意味着其他事务提交的修改可以被看到Q尽T2q没有提交或回滚?/font>

错误d。当一个事务读取由另一个未提交的事务插入的一行时Q就发生?jin)错误读取。如果另一事务一行插入到一个表里,当你的事务查询那个表时就能够d那条新记录,即其他的事务相l回滚。例如,q里l出?jin)当T2使用事务U别TRANSACTION_REPEATABLE_READ时发生的情况Q其中记录ؓ(f)tablename=usersQtablesize=11?/font>

1. T1和T2启动它们的事务?br />2. T2执行SELECT * FROM table_sizes WHERE tablesize>10q读取一行,tablesize=11的行tablename=user?br />3. T1插入tablename=groupsQtablesize=28的记录?br />4. T2再次执行SELECT * FROM table_sizes WHERE tablesize>10q读取两条记录:(x) tablename=usersQtablesize=11和tablename=groupsQtablesize=28?br />5. T1回滚事务Q因此记录tablename=goupsQtablesize=28不再存在于table_sizes表中?/font>

Ҏ(gu)T2被读取的数据集中所h的一条额外错误记录,T2可以成功地提交数据?/font>

?/font> ? 中,你会(x)发现在每一个所允许的事仉ȝ别中发生事务问题的可能性列表?/font>

用户控制的事?/font>

在许多应用程序中Q用户在一个事务结束以前,必须执行一个明的动作Q比如点?定"?取消"Q。这些情况会(x)D很多问题。例如,如果用户忘记?jin)终止活动或者让zd保持未完成的状态,资源׃直在应用E序和数据库中保持开攄态,q可能会(x)在ƈ发的zd和锁定的资源之间产生冲突Q降低了(jin)pȝ的性能。只有单一的用户应用程序或用户不共享资源的应用E序Q才不受q个问题的媄(jing)响?/font>

让用户处于一个JDBC事务控制下的主要解决Ҏ(gu)是用优化的事务。这些事务ؓ(f)外部的JDBC事务更新攉信息Q然后用一U机制来(g)查更新没有与其他M个可能在两者间已经被处理的更新发生冲突?/font>

(g)查优化冲H的机制包括使用旉标记或更改计数器Q从期望状态检查区别。例如,当应用程序从用户输入攉用于更新的数据时Q数据可以作Z批包含时间标记的安全机制的SQL语句Q被发送到数据库,以确保数据库中的原始数据与最初用于客户应用程序的数据相同。一个成功的事务更新记录Q包括时间标讎ͼ昄?jin)最q修改的数据。如果来自另一用户的更CɽW一个用L(fng)修改失效Q那么时间标记就?x)改变,q且当前事务需要被回滚而不是被提交。对于许多应用程序,中等E度的冲H事务是很少的,因此事务l常?x)成功完成?/font>

当一个事务失败时Q应用程序把所输入的数据提交给用户Q用户能够Ҏ(gu)D冲突的更改,做出必要的修改ƈ且重新提交?

其他斚w的考虑

来Q用JDBC3.0Ҏ(gu)的开发h员将在更多的Ҏ(gu)来优化事务。例如,Oracle9iW?版实施了(jin)几个JDBC3.0Ҏ(gu),包括事务存储点(SavepointQ。存储点让你在一个事务中标记一个点q且回滚它,而不是回滚整个事务?

虽然q听h有些难以|信Q但存储点确实能够极大地减少性能开销。它们对性能的实际媄(jing)响将证明JDBC3.0?x)得到更q泛的支持,但不要过多用存储点或者避免在M关键性能代码部分它们放在一赗如果你实要用它们,必ȝ保尽可能C用Connection.release Savepoint(Savepoint)Ҏ(gu)释放它们的资源?/font>

当前QJDBC2.0支持跨越多个q接的分布式事务Qƈ且Oracle提供?jin)一个ؓ(f)分布式事务设计的W合业界XA规范的Java Transaction APIQJTAQ模块。ؓ(f)分布式事务实施一个外部事务管理器的决定ƈ不是一件小事情Q然而,分布式事务比普通事务明显要慢,因ؓ(f)它需要额外的通讯工作来协调多个数据库资源之间的连接。从Ua(b)的性能观点来看Q最好是在{Ud分布式事务体pȝ构以前考虑多种可选择的设计方案?/font>

Jack Shirazi (jack@JavaPerformanceTuning.com)?JavaPerformanceTuning.com Q一个关于Java应用E序性能调优的所有方面信息的首家资源站点Q的ȝQ也是《Java Performance Tuning》(O'Reilly and Associates出版Q一书的作者?/font>




William 2006-06-30 22:44 发表评论
]]>
JDBC事务U别http://www.tkk7.com/William/archive/2006/06/30/56047.htmlWilliamWilliamFri, 30 Jun 2006 14:08:00 GMThttp://www.tkk7.com/William/archive/2006/06/30/56047.htmlhttp://www.tkk7.com/William/comments/56047.htmlhttp://www.tkk7.com/William/archive/2006/06/30/56047.html#Feedback0http://www.tkk7.com/William/comments/commentRss/56047.htmlhttp://www.tkk7.com/William/services/trackbacks/56047.html

TRANSACTION_READ_UNCOMMITTED 说明在提交前一个事务可以看到另一个事务的变化。这栯诅R不可重复的d虚读都是允许的?br />

TRANSACTION_READ_COMMITTED 说明d未提交的数据是不允许的。这个别仍然允怸可重复的d虚读产生?br />

TRANSACTION_REPEATABLE_READ 说明事务保证能够再次d相同的数据而不?x)失败,但虚M然会(x)出现?br />

TRANSACTION_SERIALIZABLE 是最高的事务U别Q它防止脏读、不可重复的d虚读?

William 2006-06-30 22:08 发表评论
]]>
Hibernate的事务和q发(ZT)http://www.tkk7.com/William/archive/2006/06/30/56034.htmlWilliamWilliamFri, 30 Jun 2006 13:33:00 GMThttp://www.tkk7.com/William/archive/2006/06/30/56034.htmlhttp://www.tkk7.com/William/comments/56034.htmlhttp://www.tkk7.com/William/archive/2006/06/30/56034.html#Feedback0http://www.tkk7.com/William/comments/commentRss/56034.htmlhttp://www.tkk7.com/William/services/trackbacks/56034.html
 (tng)除了(jin)自动版本理Q针对行U?zhn)观锁定,Hibernate也提供了(jin)辅助的APIQ它使用?SELECT FOR UPDATE的SQL语法。本章后面会(x)讨论q个API?
我们从Configuration层、SessionFactory? ?Session层开始讨论Hibernate的ƈ行控制?a target="_blank">数据?/a>事务和应?E序的长事务?

12.1.Session和事务范?transaction scopes)
一个SessionFactory对象的创Z价很昂贵Q它是线E?a target="_blank">安全的对象,它被设计成可?为所有的应用E序U程所׃n。它只创Zơ,通常是在应用E序启动的时候,׃?Configuraion的实例来创徏?
一个Session的对象是d的,非线E?a target="_blank">安全的,对于单个业务q程Q单个的 工作单元而言Q它只被使用一ơ,然后׃弃。只有在需要的时候,Session 才会(x)获取一个JDBC的ConnectionQ或一个DatasourceQ?对象。所以你可以攑ֿ(j)的打开和关闭SessionQ甚臛_你ƈ不确定一个特定的?求是否需要数据访问时Q你也可以这样做?一旦你实现下面提到的用了(jin)h拦截的模式,q就 变得很重要了(jin)?
此外我们q要考虑数据?/a>事务?a target="_blank">数据?/a>事务应该可能的短,降低数据?/a>锁定造成的资源争用?数据?/a>长事务会(x)D你的应用E序无法扩展到高的ƈ发负载?
一个操作单?Unit of work)的范围是多大Q单个的Hibernate Session能跨多?
数据?/a>事务吗?q是一个Session的作用范围对应一?a target="_blank">数据?/a>事务的范_(d)应该何时打开 SessionQ何时关闭SessionQ,你又如何划分数据?/a>事务的边界呢Q?

12.1.1.操作单元(Unit of work)
首先Q别再用session-per-operationq种反模式了(jin)Q也是_(d)在单个线E中Q?不要因ؓ(f)一ơ简单的
数据?/a>调用Q就打开和关闭一ơSessionQ?a target="_blank">数据?/a>事务也是如此?应用E序中的数据?/a>调用是按照计划好的次序,分组为原子的操作单元。(注意Q这也意味着Q应用程 序中Q在单个的SQL语句发送之后,自动事务提交(auto-commit)模式失效?jin)。这U模式专门ؓ(f)SQL控制台操作设计的?Hibernate止立即自动事务提交模式Q或者期望应用服务器止立即自动事务提交模式。)(j)
在多用户的client/server应用E序中,最常用的模式是 每个h一个会(x)?session-per-request)?在这U模式下Q来自客L(fng)的请求被发送到服务器端Q即Hibernate持久化层q行的地方)(j)Q一 个新的Hibernate Session被打开Qƈ且执行这个操作单元中所有的
数据?/a>操作?一旦操作完成(同时发送到客户端的响应也准备就l)(j)Qsession被同步,然后关闭。你也可以用单 ?a target="_blank">数据?/a>事务来处理客L(fng)hQ在你打开Session之后启动事务Q在你关?Session之前提交事务。会(x)话和h之间的关pL一对一的关p,q种模式?于大多数应用E序来说是很的?
真正的挑战在于如何去实现q种模式Q不仅Session和事务必被正确的开始和l束Q?而且他们也必能被数据访问操作访问。用拦截器来实现操作单元的划分,该拦截器在客L(fng)h辑ֈ?务器端的时候开始,在服务器端发送响应(卻IServletFilterQ之前结束。我们推?使用一个ThreadLocal 变量Q把 Sessionl定到处理客L(fng)h的线 E上厅R这U方式可以让q行在该U程上的所有程序代码轻杄讉KSessionQ就像访问一 个静(rn)态变量那P(j)。你也可以在一个ThreadLocal 变量中保持事务上下文环境Q不q这依赖 于你所选择?a target="_blank">数据?/a>事务划分机制。这U实现模式被UC?ThreadLocal Session?Open Session in View。你可以很容易的扩展本文前面章节展示?HibernateUtil 辅助cL实现q种模式。当?dng)你必胝业揭恢质_(ki)掯仄鞯姆椒ǎ?且可以把拦截器集成到你的应用环境中。请参考Hibernate
|站上面的提C和例子?

12.1.2.应用E序事务(Application transactions)
session-per-request模式不仅仅是一个可以用来设计操作单元的有用概念。很多业务处理流E都需 要一pd完整的和用户之间的交互,即用户对数据?/a>的交叉访问。在Zweb的应用和企业 应用中,跨用户交互的数据?/a>事务是无法接受的。考虑下面的例子:(x)
在界面的W一屏,打开对话框,用户所看到的数据是被一个特定的 Session 和数?库事务蝲?load)的。用户可以随意修改对话框中的数据对象?
5分钟后,用户点击“保存”,期望所做出的修改被持久化;同时他也期望自己是唯一修改q个信息的hQ不?x)出?修改冲突?
从用L(fng)角度来看Q我们把q个操作单元UCؓ(f)应用E序长事务(application transactionQ?在你的应用程序中Q可以有很多U方法来实现它?
头一个幼E的做法是,在用h考的q程中,保持Session?a target="_blank">数据?/a>事务是打开的, 保持
数据?/a>锁定Q以Lq发修改Q从而保?a target="_blank">数据?/a>事务隔离U别和原子操作。这U方式当然是一个反模式Q?因ؓ(f)数据?/a>锁定的维持会(x)D应用E序无法扩展q发用户的数目?
很明显,我们必须使用多个
数据?/a>事务来实C个应用程序事务。在q个例子中,l护业务处理程?事务隔离变成?jin)应用程序层的部分责仅R单个应用程序事务通常跨越多个数据?/a>事务。如果仅仅只有一 ?a target="_blank">数据?/a>事务Q最后的那个事务Q保存更新过的数据,而所有其他事务只是单U的d数据Q例如在一 个跨多个请?响应周期的向导风格的对话框中Q,那么应用E序事务保证其原子性。这U方式比?hq要Ҏ(gu)实现Q特别是当你使用?jin)Hibernate的下q特性的时候:(x)
自动版本?- Hibernate能够自动q行乐观q发控制 Q如果在用户思?的过E中发生q发修改冲突QHibernate能够自动(g)到?
q对象QDetached ObjectsQ? 如果你决定采用前面已l讨?session-per-request模式Q所有蝲入的实例在用h考的q程 中都处于与Sessionq的状态。Hibernate允许你把与Sessionq的对象重新关联到Session 上,q且对修改进行持久化Q这U模式被UCؓ(f) session-per-request-with-detached-objects。自动版本化被用来隔dƈ发修攏V?
长生命周期的Session QLong SessionQ? Hibernate 的Session 可以?a target="_blank">数据?/a>事务提交之后和底层的JDBCq接断开Q当一个新的客L(fng)h到来的时候,它又重新q接上底层的 JDBCq接。这U模式被UC为session-per-application-transactionQ这U情况可 能会(x)造成不必要的Session和JDBCq接的重新关联。自动版本化被用来隔dƈ发修攏V?
session-per-request-with-detached-objects ?session-per-application-transaction 各有优缺点,我们在本章后面乐观ƈ?控制那部分再q行讨论?

12.1.3.x对象标识(Considering object identity)
应用E序可能在两个不同的Session中ƈ发访问同一持久化状态,但是Q?一个持久化cȝ实例无法在两?Session中共享。因此有两种不同的标识语义:(x)
数据?/a>标识
foo.getId().equals( bar.getId() )
JVM 标识
foo==bar
对于那些兌?特定Session Q也是在单个Session的范围内Q上的对象来_(d)q?两种标识的语义是{h(hun)的,?a target="_blank">数据?/a>标识对应的JVM标识是由Hibernate来保 证的。不q,当应用程序在两个不同的session中ƈ发访问具有同一持久化标 识的业务对象实例的时候,q个业务对象的两个实例事实上是不相同的(?JVM识别来看Q。这U冲H可以通过在同步和提交的时候用自动版本化和乐 观锁定方法来解决?
q种方式把关于ƈ发的头疼问题留给?jin)Hibernate?a target="_blank">数据?/a>Q由于在单个U程内,操作单元中的对象识别?需要代h늚锁定或其他意义上的同步,因此它同时可以提供最好的可׾~性。只要在单个U程只持有一?SessionQ应用程序就不需要同步Q何业务对象。在Session 的范围内Q应用程序可以放?j)的使?=q行对象比较?
不过Q应用程序在Session的外面?=q行对象比较可能?D无法预期的结果。在一些无法预料的场合Q例如,如果你把两个q对象实例放进同一?Set的时候,可能发生。这两个对象实例可能有同一?a target="_blank">数据?/a>标识Q也是_(d) 他们代表?jin)表的同一行数据)(j)Q从JVM标识的定义上来说Q对q的对象而言QHibernate无法保证他们 的的JVM标识一致。开发h员必覆盖持久化cȝequals()Ҏ(gu)?hashCode() Ҏ(gu)Q从而实现自定义的对象相{语义。警告:(x)不要使用
数据?/a>标识 来实现对象相{,应该使用业务键|由唯一的,通常不变的属性组成。当一个瞬时对象被持久化的?候,它的数据?/a>标识?x)发生改变。如果一个瞬时对象(通常也包括脱对象实例)(j)被放入一 个SetQ改变它的hashcode?x)导致与q个Set的关pM断。虽 然业务键值的属性不?a target="_blank">数据?/a>主键那样E_不变Q但是你只需要保证在同一个Set 中的对象属性的E_性就_?jin)。请到Hibernate|站d求这个问题更多的详细的讨论。请注意Q这不是一 个有关Hibernate的问题,而仅仅是一个关于Java对象标识和判{行为如何实现的问题?

12.1.4.常见问题
决不要用反模式session-per-user-session或?session-per-applicationQ当?dng)q个规定几乎没有例外Q。请注意Q?下述一些问题可能也?x)出现在我们推荐的模式中Q在你作出某个设计决定之前,请务必理解该模式的应用前提?
Session 是一个非U程安全的类。如果一个Session 实例允许׃n的话Q那些支持ƈ发运行的东东Q例如HTTP requestQsession beans,或者是 Swing workersQ将?x)导致出现资源争用(race conditionQ。如果在HttpSession中有 Hibernate 的Session的话Q稍后讨论)(j)Q你应该考虑同步讉K你的Http session?否则Q只要用戯够快的点?yn)L览器的“刷新”,׃(x)D两个q发q行U程使用同一?Session?
一个由Hibernate抛出的异常意味着你必ȝ卛_?a target="_blank">数据?/a>事务Qƈ立即关闭Session Q稍后会(x)展开讨论Q。如果你的Sessionl定C个应用程序上Q你?d止该应用E序。回?a target="_blank">数据?/a>事务q不?x)把你的业务对象退回到事务启动时候的状态。这 意味着数据?/a>状态和业务对象状态不同步。通常情况下,q不是什么问题,因ؓ(f)异常是不?恢复?你必d回滚之后重新开始执行?
Session ~存?jin)处于持久化状态的每个对象QHibernate?x)监视和(g)查脏数据Q?q意味着Q如果你让Session打开很长一D|_(d)或是仅仅载入?jin)过多的数据Q?Session占用的内存会(x)一直增长,直到抛出OutOfMemoryException异常。这?问题的一个解x法是调用clear() 和evict()来管?Session的缓存,但是如果你需要大扚w数据操作的话Q最好考虑 使用存储q程。在W?4?扚w处理QBatch processingQ中有一些解x案。在用户?x)话期间一直保?Session打开也意味着出现脏数据的可能性很高?

12.2.
数据?/a>事务声明
数据?/a>Q或者系l)(j)事务的声明L必须的。在数据?/a>事务之外Q就无法?a target="_blank">数据?/a>通讯Q这可能?x)让那些习(fn)惯?自动提交事务模式的开发h员感到迷惑)(j)。永q用清晰的事务声明Q即使只L作也是如此。进?昑ּ的事务声明ƈ不L需要的Q这取决于你的事务隔ȝ别和数据?/a>的能力,但不怎么_(d)声明事务d有益无害?
一个Hibernate应用E序可以q行在非托管环境中(也就是独立运行的应用E序Q简单Web应用E序Q?或者Swing囑Ş桌面应用E序Q,也可以运行在托管的J2EE环境中。在一个非托管环境中,Hibernate 通常自己负责理
数据?/a>q接池。应用程序开发h员必L工设|事务声明,换句话说Q就是手工启 动,提交Q或者回?a target="_blank">数据?/a>事务。一个托的环境通常提供?jin)容器管理事务,例如事务装配通过可声 明的方式定义在EJB session beans的部|描q符中。可~程式事务声明不再需要,即?Session 的同步也可以自动完成?
让持久层具备可移植性是Z的理惟뀂Hibernate提供?jin)一套称为Transaction的封装APIQ?用来把你的部|环境中的本C务管理系l{换到Hibernate事务上。这个API是可选的Q但是我们强?推荐你用,除非你用CMT session bean?
通常情况下,l束 Session 包含?jin)四个不同的阶?
同步session(flush,刷出到磁盘)(j)
提交事务
关闭session
处理异常
session的同?flush,刷出Q前面已l讨?jin),我们现在q一步考察在托和非托环境下的事务声明和异常处理?

12.2.1.非托环?/strong>
如果Hibernat持久层运行在一个非托管环境中,
数据?/a>q接通常由Hibernate的连接池机制 来处理?



代码内容
session/transaction处理方式如下所C:(x)
//Non-managed environment idiom
Session sess = factory.openSession();
Transaction tx = null;
try {
tx = sess.beginTransaction();

// do some work
...

tx.commit();
}
catch (RuntimeException e) {
if (tx != null) tx.rollback();
throw e; // or display error message
}
finally {
sess.close();
}

你不需要显式flush() Session - 对commit()的调用会(x)自动触发session的同步?
调用 close() 标志session的结束?close()Ҏ(gu)重要的暗C是Qsession释放?jin)JDBCq接?
q段Java代码是可UL的,可以在非托管环境和JTA环境中运行?
你很可能从未在一个标准的应用E序的业务代码中见过q样的用法;致命的(pȝQ异常应该L 在应用程序“顶层”被捕获。换句话_(d)执行Hibernate调用的代码(在持久层Q和处理 RuntimeException异常的代码(通常只能清理和退出应用程序)(j)应该在不?的应用程序逻辑层。这对于你设计自q软gpȝ来说是一个挑战,只要有可能,你就应该使用 J2EE/EJB容器服务。异常处理将在本章稍后进行讨论?
h意,你应该选择 org.hibernate.transaction.JDBCTransactionFactory (q是默认选项).

12.2.2.使用JTA
如果你的持久层运行在一个应用服务器中(例如Q在EJB session beans的后面)(j)QHibernate获取 的每个数据源q接自动成为全局JTA事务的一部分。Hibernate提供?jin)两U策略进行JTA集成?
如果你用bean理事务QBMTQ,可以通过使用Hibernate?Transaction API来告?应用服务器启动和l束BMT事务。因此,事务理代码和在非托环境下是一L(fng)?




代码内容
// BMT idiom
Session sess = factory.openSession();
Transaction tx = null;
try {
tx = sess.beginTransaction();

// do some work
...

tx.commit();
}
catch (RuntimeException e) {
if (tx != null) tx.rollback();
throw e; // or display error message
}
finally {
sess.close();
}
在CMT方式下,事务声明是在session bean的部|描q符中,而不需要编E?除非你设|了(jin)属性hibernate.transaction.flush_before_completion?hibernate.transaction.auto_close_session为trueQ?否则你必自己同步和关闭Session。Hibernate可以Z自动同步和关?Session。你唯一要做的就是当发生异常时进行事务回滚。幸q的是, 在一个CMT bean中,事务回滚甚至可以由容器自动进行,因ؓ(f)由session beanҎ(gu)抛出的未处理?RuntimeException异常可以通知容器讄全局事务回滚。这意味着 在CMT中,你完全无需使用Hibernate的Transaction API ?
h意,当你配置Hibernate事务工厂的时候,在一个BMT session bean中,你应该选择 org.hibernate.transaction.JTATransactionFactoryQ在一?CMT session bean中选择org.hibernate.transaction.CMTTransactionFactory?CQ同时也要设|org.hibernate.transaction.manager_lookup_class?
如果你用CMT环境Qƈ且让容器自动同步和关闭sessionQ你可能也希望在你代码的不同部分使用 同一个session。一般来_(d)在一个非托管环境中,你可以用一个ThreadLocal 变量来持有这个sessionQ但是单个EJBҎ(gu)调用可能?x)在不同的线E中执行QD例来_(d)一个session bean调用另一个session beanQ。如果你不想在应用代码中被传递Session?象实例的问题困扰的话Q那么SessionFactory 提供?getCurrentSession()Ҏ(gu)很适合你,该方法返回一个绑定到JTA事务 上下文环境中的session实例。这也是把Hibernate集成C个应用程序中的最单的Ҏ(gu)Q这个“当 前的”sessionL可以自动同步和自动关闭(不考虑上述的属性设|)(j)。我们的session/transaction 理代码减少到如下所C:(x)




代码内容
// CMT idiom
Session sess = factory.getCurrentSession();

// do some work
...

换句话来_(d)在一个托环境下Q你要做的所有的事情是调用 SessionFactory.getCurrentSession()Q然后进行你的数据访问,把其余的工作 交给容器来做。事务在你的session bean的部|描q符中以可声明的方式来设|。session的生命周期完?由Hibernate来管理?
对after_statementq接释放方式有一个警告。因为JTA规范的一个很愚蠢的限ӞHibernate不可能自动清理Q何未关闭的ScrollableResults 或者IteratorQ它们是由scroll()或iterate()产生的。你must通过在finally块中Q显式调用ScrollableResults.close()或者Hibernate.close(Iterator)Ҏ(gu)来释攑ֺ?a target="_blank">数据?/a>游标?当然Q大部分E序完全可以很容易的避免在CMT代码中出现scroll()或iterate()?

12.2.3.异常处理
如果 Session 抛出异常 (包括MSQLException), 你应该立卛_?a target="_blank">数据?/a>事务Q调?Session.close() Q丢弃该 Session实例。Session的某些方法可能会(x)Dsession 处于不一致的状态。所有由Hibernate抛出的异帔R视ؓ(f)不可以恢复的。确保在 finally 代码块中调用close()Ҏ(gu)Q以关闭?Session?
HibernateException是一个非(g)查期异常Q这不同于Hibernate老的版本Q, 它封装了(jin)Hibernate持久层可能出现的大多数错误。我们的观点是,不应该强q应用程序开发h?在底层捕h法恢复的异常。在大多数Y件系l中Q非(g)查期异常和致命异帔R是在相应Ҏ(gu)调用 的堆栈的层被处理的Q也是_(d)在Y件上面的逻辑层)(j)Qƈ且提供一个错误信息给应用软g的用?Q或者采取其他某些相应的操作Q。请注意QHibernate也有可能抛出其他q不属于 HibernateException的非(g)查期异常。这些异常同样也是无法恢复的Q应?采取某些相应的操作去处理?
在和
数据?/a>q行交互ӞHibernate把捕L(fng)SQLException装为Hibernate?JDBCException。事实上QHibernate试把异常{换ؓ(f)更有实际含义 的JDBCException异常的子cR底层的SQLException可以 通过JDBCException.getCause()来得到。Hibernate通过使用兌?SessionFactory上的SQLExceptionConverter?把SQLException转换Z个对应的JDBCException 异常的子cR默认情况下QSQLExceptionConverter可以通过配置dialect 选项指定Q此外,也可以用用戯定义的实现类Q参考javadocs SQLExceptionConverterFactorycL?jin)解详情Q。标准的 JDBCException子类型是Q?
JDBCConnectionException - 指明底层的JDBC通讯出现错误
SQLGrammarException - 指明发送的SQL语句的语法或者格式错?
ConstraintViolationException - 指明某种cd的约束违例错?
LockAcquisitionException - 指明?jin)在执行h操作Ӟ获取 所需的锁U别时出现的错误?
GenericJDBCException - 不属于Q何其他种cȝ原生异常

12.3.乐观q发控制(Optimistic concurrency control)
唯一能够同时保持高ƈ发和高可伸羃性的Ҏ(gu)是使用带版本化的乐观ƈ发控制。版本检查用版本号?或者时间戳来检更新冲H(q且防止更新丢失Q。HibernateZ用乐观ƈ发控制的代码提供?jin)三U可 能的Ҏ(gu)Q应用程序在~写q些代码Ӟ可以采用它们。我们已l在前面应用E序长事务那部分展示?乐观q发控制的应用场景,此外Q在单个
数据?/a>事务范围内,版本(g)查也提供?jin)防止更Cq好处?
12.3.1.应用E序U别的版本检?Application version checking)
未能充分利用Hibernate功能的实C码中Q每ơ和
数据?/a>交互都需要一个新?SessionQ而且开发h员必d昄数据之前?a target="_blank">数据?/a>中重 新蝲入所有的持久化对象实例。这U方式迫使应用程序自己实现版本检查来保 应用E序事务的隔,从数据访问的角度来说是最低效的。这U用方式和 entity EJB最怼?
// foo is an instance loaded by a previous Session
session = factory.openSession();
Transaction t = session.beginTransaction();
int oldVersion = foo.getVersion();
session.load( foo, foo.getKey() ); // load the current state
if ( oldVersion!=foo.getVersion ) throw new StaleObjectStateException();
foo.setProperty("bar");
t.commit();
session.close();
version 属性?来映,如果对象 是脏数据Q在同步的时候,Hibernate?x)自动增加版本号?
当然Q如果你的应用是在一个低数据q发环境下,q不需要版本检查的话,你照样可以?q种方式Q只不过跌版本(g)查就是了(jin)。在q种情况下,最晚提交生?Qlast commit winsQ就是你的应用程序长事务的默认处理策略?误住这U策略可能会(x)让应用Y件的用户感到困惑Q因Z们有可能?x)碰上更C失掉却没 有出错信息,或者需要合q更改冲H的情况?
很明显,手工q行版本(g)查只适合于某些Y件规模非常小的应用场景,对于大多数Y件应用场?来说q不现实。通常情况下,不仅是单个对象实例需要进行版本检查,整个被修改过的关 联对象图也都需要进行版本检查。作为标准设计范例,Hibernate使用长生命周?Session的方式,或者脱对象实例的方式来提供自动版本检查?

12.3.2.长生命周期session和自动版本化
单个 Session实例和它所兌的所有持久化对象实例都被用于整个 应用E序事务。Hibernate在同步的时候进行对象实例的版本(g)查,如果(g)到q发?改则抛出异常。由开发h员来军_是否需要捕获和处理q个异常Q通常的抉择是l用?提供一个合q更改,或者在无脏数据情况下重新进行业务操作的Z(x)Q?
在等待用户交互的时候, Session 断开底层的JDBCq接。这U方??a target="_blank">数据?/a>讉K的角度来说是最高效的方式。应用程序不需要关?j)版本检查或q对象实例 的重新关联,在每?a target="_blank">数据?/a>事务中,应用E序也不需要蝲入读取对象实例?




代码内容
// foo is an instance loaded earlier by the Session
session.reconnect(); // Obtain a new JDBC connection
Transaction t = session.beginTransaction();
foo.setProperty("bar");
t.commit(); // End database transaction, flushing the change and checking the version
session.disconnect(); // Return JDBC connection

foo 对象始终和蝲入它的Session相关联?Session.reconnect()获取一个新?a target="_blank">数据?/a>q接Q或?你可以提供一个)(j)Qƈ且l当前的session。Session.disconnect() Ҏ(gu)把session与JDBCq接断开Q把
数据?/a>q接q回到连接池Q除非是你自己提供的数据 库连接)(j)。在Session重新q接?a target="_blank">数据?/a>q接之后Q你可以对Q何可能被其他事务更新q?的对象调用Session.lock()Q设|LockMode.READ 锁定模式Q这样你可以对那些你不准备更新的数据进行强制版本检查。此外,你ƈ不需?锁定那些你准备更新的数据?
假若对disconnect()和reconnect()的显式调用发生得太频J了(jin)Q你可以使用hibernate.connection.release_mode来代ѝ?
如果在用h考的q程中,Session因ؓ(f)太大?jin)而不能保存,那么q种模式是有 问题的。D例来_(d)一个HttpSession应该可能的。由?Session是一U缓存,q且保持?jin)所有被载入q的对象Q因?我们只应该在那些量的request/response情况下用这U策略。而且在这U情况下Q?Session 里面很快׃(x)有脏数据出现Q因此请牢牢Cq一?
此外Q也h意,你应该让?a target="_blank">数据?/a>q接断开的SessionҎ(gu)久层保持 关闭状态。换句话_(d)使用有状态的EJB session bean来持有SessionQ?而不要把它传递到web层(甚至把它序列化到一个单独的层)(j)Q保存在HttpSession中?

12.3.3.q对象(deatched object)和自动版本化
q种方式下,与持久化存储的每ơ交互都发生在一个新的Session中?然而,同一持久化对象实例可以在多次?a target="_blank">数据?/a>的交互中重用。应用程序操U脱对象实?的状态,q个q对象实例最初是在另一个Session 中蝲入的Q然?调用 Session.update()QSession.saveOrUpdate(), 或?Session.merge() 来重新关联该对象实例?




代码内容
// foo is an instance loaded by a previous Session
foo.setProperty("bar");
session = factory.openSession();
Transaction t = session.beginTransaction();
session.saveOrUpdate(foo); // Use merge() if "foo" might have been loaded already
t.commit();
session.close();

Hibernate?x)再一ơ在同步的时候检查对象实例的版本Q如果发生更新冲H,抛出异常?
如果你确信对象没有被修改q,你也可以调用lock() 来设|?LockMode.READQ绕q所有的~存Q执行版本检查)(j)Q从而取 ?update()操作?

12.3.4.定制自动版本化行?/strong>
对于特定的属性和集合Q通过为它们设|映属性optimistic-lock的?为falseQ来止Hibernate的版本自动增加。这L(fng)话,如果该属?脏数据,Hibernate不再增加版本号?
遗留pȝ?a target="_blank">数据?/a>Schema通常是静(rn)态的Q不可修改的。或者,其他应用E序也可能访问同一数据 库,Ҏ(gu)无法得知如何处理版本P甚至旉戟뀂在以上的所有场景中Q实现版本化不能依靠
数据?/a>表的某个特定列。在的映中讄 optimistic-lock="all"可以在没有版本或者时间戳属性映的情况下实?版本(g)查,此时Hibernate比较一行记录的每个字段的状态。请注意Q只有当Hibernate能够?较新旧状态的情况下,q种方式才能生效Q也是_(d) 你必M用单个长生命周期Session模式Q而不能?session-per-request-with-detached-objects模式?
有些情况下,只要更改不发生交错,q发修改也是允许的。当你在 的映中讄optimistic-lock="dirty"QHibernate在同步的时候将只比较有?数据的字Dc(din)?
在以上所有场景中Q不是专门讄一个版?旉戛_Q还是进行全部字D?脏数据字D|较, Hibernate都会(x)针对每个实体对象发送一条UPDATEQ带有相应的 WHERE语句 Q的SQL语句来执行版本检查和数据更新。如果你对关联实?讄U联关系使用传播性持久化Qtransitive persistenceQ,那么Hibernate可能?x)执行不?要的update语句。这通常不是个问题,但是
数据?/a>里面对on update点火 的触发器可能在脱对象没有Q何更改的情况下被触发。因此,你可以在 的映中Q通过讄select-before-update="true" 来定制这一行ؓ(f)Q强制Hibernate SELECTq个对象实例Q从而保证, 在更新记录之前,对象的确是被修改q?

12.4.(zhn)观锁定(Pessimistic Locking)
用户其实q不需要花很多_֊L?j)锁定策略的问题。通常情况下,只要为JDBCq接指定一下隔 ȝ别,然后?a target="_blank">数据?/a>L定一切就够了(jin)。然而,高用户有时候希望进行一个排它的(zhn)观锁定Q?或者在一个新的事务启动的时候,重新q行锁定?
HibernateL使用
数据?/a>的锁定机Ӟ从不在内存中锁定对象Q?
cLockMode 定义?jin)Hibernate所需的不同的锁定U别。一个锁?可以通过以下的机制来讄:
当Hibernate更新或者插入一行记录的时候,锁定U别自动讄为LockMode.WRITE?
当用h式的使用
数据?/a>支持的SQL格式SELECT ... FOR UPDATE 发送SQL的时候,锁定U别讄为LockMode.UPGRADE
当用h式的使用Oracle
数据?/a>的SQL语句SELECT ... FOR UPDATE NOWAIT 的时候,锁定U别讄LockMode.UPGRADE_NOWAIT
当Hibernate在“可重复诠Z或者是“序列化?a target="_blank">数据?/a>隔离U别下读取数据的时候,锁定模式 自动讄为LockMode.READ。这U模式也可以通过用户昑ּ指定q行讄?
LockMode.NONE 代表无需锁定。在Transactionl束Ӟ 所有的对象都切换到该模式上来。与session相关联的对象通过调用update() 或者saveOrUpdate()q该模式?
"昑ּ的用h?可以通过以下几种方式之一来表C?
调用 Session.load()的时候指定锁定模?LockMode)?
调用Session.lock()?
调用Query.setLockMode()?
如果在UPGRADE或者UPGRADE_NOWAIT锁定模式下调 用Session.load()Qƈ且要d的对象尚未被session载入q,那么对象 通过SELECT ... FOR UPDATEq样的SQL语句被蝲入。如果ؓ(f)一个对象调?load()Ҏ(gu)Ӟ该对象已l在另一个较?yu)限制的锁定模式下被载入了(jin),?么Hibernate对该对象调用lock() Ҏ(gu)?
如果指定的锁定模式是READ, UPGRADE ?UPGRADE_NOWAITQ那么Session.lock()?执行版本h查。(在UPGRADE 或者UPGRADE_NOWAIT 锁定模式下,执行SELECT ... FOR UPDATEq样的SQL语句。)(j)
如果
数据?/a>不支持用戯|的锁定模式QHibernate用适当的替代模式(而不是扔出异常)(j)?q一点可以确保应用程序的可移植性?


William 2006-06-30 21:33 发表评论
]]>
关于EasyDBO中事务管理的一些个?/title><link>http://www.tkk7.com/William/archive/2006/06/30/56031.html</link><dc:creator>William</dc:creator><author>William</author><pubDate>Fri, 30 Jun 2006 13:19:00 GMT</pubDate><guid>http://www.tkk7.com/William/archive/2006/06/30/56031.html</guid><wfw:comment>http://www.tkk7.com/William/comments/56031.html</wfw:comment><comments>http://www.tkk7.com/William/archive/2006/06/30/56031.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.tkk7.com/William/comments/commentRss/56031.html</wfw:commentRss><trackback:ping>http://www.tkk7.com/William/services/trackbacks/56031.html</trackback:ping><description><![CDATA[Ҏ(gu)据库的操作无外乎CRUDQ不是多大规模的数据库Q诏I数据库操作的全部过E的是数据库事务的理?br />一般情况下Q我们对数据库的操作基本上都是基于默认的事务理Q就是说每次执行后都是自动提交,当然Q?br />大部分的情况下这U操作可以正执行响应的业务要求Q但是对于一些业务数据要求比较严格的pȝ来说Q处<br />理好E序中事务将是一个非帔R要的内容?br /><br />对于目前EasyDBO中事务处理的一些看法,不知道对不对Q对q个研究不是很深入?br /><br />首先我们可以看到EasyDBO是线E安全的Q但是EasyJDBEngine是非U程安全的,每次实例话一个EasyDBO的时候,<br />都是重新实例化一个EasyJDBEngine。目前程序中通过EasyJDBEngine和DatabaseDAO实现的事务的支持Q但是觉?br />有一些地Ҏ(gu)妥,首先利用q个函数private void UpdateBatch(Vector vector)实现手动事务的提交,个h觉得<br />是没有真正利用到JDBC的事务管理功能,该函数只是简单的所有的操作攑ֈ一hl一执行Q当一ơ要求执行的<br />操作特别多的时候未免效率低下了(jin)?br /><br />另外一Ҏ(gu)觉得在事务管理方面没有真正利用JDBC的事务管理,JDBC事务理实际上是在JDBC Connection中实现的Q?br />事务周期仅限于Connection的生命周期内QJTA才真正实现的夸Connection的事务管理)(j)Q我们来看一个添加的函数<br /><br /> (tng)  (tng) public boolean add(DBObject obj) { // d一个对?br /> (tng)  (tng)  (tng)  (tng)DatabaseDAO dba = null; // 引入数据库操作工L(fng)<br /> (tng)  (tng)  (tng)  (tng)String sql = sqlQuery.getInsertSql(obj);<br /> (tng)  (tng)  (tng)  (tng)if (sql.equals("")) {<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)logger.error("I的sql语句无法执行!");<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)return false;<br /> (tng)  (tng)  (tng)  (tng)}<br /> (tng)  (tng)  (tng)  (tng)boolean ret = false;<br /> (tng)  (tng)  (tng)  (tng)try {<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)dba = getDatabaseDAO();<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)if (DBOConfig.getInstance().isShow_sql()) {<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)System.out.println("EasyDBO:" + sql);<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)}<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)dba.prepare(sql);<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)if (obj.getValue() != null) {<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)dba.setQueryParams(obj.getValue().values());<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)}<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)// todo : add piginzoo 加入事务支持<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)if (autoCommit == false) {<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)vec.add(dba.getPreparedStatement());<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)} else {<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)// rs = dba.preparedQuery();<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)ret = dba.isPreparedUpdate();<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)// dba.close();<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)}<br /> (tng)  (tng)  (tng)  (tng)} catch (Exception e) {<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)logger.error("d数据错误Q? + e + ":sql=" + sql);<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)e.printStackTrace();<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)if (dba != null) {<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)try {<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)dba.rollback();<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)// dba.close();<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)} catch (SQLException sqle) {<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)}<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)}<br /><br /> (tng)  (tng)  (tng)  (tng)} finally {<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)try {<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)dba.close();<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)} catch (Exception e) {<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)  (tng)logger.error("释放数据库资源错误:(x)" + e);<br /> (tng)  (tng)  (tng)  (tng)  (tng)  (tng)}<br /> (tng)  (tng)  (tng)  (tng)}<br /> (tng)  (tng)<br /> (tng)  (tng)  (tng)  (tng)return ret;<br /> (tng)  (tng)}<br /> (tng)  (tng)<br /> (tng)  (tng)  (tng)  (tng)<br /> (tng)  (tng)  (tng)  (tng)可以发现在一ơ的dl束以后Q连接被x?jin)dba.close();虽然q接没有被真正的xQ只是返回了(jin)q接池当中;<br /> (tng)  (tng)  (tng)  (tng)但是你肯定不能确定如果同一ơ执行多个操作的时候,能够利用的同一个ConnectionQ所以说JDBC的事务也无?br /> (tng)  (tng)  (tng)  (tng)说v?jin)?br /><br /> (tng)  (tng)  (tng)  (tng)当然我看到现在程序在实际应用中可能还没有真正利用到这个手动事务管理的功能Q但是我觉得q样设计事务好像<br /> (tng)  (tng)  (tng)  (tng)有点效率上的问题Q当然最重要的是没有真正利用到JDBC 的事务管理功能?<br /><img src ="http://www.tkk7.com/William/aggbug/56031.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.tkk7.com/William/" target="_blank">William</a> 2006-06-30 21:19 <a href="http://www.tkk7.com/William/archive/2006/06/30/56031.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.tkk7.com/" title="亚洲av成人片在线观看">亚洲av成人片在线观看</a> <div class="friend-links"> </div> </div> </footer> վ֩ģ壺 <a href="http://zgfxshop.com" target="_blank">Ů18ëƬëƬѹۿ</a>| <a href="http://chinacmk.com" target="_blank">պƵ</a>| <a href="http://14743592.com" target="_blank">뿴avվ</a>| <a href="http://43caopen.com" target="_blank">պ</a>| <a href="http://ydysmedia.com" target="_blank">޳ҹӰ</a>| <a href="http://4922000.com" target="_blank">ŮƵվ</a>| <a href="http://xsxdsb.com" target="_blank">ðѹۿվ</a>| <a href="http://16688shop.com" target="_blank">պѿվ</a>| <a href="http://kanboy.com" target="_blank">޳AƬ777777</a>| <a href="http://6atb.com" target="_blank">AV㽶һ</a>| <a href="http://www-33758.com" target="_blank">߹ۿ˳Ƶڵ</a>| <a href="http://szyujiaxing.com" target="_blank">þþƷһ糱</a>| <a href="http://www-75044.com" target="_blank">һɫþۺ޾Ʒ</a>| <a href="http://yytengsheng.com" target="_blank">ۺһ</a>| <a href="http://maomaots.com" target="_blank">Ƭѹۿ</a>| <a href="http://400209.com" target="_blank">ѧһëƬ</a>| <a href="http://628669.com" target="_blank">AVרAVëվ</a>| <a href="http://35469642.com" target="_blank">ɫɫBwwW</a>| <a href="http://www-33758.com" target="_blank">þùһ</a>| <a href="http://pumanpig.com" target="_blank">ĻһëƬ</a>| <a href="http://bjfljg.com" target="_blank">ŵ</a>| <a href="http://zgnyxx.com" target="_blank">ƬվɫƬѹۿcn </a>| <a href="http://zjtuntex.com" target="_blank">ðѹۿվ</a>| <a href="http://codecampo.com" target="_blank">Ƭѹۿ</a>| <a href="http://kt4444.com" target="_blank">ŮƵһ</a>| <a href="http://564ka.com" target="_blank">ƷСƵapp</a>| <a href="http://zgfxshop.com" target="_blank">ƵƷ</a>| <a href="http://zjj100.com" target="_blank">˳ӰԺ</a>| <a href="http://ryhjled.com" target="_blank">һþƵ</a>| <a href="http://54vpn.com" target="_blank">ѹۿɫƬ</a>| <a href="http://xjtuykw.com" target="_blank">ŮƵվ</a>| <a href="http://yaojing123.com" target="_blank">þѾƷƵ</a>| <a href="http://www5g9.com" target="_blank">޾Ʒ456</a>| <a href="http://w5524.com" target="_blank">ղһ</a>| <a href="http://ikybh.com" target="_blank">6080ҹһëƬѿ6080ҹ </a>| <a href="http://wwwfafa98.com" target="_blank">һƵѹۿ</a>| <a href="http://15831883389.com" target="_blank">޾ƷۺϾþ</a>| <a href="http://wwwse09.com" target="_blank">޹ۺAV߹ۿ</a>| <a href="http://maomi02.com" target="_blank">Ļ</a>| <a href="http://cz655.com" target="_blank">avŮӰ</a>| <a href="http://http99.com" target="_blank">߹ۿavվ</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>