数据库事务必须具备ACID特征,ACID是Atomic(原子性)、Consistency(一致性)、Isoation(隔离性)、Durability(持久性)的缩写。 
原子性:指整个数据库事务是不可分割的工作单元。只有事务中所有的操作执行成功,才算整个事务成功 
一致性:数据库事务不能破坏关系数据的完整性及业务逻辑上的一致性 
隔离性:在并发环境下,当不同的事务同时操纵相同的数据时,每个事务都有各自的完整数据空间 
持久性:只要事务成功结束,他对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统之后,数据库还能恢复到事务成功结束时的状态 
事物的ACID特性是由关系数据库管理系统来实现的。数据库管理系统采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所做的更新,若某个事务在执行过程中发生错误,就可以根据日志撤销事务对数据库已做的更新,使数据库退回到执行事务前的初始状态。 
数据库管理系统采用所机制来实现事务的隔离性。当多个事务同时更新数据库中相同的数据时,只允许持有锁的事务能更新该数据,其它事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。 

数据库系统的客户程序只要向数据库系统声明了一个事务,数据库系统就会自动保证事务的ACID特性。声明事务包含以下几方面: 
事务的开始边界(BEGIN) 
事务的正常结束边界(COMMIT):提交事务,永久保存被事务更新后的数据库状态 
事务的异常结束边界(ROLLBACK):撤销事务,使数据库退回到执行事务前的初始状态 
数据库支持以下两种事务模式: 
自动提交模式:每个SQL语句都是一个独立的事务,当数据库系统执行完一个SQL语句后,会自动提交事务。 
手工提交模式:必须由数据库的客户程序显式指定事务开始边界和结束边界 

在MySQL中,数据库表分为3种类型:INNODB、BDB、MyISAM类型。其中INNODB和BDB类型的表是支持数据库事务的,而MyISAM类型的表是不支持事务的。 

对于java应用,声明事务有以下方式:直接通过JDBC API类声明JDBC事务;直接通过Hibernate API来声明JDBC事务;直接通过Hibernate API来声明JTA事务;直接通过JTA API来声明JTA事务。 

在mysql.exe程序中声明事务 
每启动一个mysql.exe程序,都会得到一个单独的数据库连接。每个数据库连接都有一个全局变量@@autocommit,表示当前的事0务模式,它有两个可选值:0:表示手工提交模式;1默认值,表示自动提交模式 
mysql> select @@autocommit 
mysql> set autocommit=0; 
在自动提交模式下运行事务: 
在自动提交模式下,每个SQL语句都是一个独立的事务。 
在手工提交模式下运行事务: 
在手工提交模式下,必须显式指定事务开始边界和结束边界:事务的开始边界:begin、提交事务:commit、撤销事务:rollback 
mysql > begin 
mysql > select * from ACCOUNTS 
mysql > commit 

Java应用通过JDBC API声明JDBC事务 
在JDBC API中,java.sql.Connection类代表一个数据库连接。Connection类提供了以下用于控制事务的方法: 
setAutoCommit(boolean autoCommit):设置是否自动提交事务 
commit():提交事务 
rollback():撤销事务 
可以通过setAtuoCommit(false)方法来设置手工提交事务模式,然后就可以把多条更新数据库的SQL语句作为一个事务,在所有操纵完成后调用commit()方法来整体提交事务,若一项SQL操作失败,则会抛出SQLException,此时,应在捕获异常的代码块中调用rollback()方法撤销事务。 

Java应用通过Hibernate API声明JDBC事务 
Hibernate冯各庄了JDBC API和JTA API,Java应用直接通过Hibernate API来声明事务,有两个有点:1.有利于跨平台开发 2.当应用程序通过Hibernate API声明事务时,事务与Session更加紧密地集成在一起。 
在Hibernate API中,Session和Transaction接口提供了一下声明事务边界的方法: 
声明事务的开始边界: 
Transaction tx = session.beginTransaction(); //为Session对象分配数据库连接,并且自动把这个连接设为手工提交事务模式。Hibernate底层实现会自动调用代表数据库连接的java.sql.Connection对象的setAutoCommit(false)方法。开始一个新的JDBC事务。Session的beginTransaction()方法返回的Transaction实例的类型是由Hibernate配置文件中的hibernate.transaction.factory_class事务工厂属性决定的,该属性的默认值为org.hibernate.transaction.JDBCTransactionFactory。 
JDBCTransactionFactory表示JDBC事务工厂,它负责创建JDBCTransaction类的实例。 
提交事务: 
tx.commit(); //在默认的情况下,Session采用自动清理缓存模式,在这种模式下,commit()方法会先自动调用Session的flush()方法清理缓存,即按照Session缓存中对象的变化去同步更新数据库;向底层数据库提交事务;释放Session占用的数据库连接 
撤销事务: 
tx.rollback(); //立即撤销事务,并且释放Session占用的数据库连接 

