11 &?amp;&的区别。?
&是位q算W?amp;&是布逻辑q算W。?
12 HashMap和Hashtable的区别。?
都属于Map接口的类Q实C惟一键映到特定的g。?
HashMap cL有分cL者排序。它允许一个 null 键和多个 null 倹{?
Hashtable cM于 HashMapQ但是不允许 null 键和 null 倹{它也比 HashMap 慢,因ؓ它是同步的?
13 Collection 和 Collections的区别。?
Collection是个java.util下的接口Q它是各U集合结构的父接口?
Collections是个java.util下的c,它包含有各种有关集合操作的静态方法。?
14 什么时候用assert。?
断言是一个包含布表辑ּ的语句,在执行这个语句时假定该表辑ּ为 true。?
如果表达式计ؓ falseQ那么系l会报告一个 Assertionerror。它用于调试目的Q?
assert(a > 0); // throws an Assertionerror if a <= 0
断言可以有两UŞ式:
assert Expression1 ;
assert Expression1 : Expression2 ;
Expression1 应该L产生一个布倹{?
Expression2 可以是得Z个值的L表达式。这个值用于生成显C更多调试?
信息的 String 消息。?
断言在默认情况下是禁用的。要在编译时启用断言Q需要用 source 1.4 标记Q?
javac -source 1.4 Test.java
要在q行时启用断aQ可使用 -enableassertions 或者?ea 标记。?
要在q行旉择用断言Q可使用 -da 或者?disableassertions 标记。?
要系l类中启用断aQ可使用 -esa 或者?dsa 标记。还可以在包的基上启用或者禁用断a。?
可以在预计正常情况下不会到达的Q何位|上攄断言。断a可以用于验证传递给U有Ҏ的参数。不q,断言不应该用于验证传递给公有Ҏ的参敎ͼ因ؓ不管是否启用了断aQ公有方法都必须查其参数。不q,既可以在公有Ҏ中,也可以在非公有方法中利用断言试后置条g。另外,断言不应该以M方式改变E序的状态。?
15 GC是什? Z么要有GC? (基础)。?
GC是垃圾收集器?a target="_blank">Java E序员不用担心内存管理,因ؓ垃圾攉器会自动q行理。要h垃圾攉Q可以调用下面的Ҏ之一Q?System.gc()
Runtime.getRuntime().gc()
16 String s = new String("xyz");创徏了几个String Object?
两个对象Q一个是“xyz?一个是指向“xyz”的引用对象s。?
17 Math.round(11.5){於多少? Math.round(-11.5){於多少?
Math.round(11.5)q回QlongQ?2QMath.round(-11.5)q回QlongQ?11;
18 short s1 = 1; s1 = s1 + 1;有什么错? short s1 = 1; s1 += 1;有什么错?
short s1 = 1; s1 = s1 + 1;有错Qs1是short型,s1+1是int?不能昑ּ转化为short型。可修改为s1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正确。?
19 sleep() 和 wait() 有什么区? 搞线E的最?
sleep()Ҏ是ɾU程停止一D|间的Ҏ。在sleep 旉间隔期满后,U程不一定立x复执行。这是因为在那个时刻Q其它线E可能正在运行而且没有被调度ؓ攑ּ执行Q除?a)“醒来”的U程h更高的优先 (b)正在q行的线E因为其它原因而阻塞。?
wait()是线E交互时Q如果线E对一个同步对象x 发出一个wait()调用Q该U程会暂停执行,被调对象q入{待状态,直到被唤醒或{待旉到。?
20 Java有没有goto?
Goto—java中的保留字,现在没有在java中用。?
21 数组有没有length()q个Ҏ? String有没有length()q个ҎQ?
数组没有length()q个ҎQ有length的属性。?
String有有length()q个Ҏ。?
22 Overload和Override的区别。Overloaded的方法是否可以改变返回值的cd?
Ҏ的重写Overriding和重载Overloading是Java多态性的不同表现。重写Overriding是父cM子类之间多态性的一U表玎ͼ重蝲Overloading是一个类中多态性的一U表现。如果在子类中定义某Ҏ与其父类有相同的名称和参敎ͼ我们说该Ҏ被重写?Overriding)。子cȝ对象使用q个ҎӞ调用子cM的定义,对它而言Q父cM的定义如同被“屏蔽”了。如果在一个类中定义了多个同名的方法,它们或有不同的参C数或有不同的参数cdQ则UCؓҎ的重?Overloading)。?
Overloaded的方法是可以改变q回值的cd。?br />23 Set里的元素是不能重复的Q那么用什么方法来区分重复与否? 是用==q是e
quals()? 它们有何区别?
Set里的元素是不能重复的Q那么用iterator()Ҏ来区分重复与否。equals(
)是判M个Set是否相等。 equals()?=Ҏ军_引用值是否指向同一对象equals()在类中被覆盖Qؓ的是当两个分ȝ对象的内容和cd盔R的话Q返回真倹{?
24最常见到的runtime exception。?
ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException,EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException,ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFORMatException, Secur
ityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException
25 error和exception有什么区?
error 表示恢复不是不可能但很困隄情况下的一U严重问题。比如说内存溢出。不可能指望E序能处理这L情况。?
exception 表示一U设计或实现问题。也是_它表C如果程序运行正常,从不会发生的情况。?
26 List, Set, Map是否l承自Collection接口?
ListQSet是?
Map不是
27 abstract class和interface有什么区?
声明Ҏ的存在而不d现它的类被叫做抽象类Qabstract classQ,它用于要创徏一个体现某些基本行为的c,qؓ该类声明ҎQ但不能在该cM实现该类的情c不能创建abstract cȝ实例。然而可以创Z个变量,其类型是一个抽象类Qƈ让它指向具体子类的一个实例。不能有抽象构造函数或抽象静态方法。Abstract cȝ子类为它们父cM的所有抽象方法提供实玎ͼ否则它们也是抽象cMؓ。取而代之,在子cM实现该方法。知道其行ؓ的其它类可以在类中实现这些方法。?
接口QinterfaceQ是抽象cȝ变体。在接口中,所有方法都是抽象的。多l承性可通过实现q样的接口而获得。接口中的所有方法都是抽象的Q没有一个有E序体。接口只可以定义static final成员变量。接口的实现与子cȝ|除了该实现类不能从接口定义中l承行ؓ。当cd现特D接口时Q它定义Q即程序体l予Q所有这U接口的Ҏ。然后,它可以在实现了该接口的类的Q何对象上调用接口的方法。由于有抽象c,它允怋用接口名作ؓ引用变量的类型。通常的动态联~将生效。引用可以{换到接口cd或从接口cd转换Qinstanceof q算W可以用来决定某对象的类是否实现了接口。?
28 abstract的method是否可同时是static,是否可同时是nativeQ是否可同时是synchronized?
都不q?
29 接口是否可承接? 抽象cL否可实现(implements)接口? 抽象cL否可l承实体c?concrete class)?
接口可以l承接口。抽象类可以实现(implements)接口Q抽象类可承实体类Q但前提是实体类必须有明的构造函数。?
30 启动一个线E是用run()q是start()?
启动一个线E是调用start()ҎQɾU程所代表的虚拟处理机处于可运行状态,q意味着它可以由JVM调度q执行。这q不意味着U程׃立即q行。run()Ҏ可以产生必须退出的标志来停止一个线E。?
31 构造器Constructor是否可被override?
构造器Constructor不能被承,因此不能重写OverridingQ但可以被重载Overloading。?
32 是否可以l承Stringc?
StringcLfinalcL不可以ѝ?
33 当一个线E进入一个对象的一个synchronizedҎ后,其它U程是否可进入此对象的其它方?
不能Q一个对象的一个synchronizedҎ只能׃个线E访问。?
33 try {}里有一个return语句Q那么紧跟在q个try后的finally {}里的code会不
会被执行Q什么时候被执行Q在return前还是后?
会执行,在return前执行。?
34 ~程? 用最有效率的Ҏ出2乘以8{於?
2 << 3
35 两个对象值相?x.equals(y) == true)Q但却可有不同的hash codeQ这句话对不?
不对Q有相同的hash code。?
36 当一个对象被当作参数传递到一个方法后Q此Ҏ可改变这个对象的属性,q 可q回变化后的l果Q那么这里到底是g递还是引用传?
是g递?a target="_blank">Java ~程语言只由g递参数。当一个对象实例作Z个参数被传递到Ҏ中时Q参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变Q但对象的引用是永远不会改变的。?
37 swtich是否能作用在byte上,是否能作用在long上,是否能作用在String?
switchQexpr1Q中Qexpr1是一个整数表辑ּ。因此传递给 switch 和 case 语句的参数应该是 int、 short、 char 或者 byte。long,string 都不能作用于swtich。?
38 Hashtable和HashMap
Hashtablel承自Dictionaryc,而HashMap是Java1.2引进的Map interface的一个实玊W?
HashMap允许null作ؓ一个entry的key或者valueQ而Hashtable不允?
q有是QHashMap把Hashtable的containsҎL了,Ҏcontainsvalue和containsKey。因为containsҎҎ让h引v误解?
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是Q在
多个U程讉KHashtableӞ不需要自׃ؓ它的Ҏ实现同步Q而HashMap必Mؓ之提供外同步。?
Hashtable和HashMap采用的hash/rehash法都大概一P所以性能不会有很大的差异?
作者:Jack Shirazi
开发通过ACID试的应用程?/em>
事务使得开发h员的工作变得单多了。通过在JDBC API和诸如Oracle9i的关pL据库中用事务功能,在更新多用户应用E序Ӟ你可以把数据遭破坏的可能性降到最低。然而,事务需要处理开销Q与免费事务应用E序Q更Ҏ被破坏)相比较,它会降低pȝ的性能。那么,当用事务时Q什么才是保持性能的最好方法?
最佳的性能调优是避免做那些没必要做的事情。事务处理是数据库的大量工作Q而且数据库默认地l护多种资源以确保事务具有ACIDQ原子性,一致性,隔离性和持箋性)属性(查看"ACID Transaction Properties"工具栏获取详l信息)。这些数据库资源理多个数据q发操作以及提交和回滚操作,从而保证ACID事务属性。如果你能减数据库的此cL作,将提高应用E序的性能。让我们看一些避免处理开销q提高事务性能的方法?/font>
自动提交模式
最大限度减事务开销的第一个方法是通过把多个操作移C个单一事务中来合ƈ事务。默认情况下QJDBCq接工作在自动提交模式下Q这意味着每个发送到数据库的操作都会作ؓ独立事务自动执行。在q种情况下,每个Statement.executeQ)Ҏ调用都如同由一条BEGIN TRANSACTION命o开始,q由一条COMMIT命ol束?
关闭自动提交模式q且明确定义事务需要进行大量额外的工作Q因Z必须手动d事务划分语句QCOMMIT和ROLLBACKQ。但是合q事务可以减性能开销Q特别是当你对你的系l进行~时。(下面?span class="bodycopy">"部分会涉及到合ƈ更新事务的技术细节。)在重负荷pȝ中,事务开销意义重大。开销低Q系l的可~性就好?/font>
单地使用Connection.setAutoCommit(false)命o来关闭自动提交模式?
JDBC APIq提供了一个Connection.getAutoCommit()Ҏ来返回当前的自动提交模式。当你关闭了自动提交模式Q你需要用两个事务划分方法:Connection.commit()和Connection.rollback()?
当h工控制事务时Q需要遵循以下几条原则:使事务尽可能保持短,不要在一个事务中包含很多操作使它们变得非常冗ѝ(使事务打开q保持行开锁状态,会媄响其他事务ƈ降低可~性。)然而,如果几项操作可以一Ҏ一地执行Q那么就把它们合q到一个事务中?
合ƈ操作可能需要在你的SQL语句中增加额外的条g逻辑Qƈ且可能需要时表。不这个开销Q合q事务会更加有效Q因为数据库可以在一个步骤内获得所有需要的锁,q在一个步骤内释放它们?
当自动提交模式没有关闭时Q它所引v的更多事务会产生更多的通信开销Q更多的锁定和释放时_以及与其他会话发生冲H的更大可能性?/font>
扚w更新
扚w更新单地说就是在一个事务和一个数据库调用中将多个DML语句Q例如插入、更新和删除Q发送到数据库。JDBC通过Statement.addBatch()和Statement.executeBatch()Ҏ支持q项功能。批量更新的技巧相当简单,在下文中会加以说明。记住关闭自动提交模式(保一个批处理作ؓ一个事务执行)Qƈ且当你完成后q一切后Q明提交批事务?/font>
清单 1 中的CZ使用了普通的JDBC Statement对象。另外,JDBC API提供了一个PreparedStatementc,它也可以用参数表CSQL语句?
此外Q当你用PreparedStatement 对象来代替Statement对象ӞOracle的JDBC批处理实施就可以得到优化。在Oracle JDBC中,Statement对象不会在一ơ网l传输中传送所有成批的SQL语句。由于这个限Ӟ当成批传送语句时可以使用PreparedStatement对象Q因为PreparedStatement在一ơ批处理中会传送所有的语句?
清单 2 l出了用参数语句和PreparedStatement对象的相同批处理技巧?
借助于所有批处理语句相同的查询计划,在PreparedStatement对象中利用参数语句数据库进一步优化批处理。如果没有参数设定,语句׃各不相同Q因而数据库׃能重复用查询计划?
虽然q种Ҏl常可以提高性能Q但应注意以下几点:处理开销与创建查询计划的联合导致第一ơ执行SQL语句时会比用普通Statement对象时运行得更慢Q而随后准备好的执行语句将会快很多。(开发h员经常把首次PreparedStatement批处理移动到应用E序中对旉要求低的部分加以执行。)使用PreparedStatement对象比使用Statement对象更有效,特别是当使用过50条语句的大批量处理时?br />
以上的示例用了JDBC规范所定义的标准批处理模式。Oracle的JDBC实施提供了一U可选择的批处理模式Q它使用了一U被UCOraclePreparedStatement.setExecuteBatch(int)的新Ҏ。在q种模式下,预设的语句被自动保存在客LQ直到语句的数量与setExecuteBatch(int)中的参数所定义?扚w?相等。这样一来,U篏的语句在一ơ传送中被发送到数据库。Oracle所推荐的这U模式在某些情况下会比标准的批处理模式更快。当使用它的时候,调整扚w值来优化你的应用E序中事务的性能。Oracle模式惟一需要注意的一ҎQ它不是标准?-它用官方JDBC规范所不支持的扩展功能?br />
事务被定义ؓ全有或全无操作。一个事务的ACID属性确保每件事情都发生在一个事务,如同在事务期间在数据库中没有发生其他操作。由此可见,Ҏ据库来说Q确保ACID属性有很多工作要做?/font>
JDBC Connection界面定义了五U事务隔ȝ别(在下面说明)。ƈ不是所有的数据库都支持所有的U别。例如,Oracle9i只支持TRANSACTION_READ_COMMITTED和TRANSACTION_ SERIALIZABLEq两个别?/font>
许多数据库,例如Oracle9iQ提供了其他事务U别支持。这些别不提供"真正?事务Q因为它们不完全W合ACID属性。然而,它们通过可接受的事务功能提供更好的性能Q因此它们对很多操作cd是非常有用的?/font>
在JDBC中定义的U别包括Q?
TRANSACTION_NONE。正式地ԌTRANSACTION_NONE不是一个有效的事务U别。根据java.sql Connection API文gQ这个别表CZ务是不被支持的,因此理论上说你不能用TRANSACTION_NONE作ؓ一个自变量赋给Connection.setTransactionIsolation()Ҏ。事实上Q虽然一些数据库实施了这个事务别,但是Oracle9i却没有实施?/font>
TRANSACTION_READ_UNCOMMITTED。这是最快的完全有效的事务别。它允许你读取其他还没有被提交到数据库的q发事务做出的修攏V这个API文g指出Q脏dQdirty readsQ、不可重复读取(non-repeatable readsQ和错误dQphantom readsQ都可以在这个事务别发生(参阅" 一些非ACID事务问题 "部分Q。这个别意在支持ACID?原子性(AtomicQ?部分Q在q个U别中,你的修改如果被提交,被认ؓ是同时发生的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别中,你的修改如果被提交,被认ؓ是同时发生的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改变了这个倹{API文g指出Q脏d和不可重复读取在q个事务U别中是被禁止的Q但是错误读取可以发生?
从技术上Ԍ数据库通过在被d或写入的行上加锁来实施这个别,q且保持锁定状态直C务结束。这防止了q些行被修改或删除,但是不能防止额外的行被添?-因此Q就可能产生错误d。Oracle9i不支持这个别?/span>
TRANSACTION_SERIALIZABLE。这是最慢的事务U别Q但是它完全与ACID兼容?单词可串行化QserializableQ?指的是ACID兼容Q其中你的事务被认ؓ在整体上已经发生Q就如同其他所有已提交的事务在q个事务之前或之后全部发生。换句话_事务被串行执行?/span>
脏读取、不可重复读取和错误d在TRANSACTION_SERIALIZABLEU别是全部被止的。从技术上Ԍ数据库通过锁定在事务中使用的表来实施这个别。Oracle9i支持q个U别Q正如每个与W合ACID的数据库那样Q?
开发通过ACID试的应用程?/em>
选择正确的?/font>
你可以通过使用Connection.setTransactionIsolation()Ҏ讑֮一个连接的事务U别。类似地Q你可以通过使用Connection.getTransactionIsolation()Ҏ获得q接的当前事务别。你可以通过使用DatabaseMetaData.supportsTransaction IsolationLevel()Ҏ定׃的数据库驱动E序所支持的事务别,?/font> 清单3 所C?/font>
事务U别高Q数量越多、限制性更强的锁就会被q用到数据库记录或者表中。同Ӟ更多的锁被运用到数据库和它们的覆盖面宽QQ意两个事务冲H的可能性就大?/font>
如果有一个冲H(例如两个事务试图获取同一个锁Q,W一个事务必会成功Q然而第二个事务被L直到W一个事务释放该锁(或者是试获取该锁的行时导致操作失败)?
更多的冲H发生时Q事务的执行速度会变慢Q因为它们将p更多的时间用于解军_H({待锁被释放Q?
最大限度地增加应用E序的可伸羃性需要^衡地理解事务执行Ҏ。一斚wQ你可以通过在事务中所执行的操作数量减到最来优化应用E序Q从而减了单个事务所p的时间。但是这样就增加了事务的L量,q可能增加冲H的风险。用批量操作,你可以最大限度地减少所执行事务的数量?
然而,q增加了单个事务的长度,也可能增加冲H的风险。在L一U情况下Q当你降低事务隔ȝ别时Q事务用的锁就少Q因此越不会引v性能的下降。这样做的风险是因ؓ没有使用完全W合ACID的事务,从而损׃功能性?/font>
如果你需要把事务执行旉减到最的话,在你的整个应用程序中使用一个事务别好像ƈ不是很理惟뀂在应用E序中查找读取查询,对于每个查询Q考虑在下? 一些非ACID事务问题 "部分列出的Q何问题是否会对给定数据的查询或数据更新模式生负面媄响。读取静态表Q或者只被读取它们的同一事务所更新的表Q可以安全地使用最低的事务U别。在那些不可能进行ƈ发更新的事务中,你可以安全、高效地使用诸如TRANSACTION_ READ_COMMITTEDq样的别?
当一个连接用了不完全符合ACID的TRANSATION_SERIALIZABLE事务U别Ӟ׃发生很多问题。下面的例子使用了一个名为table_sizes的表Q它有两个字D,tablename和tablesize。这个例子还使用了两个事务,T1和T2Q其中T1使用TRANSACTION_SERIALIZABLEU别?/font>
脏读取。当一个事务能发现一行中有未提交的更ҎQ就发生了一ơ脏d。如果另一个事务改变了一个|你的事务可以d那个改变的|但其他的事务回滚其事务Qɘq个值无效或成ؓ脏倹{例如,q里l出了当T2使用事务U别TRANSACTION_ READ_UNCOMMITTED时发生的情况Q其中记录ؓtablename=usersQtablesize=11?
|
|||
隔离U别 | 脏读? | 不可重复d | 错误插入 |
d未提交数?/font> | ?/font> | ?/font> | ?/font> |
d已提交数?/font> | ? | ?/font> | ?/font> |
可重复读? | ? | ? | ?/font> |
可串行化 | ? | ? | ? |
1. T1和T2启动它们的事务?br />2. T1记录更Cؓtablename=usersQtablesize=12?br />3. T2dT1未提交的修改Q读取记录tablename=userQtablesize=12Q因为T2的事务别意味着未提交的修改有时可以被读取?br />4. T1回滚事务Q因此tablename=users行中tablesize=11?br />5. T2仍有无效的记录|记录tablename=usersQtablesize=12。但是它可以通过脏表寸值工作,q且能在脏值的基础上成功地提交修改?/font>
不可重复d。当事务内一条记录在事务被两ơ读取而没有更新时Q就发生了不可重复读取,而且Q从两次d中可以看C同的l果。如果你的事务读取一个|q且另一事务提交了对q个值的一ơ修改(或删除了q条记录Q,然后你的事务便可以读取这个修改后的|或发现这条记录丢失)Q尽你的事务还没有提交或回滚。例如,q里l出了当T2使用事务U别TRANSACTION_READ_COMMITTED时发生的情况Q其中记录ؓtablename=usersQtablesize=11?
1. T1和T2启动它们的事务?br />2. T2d记录tablename=usersQtablesize=11?br />3. T1记录更Cؓtablename=usersQtablesize=12q提交修攏V?br />4. T2重新d记录tablename=usersQƈ且现在看到tablesize=12Q因为T2的事务别意味着其他事务提交的修改可以被看到Q尽T2q没有提交或回滚?/font>
错误d。当一个事务读取由另一个未提交的事务插入的一行时Q就发生了错误读取。如果另一事务一行插入到一个表里,当你的事务查询那个表时就能够d那条新记录,即其他的事务相l回滚。例如,q里l出了当T2使用事务U别TRANSACTION_REPEATABLE_READ时发生的情况Q其中记录ؓ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读取两条记录: tablename=usersQtablesize=11和tablename=groupsQtablesize=28?br />5. T1回滚事务Q因此记录tablename=goupsQtablesize=28不再存在于table_sizes表中?/font>
ҎT2被读取的数据集中所h的一条额外错误记录,T2可以成功地提交数据?/font>
?/font> ? 中,你会发现在每一个所允许的事仉ȝ别中发生事务问题的可能性列表?/font>
用户控制的事?/font>
在许多应用程序中Q用户在一个事务结束以前,必须执行一个明的动作Q比如点?定"?取消"Q。这些情况会D很多问题。例如,如果用户忘记了终止活动或者让zd保持未完成的状态,资源׃直在应用E序和数据库中保持开攄态,q可能会在ƈ发的zd和锁定的资源之间产生冲突Q降低了pȝ的性能。只有单一的用户应用程序或用户不共享资源的应用E序Q才不受q个问题的媄响?/font>
让用户处于一个JDBC事务控制下的主要解决Ҏ是用优化的事务。这些事务ؓ外部的JDBC事务更新攉信息Q然后用一U机制来查更新没有与其他M个可能在两者间已经被处理的更新发生冲突?/font>
查优化冲H的机制包括使用旉标记或更改计数器Q从期望状态检查区别。例如,当应用程序从用户输入攉用于更新的数据时Q数据可以作Z批包含时间标记的安全机制的SQL语句Q被发送到数据库,以确保数据库中的原始数据与最初用于客户应用程序的数据相同。一个成功的事务更新记录Q包括时间标讎ͼ昄了最q修改的数据。如果来自另一用户的更CɽW一个用L修改失效Q那么时间标记就会改变,q且当前事务需要被回滚而不是被提交。对于许多应用程序,中等E度的冲H事务是很少的,因此事务l常会成功完成?/font>
当一个事务失败时Q应用程序把所输入的数据提交给用户Q用户能够ҎD冲突的更改,做出必要的修改ƈ且重新提交?
其他斚w的考虑
来Q用JDBC3.0Ҏ的开发h员将在更多的Ҏ来优化事务。例如,Oracle9iW?版实施了几个JDBC3.0Ҏ,包括事务存储点(SavepointQ。存储点让你在一个事务中标记一个点q且回滚它,而不是回滚整个事务?
虽然q听h有些难以|信Q但存储点确实能够极大地减少性能开销。它们对性能的实际媄响将证明JDBC3.0会得到更q泛的支持,但不要过多用存储点或者避免在M关键性能代码部分它们放在一赗如果你实要用它们,必ȝ保尽可能C用Connection.release Savepoint(Savepoint)Ҏ释放它们的资源?/font>
当前QJDBC2.0支持跨越多个q接的分布式事务Qƈ且Oracle提供了一个ؓ分布式事务设计的W合业界XA规范的Java Transaction APIQJTAQ模块。ؓ分布式事务实施一个外部事务管理器的决定ƈ不是一件小事情Q然而,分布式事务比普通事务明显要慢,因ؓ它需要额外的通讯工作来协调多个数据库资源之间的连接。从Ua的性能观点来看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>
代码内容 session/transaction处理方式如下所C: //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(); } |
代码内容 // 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 idiom Session sess = factory.getCurrentSession(); // do some work ... |
代码内容 // 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 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(); |