事务是指作为单个逻辑工作单元执行一组数据操作,这些操作要么必须全部成功,要么必须全部失败,以保证数据的一致性和完整性。事务具有ACID属性:原子性(Atomic)、一致性(Consistent)、隔离性(Isolated)、持久性(Durable)。
数据库事务的ACID特性是由关系数据库管理系统(RDBMS)来实现的。数据库管理系统采用日志来保证食物的原子性、一致性和持久性。日志记录事务对数据库所做的更新,如果某个事务在执行过程中发生错误,就可以根据日志,撤销事务对数据库已做的更新,使数据库退回到执行事务前的初始状态。数据库管理系统采用锁机制来实现事务的隔离性。当多个事务同时更新数据库统一的数据时,只运行持有锁的事务能更新该数据,其他事物必须等待,直到当前一个事物释放了锁,其他事物才有机会更新该数据。
数据库系统的客户程序只要向数据库系统声明一个事务,数据库系统就会自动保证事务的ACID特性。
在JDBC API中,java.sql.Connection类代表一个数据库连接。它提供以下方法控制事务:
(1)setAutoCommit(Boolean autoCommit):设置是否自动提交事务
(2)commit():提交事务
(3)rollback():撤销事务
Hibernate对JDBC进行轻量级的对象封装,Hibernate本身在设计时并不具备事务处理功能,平时所用的Hibernate的事务,只是将底层的JDBCTransaction或者JTATransaction进行一下封装,在外面套上Transaction和Session的外壳,其实底层都是通过委托底层的JDBC或JTA来实现事务的调度功能。
(1)Hibernate中使用JDBC事务
要在Hibernate中使用JDBC事务,可以再hibernate.cfg.xml中指定Hibernate事务为JDBCTransaction。
注意:如果不进行配置,Hibernate会默认使用JDBC事务。
代码如下:
<hibernate-configuration>
<session-factory>
...
<property name="hibernate.transaction.factory_class">
org.hibernate.transaction.JDBCTransactionFactory
</property>
</session-factory>
</hibernate-configuration>
Hibernate使用JDBC transaction处理方式如下:
Transaction tx=null;
try{
tx=session.beginTransaction();//开启事务
//执行持久化操作
...
tx.commit();//操作正常结果,提交事务
}catch(RuntimeException e){
if(tx !=null) tx.rollback(); //操作过程有异常,回滚事务
throw e;//处理异常
}finally{
session.close();
}
(2)Hibernate中使用JTA事务
JTA(Java Transaction API)是事务服务的JavaEE解决方案。本质上,它是描述事务接口的JavaEE模型的一部分。
JTA具有3个接口:UserTransaction接口、TransactionManager接口和Transaction接口,这些接口共享公共的事务操作。UserTransaction能够执行事务划分和基本的事务操作,TransactionManager能够执行上下文管理。
JTA服务需要第三方的应用程序提供具体的实现,而JavaEE应用服务器都会提供JTA服务。因此要使用JTA事务服务,一般都需要把Hibernate应用程序部署到JavaEe应用服务器中使用,而且数据库的连接池要交给这个应用服务器来管理。
在一个具有多个数据库的系统中,可能一个程序将会调用几个数据库中的数据,需要一种分布事务,或者准备用JTA来管理Session的长事务,那么就需要使用JTATransaction。
在hibernate.cfg.xml中配置JTA事务管理如下:
<hibernate-configuration>
<session-factory>
...
<property name="hibernate.transaction.factory_class">
org.hibernate.transaction.JTATransactionFactory
</property>
</session-factory>
</hibernate-configuration>
一下代码掩饰JTA事务管理实例:
UserTransaction tx=null;
Session session1=null;
Session session2=null;
try{
//通过JNDI查找到JTA事物实例
tx=(UserTransaction) new InitialContext().lookup("java:comp/UserTransaction");
tx.begin();//开启JTA事务
//开始使用Session执行持久化操作
session1=SessionFactory1.getCurrentSession();
session2=SessionFactory2.getCurrentSession();
session1.load(...);
session2.save(...);
...
tx.commit();
}catch(RuntimeException e){
tx.rollback();
throw e;
}finally{
session1.close();
session2.close();
}