在Hibernate3以前的版本中,Hibernate抛出的异常都属于受检查异常(Checked Excpetion) 
,因此程序必须捕获并处理这种异常(JDBC API抛出异常都属于受检查异常)。但在多数情况下,Hibernate抛出的异常都是致命的。因此,从Hibernate3版本开始,Hibernate抛出的异常都是运行时异常。 
public void doWork(){ 
   Session session = factory.openSession(); 
   Transaction tx; 
   try{ 
      tx = session.beginTransaction(); 
      tx.setTimeout(5);  //设置事务超时时间 
      ... 
      tx.commit(); 
   }catch(RuntimeException e){ 
      if(tx==null){ 
         try{ 
             tx.rollback(); 
         }catch(RuntimeException ex){ 
             log.error("无法撤销事务",ex); 
         } 
      } 
     throw e; 
   }finally{ 
     try{ 
        session.close(); 
     }catch(RuntimeException ex){ 
        log.error("无法关闭Session",ex); 
     } 
   } 


一个Session可以对应多个事务,,但一个Session只允许有一个未提交的事务。 

Java应用通过Hibernate API声明JTA事务 
JTA事务主要运行在受管理环境中。与JDBC事务相比,JTA具有以下特点:由低层JTA实现来提供和管理数据库连接池。而对于JDBC事务,必须由Hibernate来管理数据库连接池;数据库连接池与JNDI绑定,应用程序可通过JNDI API来访问数据库连接池;在处理复杂的大事务方面,由JTA实现提供的数据库连接池更加健壮可靠,性能优越;通过JTA API来声明JTA事务时,支持分布式事务 ;JTA事务在运行时并不会产生额外的系统开销。对于非分布式的JTA事务,它和JDBC具有同样的运行效率。 
通过Hibernate API来声明JTA事务的步骤: 
在Hibernate配置文件中配置hibernate.connection.datasource属性、hibernate.transaction.factory_class属性和hibernate.transaction.manager_lookup_class属性 
#指定数据库连接池的JNDI 
hibernate.connection.datasource=java:comp/env/jdbc/SAMPLEDB 

#制定事务工厂 
hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory 
hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JbossTransactionManagerLookup 

JTA和JDBC在Hibernate内部实现的运行时行为有以下区别: 
对于JDBC事务,当事务开始时,Session被分配一个数据库连接,当事务结束时,Session就释放数据库连接;对于JTA事务,仅仅当执行完一个SQL语句时,Session才获得数据库连接,而SQL语句执行完毕后,Session就立刻释放数据库连接。JTA实现会保证同一个JTA事务中的所有SQL操作都是用同一个数据库连接。用org.hibernate.Transaction接口的setTimeout()方法来设定超时时间时,对于JDBC事务,实际上设定的是JDBC层的PreparedSatement执行SQL语句的超时时间;而对于JTA事务,JTA实现能够监控整个JTA事务是否超时,Transaction接口的setTimeout()方法与javax.transaction.UserTransaction接口的setTransactionTimeout()方法是等价的。 

Java应用通过JTA API声明JTA事务 
通过JTA API声明JTA事务的步骤如下: 
在Hibernate配置文件中配置hibernate.transaction.factory_class属性和hibernate.transaction.manager_lookup_class属性 
hibernate.transaction.factory_class=org.hibernate.transaction.JTATransactionFactory 
hibernate.transaction.manager_lookup_class=org.hibernate.transaction.JbossTransactionManagerLookup 
在程序中,通过JTA的javax.transaction.UserTransaction接口来声明JTA事务。 
UserTransaction utx = (UserTransaction)new InitialContext().lookup("UserTransaction"); 
Session session1 = null; 
Session session2 = null; 

try{ 
   utx.begin(); 

   session1 = sessionFactory.openSession(); 
   session2 = sessionFactory.openSession(); 
   .... 
   //默认情况下,UserTransaction的commit()方法提交事务时,不会自动清理缓存 
   session1.flush(); 
   session2.flush(); 

   uxt.commit();   

} }catch(RuntimeException e){ 
      if(tx==null){ 
         try{ 
             utx.rollback(); 
         }catch(RuntimeException ex){ 
             log.error("无法撤销事务",ex); 
         } 
      } 
     throw e; 
   }finally{ 
     try{ 
        session1.close(); 
        session2.close(); 
     }catch(RuntimeException ex){ 
        log.error("无法关闭Session",ex); 
     } 
   } 

若在Hibernate配置文件中设置以下两个属性时,则可不必手动清理缓存和关闭Session 
hibernate.transaction.flush_before_completion:若为true,在提交事务前自动清理缓存 
hibernate.transaction.auto_close_session:若为true,在提交或撤销事务后自动关闭Session