11 (tng) (tng) (tng)&?amp;&的区别。?
&是位q算W?amp;&是布?yu)(dng)逻辑q算W。?
12 (tng) (tng)HashMap和Hashtable的区别。?
都属于Map接口的类Q实C(jin)惟一键映到特定的g。?
HashMap (tng)cL有分cL者排序。它允许一个?tng)null (tng)键和多个 (tng)null (tng)倹{?
Hashtable (tng)cM于?tng)HashMapQ但是不允许 (tng)null (tng)键和 (tng)null (tng)倹{它也比 (tng)HashMap (tng)慢,因ؓ(f)它是同步的?
13 (tng)Collection (tng)和?tng)Collections的区别。?
(tng) (tng) (tng) (tng)Collection是个java.util下的接口Q它是各U集合结构的父接口?
Collections是个java.util下的c,它包含有各种有关集合操作的静(rn)态方法。?
14 (tng)什么时候用assert。?
断言是一个包含布?yu)(dng)表辑ּ的语句,在执行这个语句时假定该表辑ּ为 (tng)true。?
如果表达式计ؓ(f) (tng)falseQ那么系l会(x)报告一个?tng)Assertionerror。它用于调试目的Q?
assert(a (tng)> (tng)0); (tng)// (tng)throws (tng)an (tng)Assertionerror (tng)if (tng)a (tng)<= (tng)0 (tng)
断言可以有两UŞ式:(x) (tng)
assert (tng)Expression1 (tng); (tng)
assert (tng)Expression1 (tng): (tng)Expression2 (tng); (tng)
Expression1 (tng)应该L产生一个布?yu)(dng)倹{?
Expression2 (tng)可以是得Z个值的L表达式。这个值用于生成显C更多调试?
信息的?tng)String (tng)消息。?
断言在默认情况下是禁用的。要在编译时启用断言Q需要用?tng)source (tng)1.4 (tng)标记Q?
javac (tng)-source (tng)1.4 (tng)Test.java (tng)
要在q行时启用断aQ可使用 (tng)-enableassertions (tng)或者?ea (tng)标记。?
要在q行旉择用断言Q可使用 (tng)-da (tng)或者?disableassertions (tng)标记。?
要系l类中启用断aQ可使用 (tng)-esa (tng)或者?dsa (tng)标记。还可以在包的基上启用或者禁用断a。?
可以在预计正常情况下不会(x)到达的Q何位|上攄断言。断a可以用于验证传递给U有Ҏ(gu)的参数。不q,断言不应该用于验证传递给公有Ҏ(gu)的参敎ͼ因ؓ(f)不管是否启用?jin)断aQ公有方法都必须(g)查其参数。不q,既可以在公有Ҏ(gu)中,也可以在非公有方法中利用断言试后置条g。另外,断言不应该以M方式改变E序的状态。?
15 (tng)GC是什? (tng)Z么要有GC? (tng)(基础)。?
GC是垃圾收集器?a target="_blank">Java (tng)E序员不用担?j)内存管理,因?f)垃圾攉器会(x)自动q行理。要h垃圾攉Q可以调用下面的Ҏ(gu)之一Q?System.gc() (tng)
Runtime.getRuntime().gc() (tng)
16 (tng)String (tng)s (tng)= (tng)new (tng)String("xyz");创徏?jin)几个String (tng)Object? (tng)
两个对象Q一个是“xyz?一个是指向“xyz”的引用对象s。?
17 (tng)Math.round(11.5){於多少? (tng)Math.round(-11.5){於多少? (tng)
Math.round(11.5)q回QlongQ?2QMath.round(-11.5)q回QlongQ?11; (tng)
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)
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正确。?
19 (tng)sleep() (tng)和?tng)wait() (tng)有什么区? (tng)搞线E的最?
sleep()Ҏ(gu)是ɾU程停止一D|间的Ҏ(gu)。在sleep (tng)旉间隔期满后,U程不一定立x复执行。这是因为在那个时刻Q其它线E可能正在运行而且没有被调度ؓ(f)攑ּ执行Q除?a)“醒来”的U程h更高的优先 (tng)(b)正在q行的线E因为其它原因而阻塞。?
wait()是线E交互时Q如果线E对一个同步对象x (tng)发出一个wait()调用Q该U程?x)暂停执行,被调对象q入{待状态,直到被唤醒或{待旉到。?
20 (tng)Java有没有goto? (tng)
Goto—java中的保留字,现在没有在java中用。?
21 (tng)数组有没有length()q个Ҏ(gu)? (tng)String有没有length()q个Ҏ(gu)Q?
数组没有length()q个Ҏ(gu)Q有length的属性。?
String有有length()q个Ҏ(gu)。?
22 (tng)Overload和Override的区别。Overloaded的方法是否可以改变返回值的cd? (tng)
Ҏ(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)。?
Overloaded的方法是可以改变q回值的cd。?br />23 (tng)Set里的元素是不能重复的Q那么用什么方法来区分重复与否? (tng)是用==q是e (tng)
quals()? (tng)它们有何区别? (tng)
Set里的元素是不能重复的Q那么用iterator()Ҏ(gu)来区分重复与否。equals( (tng)
)是判M个Set是否相等。?tng)equals()?=Ҏ(gu)军_引用值是否指向同一对象equals()在类中被覆盖Qؓ(f)的是当两个分ȝ对象的内容和cd盔R的话Q返回真倹{?
24最常见到的runtime (tng)exception。?
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)
ityException, (tng)SystemException, (tng)UndeclaredThrowableException, (tng)UnmodifiableSetException, (tng)UnsupportedOperationException (tng)
25 (tng)error和exception有什么区? (tng)
error (tng)表示恢复不是不可能但很困隄情况下的一U严重问题。比如说内存溢出。不可能指望E序能处理这L(fng)情况。?
exception (tng)表示一U设计或实现问题。也是_(d)它表C如果程序运行正常,从不?x)发生的情况。?
26 (tng)List, (tng)Set, (tng)Map是否l承自Collection接口? (tng)
(tng) (tng) (tng) (tng) (tng)ListQSet是?
(tng) (tng) (tng) (tng) (tng)Map不是 (tng)
27 (tng)abstract (tng)class和interface有什么区? (tng)
声明Ҏ(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)的其它类可以在类中实现这些方法。?
接口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)接口。?
28 (tng)abstract的method是否可同时是static,是否可同时是nativeQ是否可同时是synchronized? (tng)
都不q?
29 (tng)接口是否可承接? (tng)抽象cL否可实现(implements)接口? (tng)抽象cL否可l承实体c?concrete (tng)class)? (tng)
接口可以l承接口。抽象类可以实现(implements)接口Q抽象类可承实体类Q但前提是实体类必须有明的构造函数。?
30 (tng)启动一个线E是用run()q是start()? (tng)
启动一个线E是调用start()Ҏ(gu)QɾU程所代表的虚拟处理机处于可运行状态,q意味着它可以由JVM调度q执行。这q不意味着U程׃(x)立即q行。run()Ҏ(gu)可以产生必须退出的标志来停止一个线E。?
31 (tng)构造器Constructor是否可被override? (tng)
构造器Constructor不能被承,因此不能重写OverridingQ但可以被重载Overloading。?
32 (tng)是否可以l承Stringc? (tng)
StringcLfinalcL不可以ѝ?
33 (tng)当一个线E进入一个对象的一个synchronizedҎ(gu)后,其它U程是否可进入此对象的其它方? (tng)
不能Q一个对象的一个synchronizedҎ(gu)只能׃个线E访问。?
33 (tng) (tng)try (tng){}里有一个return语句Q那么紧跟在q个try后的finally (tng){}里的code?x)不?tng)
?x)被执行Q什么时候被执行Q在return前还是后? (tng)
?x)执行,在return前执行。?
34 (tng)~程? (tng)用最有效率的Ҏ(gu)出2乘以8{於? (tng)
2 (tng)<< (tng)3 (tng)
35 (tng)两个对象值相?x.equals(y) (tng)== (tng)true)Q但却可有不同的hash (tng)codeQ这句话对不? (tng)
不对Q有相同的hash (tng)code。?
36 (tng) (tng)当一个对象被当作参数传递到一个方法后Q此Ҏ(gu)可改变这个对象的属性,q?tng)可q回变化后的l果Q那么这里到底是g递还是引用传? (tng)
是g递?a target="_blank">Java (tng)~程语言只由g递参数。当一个对象实例作Z个参数被传递到Ҏ(gu)中时Q参数的值就是对该对象的引用。对象的内容可以在被调用的方法中改变Q但对象的引用是永远不会(x)改变的。?
37 (tng) (tng)swtich是否能作用在byte上,是否能作用在long上,是否能作用在String? (tng)
switchQexpr1Q中Qexpr1是一个整数表辑ּ。因此传递给 (tng)switch (tng)和?tng)case (tng)语句的参数应该是 (tng)int、?tng)short、?tng)char (tng)或者?tng)byte。long,string (tng)都不能作用于swtich。?
38 Hashtable和HashMap (tng)
Hashtablel承自Dictionaryc,而HashMap是Java1.2引进的Map (tng)interface的一个实玊W?
HashMap允许null作ؓ(f)一个entry的key或者valueQ而Hashtable不允?
q有是QHashMap把Hashtable的containsҎ(gu)L?jin),?gu)containsvalue和containsKey。因为containsҎ(gu)Ҏ(gu)让h引v误解?
最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是Q在
多个U程讉KHashtableӞ不需要自׃ؓ(f)它的Ҏ(gu)实现同步Q而HashMap必Mؓ(f)之提供外同步。?
Hashtable和HashMap采用的hash/rehash法都大概一P所以性能不会(x)有很大的差异?
作者:(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 />
事务被定义ؓ(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>
脏读取、不可重复读取和错误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样的别?
当一个连接用了(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?
|
|||
隔离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>
代码内容 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(); } |
代码内容 // 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(); |