事务
1、事务:操作数据库中各种数据项的一个程序执行单元。
2、事务的特性:
- 原子性:事务是执行数据库一系列操作的最小单位,不可再分;
- 一致性:一个事务中的各项操作要么同时成功,要么同时失败;
- 隔离性:一个事务的操作不受其他事务的干扰;
- 持久性:事务一旦提交,不可回滚。
3、事务的并发操作可能出现的问题:
- 脏读:一个事务读取到了另一个事务已经更新但没有提交的数据;
- 不可重复读:一个事务在另一个事务的两次读取操作中间更新了数据;
- 幻读:一个事务在另一个事务的两次读取操作中间插入了数据。
4、事务隔离级别:
- Read uncommitted(读未提交):可能出现脏读、不可重复读和幻读。
- Read committed(读提交):可以避免脏读,但可能出现不可重复读和幻读。
- Repeatable read(重复读):可以避免脏读和不可重复读,但可能出现幻读。
- Serializable(序列化):可以避免脏读、不可重复读和幻读,但是并发性极低,一般很少使用。
Hibernate的事务管理
1、开启事务:Transaction ts = session.beginTransaction();
2、回滚事务:ts.rollBack();
3、提交事物:ts.commit();
4、事务隔离级别的配置:在hibernate.cfg.xml文件中配置
- 1:Read uncommitted isolation
- 2:Read committed isolation
- 4:Repeatable read isolation
- 8:Serializable isolation
<!--例:设置隔离级别为:Repeatable read isolation-->
<property name="hibernate.connection.isolation">4</property>
线程绑定Session
1、原因:事务通常是设置在service层的,因为dao层处理的都是一个一个的具体的对数据库的操作,如果为每一个操作都加一个事务管理是没有意义的,因为事务就是要保证多个操作的同时成功或失败。但是一个事务的每个操作都必须在同一个session 中,这就需要事务中dao层的每个方法获得的都是同一个session对象。
2、解决:使一个事务中dao层的每个方法获得同一个session对象,做法有两种:
- 1、将service层创建的session对象传递给事务中dao层的每个方法;
- 2、将service层的session对象绑定到ThreadLocal中,在dao层的每个方法中都从ThreadLocal获取session对象。由于事务中的每个操作都在同一个线程中,因此在该线程的任何地方获取的session对象都会是同一个。
3、Hibernate的的解决:Hibernate解决以上问题采用的是第二种方法,但是Hibernate是一个很完善的框架,它底层已经为我们绑定好了session对象,只需要调用SessionFactory的getCurrentSession()方法就能获得绑定好的session对象。但是,这么做还需要一个前提,就是在hibernate.cfg.xml文件中进行配置。
在Hibernate的配置文件中,用hibernate.current_session_context_class属性来指定管理session的方式,管理方式有以下几种:
- thread:Session对象的生命周期与本地线程绑定;
- jta:Session的生命周期与JTA事务绑定,用于跨数据库的事务管理;
- managed:Hibernate委托程序来管理Session对象的生命周期。
<!--例:Session对象的生命周期与本地线程绑定-->
<property name="hibernate.current_session_context_class">thread</property>