Hibernate事务和并发控制
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{??? …….}
?????? Hibernate对JDBC进行了轻量级的对象封装,Hibernate本身在设计时并不具备事务处理功能,平时所用的Hibernate的事务,只是将底层的JDBCTransaction或者JTATransaction进行了一下封装,在外面套上Transaction和Session的外壳,其实底层都是通过委托底层的JDBC或JTA来实现事务的调度功能。2.2.???????<session-factory>……<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>……</session-factory>Hibernate 使用JDBC transaction处理方式如下所示: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();}?2.3.??????<session-factory>……<property name="hibernate.transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>……</session-factory>下面是一个实际应用的JTA示例:// BMT(bean管理事务) idiom with getCurrentSession()try {??? UserTransaction tx = (UserTransaction)new InitialContext()??????????????????????????? .lookup("java:comp/UserTransaction");???? tx.begin();???? // Do some work on Session bound to transaction??? factory.getCurrentSession().load(...);??? factory.getCurrentSession().persist(...);???? tx.commit();}catch (RuntimeException e) {??? tx.rollback();??? throw e; // or display error message}在CMT方式下,事务声明是在session bean的部署描述符中,而不需要编程。 因此,代码被简化为:// CMT idiomSession sess = factory.getCurrentSession();?// do some work...?3.?????? <session-factory><!-- 设置JDBC的隔离级别 --><property name="hibernate.connection.isolation">2</property></session-factory>设置之后,在开始一个事务之前,Hibernate将为从连接池中获得的JDBC连接设置级别。需要注意的是,在受管理环境中,如果Hibernate使用的数据库连接来自于应用服务器提供的数据源,Hibernate不会改变这些连接的事务隔离级别。在这种情况下,应该通过修改应用服务器的数据源配置来修改隔离级别。5.???package org.qiujy.domain.versionchecking;?import java.util.Date;?public class Product implements java.io.Serializable{?????? private Long id ;?????? /**package org.qiujy.domain.versionchecking;?import java.util.Date;?import org.hibernate.HibernateException;import org.hibernate.Session;import org.hibernate.Transaction;import org.qiujy.common.HibernateSessionFactory;?public class TestVersionChecking {???????????? public static void main(String[] args) {????????????? Product prod = new Product();????????????? prod.setName("IBM thinkPad T60");????????????? prod.setUnitCost(new Double(26000.00));????????????? prod.setDescription("笔记本电脑");????????????? prod.setPubTime(new Date());?????????????????????????? //test start.......????????????? Session session = HibernateSessionFactory.getSession();????????????? Transaction tx =null;????????????? try{???????????????????? tx =?session.beginTransaction();???????????????????????????????????????? session.save(prod);????????????? ? ????????????? ????? tx.commit();????????????? }catch(HibernateException e){???????????????????? if(tx != null){??????????????????????????? tx.rollback();???????????????????? }???????????????????? e.printStackTrace();????????????? }finally{???????????????????? HibernateSessionFactory.closeSession();????????????? }???????//进行更新 测试..????????????? prod.setDescription("新款的");?????????????????????????? Session session2 = HibernateSessionFactory.getSession();????????????? Transaction tx2 =null;????????????? try{???????????????????? tx2 =?session2.beginTransaction();???????????????????????????????????????? session2.update(prod);????????????? ?????????????? ????? tx2.commit();????????????? }catch(HibernateException e){???????????????????? if(tx2 != null){??????????????????????????? tx2.rollback();???????????????????? }???????????????????? e.printStackTrace();????????????? }finally{???????????????????? HibernateSessionFactory.closeSession();????????????? }?????? }}新增数据时产生的SQL是:insert into products (version, name, description, unitCost, pubTime)??? values(?, ?, ?, ?, ?)程序无需为Product对象的version属性显示赋值,当持久化一个Product对象时,Hibernate会自动为它赋初始值为0。更新数据时产生的SQL是:????update??????? products??? set??????? version=?,??????? name=?,??????? description=?,??????? unitCost=?,??????? pubTime=???? where??????? id=???????? and version=?当Hibernate更新一个Product对象,会根据它的id和version属性到相应的数据库表中定位匹配的记录,如果存在这条匹配的记录,就更新记录,并且把version字段的值加1。若找不到匹配的记录,此时Hibernate会抛出StaleObjectStateException。?需要注意的是,由于乐观锁定是使用系统中的程序来控制,而不是使用数据库中的锁定机制,因而如果有人故意自行更新版本信息来超过检查,则锁定机制就无效。所以建议把持久化类中的version的get方法设置为private的。5.1.2.???????使用时间戳(<timestamp>):跟版本检查的用法相似。不再多说。5.2.???????悲观锁(Pessimistic Locking):悲观锁假定当前事务操纵数据资源时,肯定还会有其他事务同时访问该数据资源,为了避免当前事务的操作受到干扰,先锁定资源。尽管悲观锁能够防止丢失更新和不可重复读这类并发问题,但是它影响并发性能,因此应该很谨慎地使用悲观锁。