一、事务
事务是一个非常重要的编程概念,使用事务,可以很简单地构造出可靠稳定的应用程序,尤其对那些需要进行并发数据访问的应用程序,事务更是重要的多。 使用事务,便可以利用事务的四个重要属性:ACID。 * 原子性( atomic):事务中包含的各项操作必须全部成功执行或者全部不执行。任何一项操作失败,将导致整个事务失败,其他已经执行的任务所作的数据操作都将被撤销,只有所有的操作全部成功,整个事务才算是成功完成。 * 一致性( consistent):保证了当事务结束后,系统状态是一致的。那么什么是一致的系统状态?例如,如果银行始终遵循着"银行账号必须保持正态平衡"的原则,那么银行系统的状态就是一致的。上面的转账例子中,在取钱的过程中,账户会出现负态平衡,在事务结束之后,系统又回到一致的状态。这样,系统的状态对于客户来说,始终是一致的。 * 隔离性( isolated):使得并发执行的事务,彼此无法看到对方的中间状态。保证了并发执行的事务顺序执行,而不会导致系统状态不一致。 * 持久性( durable):保证了事务完成后所作的改动都会被持久化,即使是发生灾难性的失败。可恢复性资源保存了一份事务日志,如果资源发生故障,可以通过日志来将数据重建起来。 二、事务界定 两种事务界定的模型 * 声明式事务界定 * 编程式事务界定 三、设计DAO时需要考虑的问题 * 事务要如何开始? * 事务应如何结束? * 哪一个对象将负责开始一个事务? * 哪一个对象将负责结束一个事务? * DAO是否要负责事务的开始和结束? * 应用程序是否需要通过多个DAO访问数据? * 事务涉及到一个DAO还是多个DAO? * 一个DAO是否调用另一个DA 的方法? 了解上述问题的答案将有助于选择最适合的DAO的事务界定策略。在DAO中有两种主要的界定事务的策略。一种方式是让DAO负责界定事务,另一种将事务界定交给调用这个DAO方法的对象处理。 如果选择了前一种方式,那么就将事务代码嵌入到DAO中。如果选择后一种方式,那么事务界定代码就是在DAO类外面。对于需要在一个事务中访问多个DAO的应用程序应该使用第二中策略。 四、事务界定两种实现方式 JTA事务和JDBC事务 1.JTA事务 JTA是一种不受实施限制的高层协议API,该协议API使应用程序和应用服务器可以访问事务。JTA属于全局事务,由应用服务器管理(Tomcat需要结合JOTM(Java Open Transaction Manager)来支持事务),使用JTA的同时需要使用JNDI。 JTA及其同门兄弟JTS为 J2EE 平台提供了分布式事务服务。一个分布式的事务涉及一个事务管理器和一个或者多个资源管理器。一个资源管理器是任何类型的持久性的数据存储。事务管理器负责协调所有事务参与者之间的通信。 JTA事务比JDBC事务功能更强。JDBC事务局限为一个数据库连接,而JTA事务可以有多个参与者。所有下列Java平台组件都可以参与JTA事务: * JDBC 连接 * JDO PersistenceManager 对象 * JMS 队列 * JMS 主题 * 企业 JavaBeans * 符合 J2EE 连接体系结构(J2EE Connector Architecture)规范的资源适配器 要用JTA进行事务界定,应用程序要调用javax.transaction.UserTransaction接口中的方法: * public void begin() * public void commit() * public void rollback() * public int getStatus() * public void setRollbackOnly() * public void setTransactionTimeout(int) [代码示例:JTA进行事务界定] import javax.transaction.*; import javax.naming.*; // ... InitialContext ctx = new InitialContext(); Object txObj = ctx.lookup("java:comp/UserTransaction"); UserTransaction utx = (UserTransaction) txObj; utx.begin(); // ... DataSource ds = obtainXADataSource(); Connection conn = ds.getConnection(); pstmt = conn.prepareStatement("Update MOVIES ..."); pstmt.setString(1, "Spinal Tap"); pstmt.executeUpdate(); // ... utx.commit(); // ... [/代码示例] 2.JDBC事务 JDBC事务受数据库的事务管理器控制。JDBC事务属于本地事务,它容易使用,但是存在缺点:它们不能用于多个事务性资源,也就是事务的范围局限于一个数据库连接,一个JDBC事务不能跨越多个数据库。另一个缺点是局部事务趋向于入侵式的编程模式。 JDBC事务是用Connection对象控制的。JDBC Connection接口( java.sql.Connection )提供了两种事务模式:自动提交和手工提交。java.sql.Connection 提供了以下控制事务的方法: * public void setAutoCommit(boolean) * public boolean getAutoCommit() * public void commit() * public void rollback() [代码示例:用JDBC API进行事务界定] import java.sql.*; import javax.sql.*; // ... DataSource ds = obtainDataSource(); Connection conn = ds.getConnection(); conn.setAutoCommit(false); // ... pstmt = conn.prepareStatement("Update MOVIES ..."); pstmt.setString(1, "The Great Escape"); pstmt.executeUpdate(); // ... conn.commit(); // ... [/代码示例] JDBC支持的四种事务隔离模式(transaction isolation mode)。 3.JTA和JDBC 用JTA界定事务,那么就需要有一个实现javax.sql.XADataSource、javax.sql.XAConnection和javax.sql.XAResource接口的JDBC驱动程序。一个实现了这些接口的驱动程序将可以参与JTA事务。一个XADataSource对象就是一个XAConnection对象的工厂。XAConnections是参与JTA事务的JDBC连接。 并需要用应用服务器的管理工具设置XADataSource。J2EE应用程序用JNDI查询数据源。一旦应用程序找到了数据源对象,它就调用javax.sql.DataSource.getConnection()以获得到数据库的连接。 XA连接与非XA连接不同。一定要记住XA连接参与了JTA事务。这意味着XA连接不支持JDBC的自动提交功能。同时,应用程序一定不要对XA连接调用java.sql.Connection.commit()或者java.sql.Connection.rollback()。相反,应用程序应该使用 UserTransaction.begin()、UserTransaction.commit()和UserTransaction.rollback() 。 三、Spring、Hibernate和iBatis 这三个框架都有通过JDBC事务界定的方式实现事务管理。但相比之下,Spring在事务管理方面是其中最成熟的。 1.Spring Spring Framework实际上是Expert One-on-One J2EE Design and Development一书中所阐述的设计思想的具体实现。 Spring Framework的功能非常多。包含AOP、ORM、DAO、Context、Web、MVC等几个部分组成。但其中最需要用的是AOP、ORM、Context。Context中,最重要的是Beanfactory,它能将接口与实现分开,非常强大。前AOP应用最成熟的还是在事务管理上。 2.Hibernate Spring框架已经提供了对Hibernate框架的良好支持,因此不再需要再头痛于Hibernate的session管理,事务管理等方面,这些Spring框架已经进行了很好的封装。 3.ibatis ibatis不熟悉,如果你对ibatis的事务管理比较熟悉,请告诉我<yejienihao@hotmail.com>如何ibatis的实现方式:) 四、推荐阅读 事务管理最佳实践全面解析 http://dev.csdn.net/author/shendl/7098537bcd8b436197cd7e959936a911.html 事务管理最佳实践多余的话之一 http://dev.csdn.net/author/shendl/4fe0df2717bd47d8b73b31a16f38d1bb.html 事务管理最佳实践多余的话之二 http://dev.csdn.net/author/shendl/7fc1c42ab0a6433eab061943bb380dcf.html 事务管理最佳实践多余的话之三 http://dev.csdn.net/author/shendl/f4f97546410a4653949ba8ae837c4383.html 集成 Hibernate,Spring,Struts Portlet 框架构建Portlet应用 http://www-128.ibm.com/developerworks/cn/websphere/library/techarticles/guorui/ 基于struts+spring+ibatis的轻量级J2EE开发 http://www-128.ibm.com/developerworks/cn/java/j-s-s-i/ 在Jstl+Spring+ibatis开发中应用事务管理经验总结 http://blog.donews.com/yarak/archive/2006/04/25/845534.aspx [附录1:参考文献] 使用Enterprise Bean处理事务, http://gceclub./staticcontent/html/sunone/app7/app7-dg-ejb/detrans.html ---- 事务服务浅析 http://www-128.ibm.com/developerworks/cn/java/l-transation/part1/ http://www-128.ibm.com/developerworks/cn/java/l-transation/part2/ ---- 高级DAO编程 http://www-128.ibm.com/developerworks/cn/java/j-dao/ ---- 基于JDBC的数据库连接池高效管理策略 http://www-128.ibm.com/developerworks/cn/java/l-jdbcperform/ ---- Spring 事务管理 http://www./reference2/html/transaction.html ---- 分析Hibernate的事务处理机制 http://www.yesky.com/255/1922255.shtml ---- 集成 Hibernate,Spring,Struts Portlet 框架构建Portlet应用 http://www-128.ibm.com/developerworks/cn/websphere/library/techarticles/guorui/ ---- 基于struts+spring+ibatis的轻量级J2EE开发 http://www-128.ibm.com/developerworks/cn/java/j-s-s-i/ ---- 在Jstl+Spring+ibatis开发中应用事务管理经验总结 http://blog.donews.com/yarak/archive/2006/04/25/845534.aspx ---- How to use JDBC and transactions in Tomcat with JOTM http://jotm./current/jotm/doc/howto-tomcat-jotm.html [附录2:缩写列表] DAO - Data Access Object JTA - Java Transaction API JTS - Java Transaction Service (Java事务服务) JDBC - Java Database Connectivity |
|