事务的定义
事务就是指作为单个逻辑工作单元执行的一组数据操作,这些操作要么必须全部成功,要么必须全部失败,以保证数据的一致性和完整性。
事务具有ACID属性
原子性(Atomic):事务由一个或多个行为绑在一起组成,好像是一个单独的工作单元。原子性确保在事务中的所有操作要么都发生,要么都不发生。
一致性(Consistent):一旦一个事务结束了(不管成功与否),系统所处的状态和它的业务规则是一致的。即数据应当不会被破坏。
隔离性(Isolated):事务应该允许多个用户操作同一个数据,一个用户的操作不会和其他用户的操作相混淆。
持久性(Durable):一旦事务完成,事务的结果应该持久化。
事务的ACID特性是由关系数据库管理系统(RDBMS)来实现的。
1)数据库管理系统采用日志来保证事务的原子性、一致性和持久性。日志记录了事务对数据库所做的更新,如果某个事务在执行过程中发生错误,就可以根据日志,撤销事务对数据库已做的更新,使数据库退回到执行事务前的初始状态。
2)数据库管理系统采用锁机制来实现事务的隔离性。当多个事务同时更新数据库相同的数据时,只允许持有锁的事务能更新该数据,其他事务必须等待,直到前一个事务释放了锁,其他事务才有机会更新该数据。
数据库事务声明
数据库系统的客户程序只要向数据库系统声明了一个事务,数据库系统就会自动保证事务的ACID特性。在JDBC API中,java.sql.Connection类代表一个数据库连接。它提供了以下方法控制事务:
1. setAutoCommit(Boolean autoCommit):设置是否自动提交事务。
2. commit():提交事务。
3. rollback():撤销事务
JDBC API声明事务的示例代码如下:
- <span style="font-size: large;">Connection = null;
- PreparedStatement pstmt = null;
- try{
- con = DriverManager.getConnection(dbUrl, username, password);
- //设置手工提交事务模式
- con.setAutoCommit(false);
- pstmt = ……;
- pstmt.executeUpdate();
- //提交事务
- con.commit();
- }catch(Exception e){
- //事务回滚
- con.rollback();
- …..
- } finally{
- …….
- }</span>
Hibernate 是JDBC 的轻量级封装,本身并不具备事务管理能力。
在事务管理层, Hibernate将其委托给底层的JDBC或者JTA,只是将底层的JDBCTransaction或者JTATransaction进行封装一下,在外边套上Transaction和Session的外壳,以实现事务管理和调度功能。
1)Hibernate中使用JDBC事务
如果在Hibernate中使用JDBC事务,可以在hibernate.cfg.xml中指定Hibernate事务为JDBCTransaction。如果不进行配置,Hibernate会默认使用JDBC事务。代码如下
- <span style="font-size: large;"><span style="font-size: large;"><?xml version="1.0" encoding="utf-8" ?>
- <!DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
- <hibernate-configuration>
- <session-factory>
- <property name="hibernate.transaction.factory_class">
- org.hibernate.transaction.JDBCTransactionFactory
- </property>
- </session-factory>
- </hibernate-configuration></span></span>
基于JDBC的事务管理将事务管理委托给JDBC 进行处理无疑是最简单的实现方式,Hibernate 对于JDBC事务的封装也极为简单。
我们来看下面这段代码:
- <span style="font-size: large;"><span style="font-size: large;">Transaction tx=null;
- try{
- session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction(); //开启事务
- //执行持久化操作
- ……
- tx.commit(); //操作正常,提交事务
- }catch(RuntimeException e){
- if(tx!=null){
- tx.rollback();//操作过程中有一场,回滚事务
- throw e;//处理异常
- }
- }finally{
- session.close()
- } </span></span>
- <span style="font-size: large;"><span style="font-size: large;">Connection dbconn = getConnection();
- dbconn.setAutoCommit(false);
- ……
- dbconn.commit(); </span></span>
这也就是说,我们一开始从SessionFactory获得的session,其自动提交属性就已经被关闭(AutoCommit=false),下面的代码将不会对数据库产生任何效果:
- <span style="font-size: large;"><span style="font-size: large;">session = sessionFactory.openSession();
- session.save(user);
- session.close();
- session = sessionFactory.openSession();
- session.save(user);
- session.close(); </span></span>
- <span style="font-size: large;"><span style="font-size: large;">session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- session.save(user);
- tx.commit();
- session.close(); </span></span>
- <span style="font-size: large;"><span style="font-size: large;"><?xml version="1.0" encoding="utf-8" ?>
- <!DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
- <hibernate-configuration>
- <session-factory>
- <property name="hibernate.transaction.factory_class">
- org.hibernate.transaction.JTATransactionFactory
- </property>
- </session-factory>
- </hibernate-configuration></span></span>
- <span style="font-size: large;"><span style="font-size: large;">public class ClassA{
- public void saveUser(User user){
- session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- session.save(user);
- tx.commit();
- session.close();
- }
- }
- public class ClassB{
- public void saveOrder(Order order){
- session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- session.save(order);
- tx.commit();
- session.close();
- }
- }
- public class ClassC{
- public void save(){
- ……
- UserTransaction tx = new InitialContext().lookup(“……”);
- ClassA.save(user);
- ClassB.save(order);
- tx.commit();
- ……
- }
- }
- public class ClassA{
- public void saveUser(User user){
- session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- session.save(user);
- tx.commit();
- session.close();
- }
- }
- public class ClassB{
- public void saveOrder(Order order){
- session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- session.save(order);
- tx.commit();
- session.close();
- }
- }
- public class ClassC{
- public void save(){
- try{
- UserTransaction tx = (UserTransaction)new InitialContext().lookup(“java:comp/UserTransaction”);
- tx.begin();//开启JTA事务
- ClassA.save(user);
- ClassB.save(order);
- tx.commit();//操作正常,提交JTA事务
- }catch(RuntimeException e){
- tx.rollback();//操作异常,回滚JTA事务
- throw e;//异常处理
- }finally{
- }
- }
- }</span></span>
- <span style="font-size: large;"><span style="white-space: normal; font-size: 12px;"><span style="font-size: large;"><span style="font-size: large;"> </span></span><span style="white-space: pre;"><span style="font-size: large;"><span style="font-size: large;">public class ClassA{</span></span></span></span></span>
- <span style="font-size: large;"><span style="font-size: large;">public void save(TUser user){
- session = sessionFactory.openSession();
- session.save(user);
- session.close();
- }
- ……
- }
- public class ClassB{
- public void save (Order order){
- session = sessionFactory.openSession();
- session.save(order);
- session.close();
- }
- ……
- }
- public class ClassC{
- public void save(){
- ……
- UserTransaction tx = new InitialContext().lookup(“……”);
- classA.save(user);
- classB.save(order);
- tx.commit();
- ……
- }
- }
- public class ClassA{
- public void save(TUser user){
- session = sessionFactory.openSession();
- session.save(user);
- session.close();
- }
- ……
- }
- public class ClassB{
- public void save (Order order){
- session = sessionFactory.openSession();
- session.save(order);
- session.close();
- }
- ……
- }
- public class ClassC{
- public void save(){
- ……
- UserTransaction tx = new InitialContext().lookup(“……”);
- classA.save(user);
- classB.save(order);
- tx.commit();
- ……
- }
- }
- </span></span>
- <span style="font-size: large;"><span style="font-size: large;">/**
- * @ejb.interface-method
- * view-type="remote"
- *
- * @ejb.transaction type = "Required"
- **/
- public void save(){
- //EJB环境中,通过部署配置即可实现事务申明,而无需显式调用事务
- classA.save(user);
- classB.save(log);
- }//方法结束时,如果没有异常发生,则事务由EJB容器自动提交。</span></span>