spring--事务管理
目录
1.基本概念
2.事务管理三大接口
3.声明事务管理的两种配置
一、基本概念
事务(Transaction),是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。
事务是一系列的动作,它们综合在一起才是一个完整的工作单元,这些动作必须全部完成,如果有一个失败的话,那么事务就会回滚到最开始的状态,仿佛什么都没发生过一样。用来确保数据的完整性和一致性。
举一个例子:
如:从银行中取钱。第一步,输入密码和金额。从银行卡中扣除100元。第二步,从ATM中出100元。这两个步骤,要么全部执行完,要么都不执行。因为。如果,执行了第一步,不执行第二步,就会扣了钱。自己拿不到钱。如果,执行了第二步,不执行第一步。则银行会亏掉100元。显然这样的系统是不会被采纳的。
事务管理有四个特性:
(1) 原子性(Atomicity) : 事务是一个原子操作,由一系列动作组成。确保动作要么全部完成,要么完全不起作用。
(2) 一致性(Consistency) : 一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态。
(3) 隔离性(Isolation) : 许多事务会同时处理相同的数据,所以每个事务都应与其他事务隔离开,防止数据损坏。
(4) 持久性(Durability) :一旦事务完成,无论发生什么系统错误,它的结果都不会受到影响,这样就能从任何系统崩溃中恢复过来。通常情况下,事务的结果被写到持久化存储器中。
二、事务管理的三大接口
1、PlatformTransactionManager 事务管理器
因为spring并不是直接去管理事务的,而是通过事务管理接口org.springframework.transaction.PlatformTransactionManager,对其他平台提供对应的事务管理器。具体的事务管理器的机制由对应的各个平台去实现。如:jdbc、Hibernate平台。
接口中提供了三个方法:
(1) TransactionStatus getTransaction(TransactionDefinition definition)
事务管理通过TransactionDefinition参数来获取事务状态,来管理事务。
(2) void commit(TransactionStatus status) 根据状态提交。
(3) void rollback(TransactionStatus status) 根据状态回滚。
2、TransactionStatus 事务状态
用来记录事务的状态 该接口定义了一组方法,用来获取或判断事务的相应状态信息。

3、TransactionDefinition 基本事务属性的定义
接口PlatformTransactionManager通过getTransaction(TransactionDefinition definition)方法来得到事务,这个方法里面的参数是TransactionDefinition类,这个类就定义了一些基本的事务属性。事务属性可以理解成事务的基本配置,描述事务策略如何应用到方法上。
定义了五个方法和一些属性:(使用A事务传播给B事务为例)
1、传播行为:当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。
PROPAGATION_REQUIRED :required (必须),A有事务,B用A的,反之,B创建新的事务。
PROPAGATION_SUPPORTS :supports (支持),A有事务,B用A的,反之,B非事务执行。
PROPAGATION_MANDATORY :mandatory (强制),A有事务,B用A的,反之,B抛出异常。
PROPAGATION_REQUIRES_NEW :requires_new (必须为新),A有事务将A挂起,B创建新事务,反之,B创建新事务
PROPAGATION_NOT_SUPPORTED :not_supported(不支持) A有事务将A挂起,B非事务执行,反之,B非事务执行
PROPAGATION_NEVER :never (从不) A有事务,B抛出异常,反之,B非事务执行
PROPAGATION_NESTED :nested (嵌套) A和B底层采用保存点机制,形成嵌套事务
2、隔离级别:定义了一个事务可能受其他并发事务影响的程度。
当多个事务并发运行时,经常会操作相同的数据来完成任务。同时也引起了一下问题:
(1) 脏读 (Dirty reads) : 发生在一个事务读取了另一个事务改写但尚未提交的数据时。如果改写在稍后被回滚了,那么第一个事务获取的数据就是无效的。
(2) 不可重复读 (Nonrepeatable read) : 发生在一个事务执行相同的查询两次或两次以上,但每次都得到的数据是不同时。这通常是因为另一个并发事务在两次查询期间进行了更新。重点是对数据的修改数据。
(3) 幻读 (Phantom read) : 它发生在一个事务读取了几行数据,接着另一个并发事务插入了一些数据时。在随后的查询中,第一个事务就会发现多了一些原本不存在的记录。重点是对数据的新增或删除。
隔离级别的属性:
(1) ISOLATION_DEFAULT:使用后端数据库默认的隔离级别
(2) ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
(3) ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
(4) ISOLATION_SERIALIZABLE:最高的隔离级别,完全服从ACID的隔离级别,确保阻止脏读、不可重复读以及幻读,也是最慢的事务隔离级别,因为它通常是通过完全锁定事务相关的数据库表来实现的
3、只读 : 设置为是否只读事务。如果事务只对后端的数据库进行该操作,数据库可以利用事务的只读特性来应用它认为合适的优化措施
4、事务超时:事务不能运行太长的时间。因为事务可能涉及对后端数据库的锁定,长时间的事务,会对占用不必要的数据库资源。事务超时就像一个定时器,如果在规定的时间内事务没有执行完,那一样会自动回滚,而不是一直等待其运行结束。
5、回滚规则 :主要定义了哪些异常会导致事务回滚而哪些不会。默认情况下,事务只有遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚 。但是一样可以为检查型异常设置为像运行期异常一样的回滚。
三、声明事务的两种方法
1、基于xml的配置
主要是在applicationContext.xml配置文件上配置aop 自动生成代理,进行事务管理。
dao层的数据操作和service对数据操作的方法都定义好。主要改变的是spring的配置文件。
//数据库连接池 (这里使用c3p0)
<bean id="datasource" class="com.mchange.v2.c3p0.DriverManagerDataSource">
<property name="driverClass" value="com.mysql.jdbc.Driver" /> //连接驱动
<property name="jdbcUrl" value="jdbc:mysql:///chat" /> //数据库连接路径
<property name="user" value="root" /> //数据库设置的用户名
<property name="password" value="123"/> //设置的数据库密码
</bean>
//(1) 配置事务管理器。 (需要先连接配置好数据库连接池datasource)
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="datasource" /> //已经配置的数据库连接池 </bean> //(2) 配置事务通知 (使用一些属性进行设置需要事务管理的方法) <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <!-- 传播行为 使用扫描虚拟名的方法 --> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="insert*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="find*" propagation="SUPPORTS" read-only="true" /> <tx:method name="query*" propagation="SUPPORTS" read-only="true" /> <tx:method name="get*" propagation="SUPPORTS" read-only="true" /> <tx:method name="select*" propagation="SUPPORTS" read-only="true" /> </tx:attributes> </tx:advice> //(3) 配置切入点 <aop:config> <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.ssm.service.*.*(..))" /> //需要扫描的包路径 </aop:config>
2、基于aop注解配置
需要在applicationContext.xml配置文件上配置,并且还要在目标类或者目标方法中使用@Transactional并且设置属性。
如果注解在类上,那就是类里面的所有的方法都使用事务管理。
如果单独在方法上,那是具体的方法使用事务管理。
//(1) 配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="datasource" /> </bean>
//(2)将管理器交予spring<tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true"/>proxy-target-class为ture,就是使用cglib 代理

浙公网安备 33010602011771号