事务的基本原理:
Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行:
1,获取连接 Connection con = DriverManager.getConnection()
2,开启事务con.setAutoCommit(true/false);
3,执行insert,update,delete
4,提交事务/回滚事务 con.commit() / con.rollback();
5,关闭连接 conn.close();
使用Spring的事务管理功能后,我们不在关心2和4的代码,而是由Spirng 自动完成
1和5的代码交给数据库连接池完成
真正关心的也就只有3(hibernate,mybatis帮忙完成)
最后我们什么都不知道了
事务的特性(4个):
原子性(Atomicity):事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。
一致性(Consistency):一旦事务完成(不管成功还是失败),系统必须确保它所建模的业务处于一致的状态,而不会是部分完成部分失败。在现实中的数据不应该被破坏。
隔离性(Isolation):可能有许多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止数据损坏。
持久性(Durability):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,这样就能从任何系统崩溃中恢复过来。通常情况下,事务的结果被写到持久化存储器中。
接口:PlatformTransactionManager
抽象类:AbstractPlatformTransactionManager
具体实现类:
DataSourceTransactionManager(jdbc)
DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); con.commit(); |
HibernateTransactionManager(hibernate)
HibernateTransactionObject txObject = (HibernateTransactionObject) status.getTransaction(); Transaction tx = txObject.getSessionHolder().getTransaction(); tx.commit(); |
JpaTransactionManager(jpa)
JpaTransactionObject txObject = (JpaTransactionObject) status.getTransaction(); EntityTransaction tx = txObject.getEntityManagerHolder().getEntityManager().getTransaction(); tx.commit(); |
Spring为各个平台提供了统一事务管理器,但是具体的实现就是各个平台自己的事情了。
事务的传播行为(7个):
PROPAGATION_REQUIRED(默认)--支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。
PROPAGATION_SUPPORTS--支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY--支持当前事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW--新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED--以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER--以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。
嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。
事务的隔离级别(5个):
ISOLATION_DEFAULT(默认):使用数据库默认的事务隔离级别.
ISOLATION_READ_UNCOMMITTED(读未提交) :这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
ISOLATION_READ_COMMITTED(读已提交):保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据
ISOLATION_REPEATABLE_READ(可重复读):这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。
ISOLATION_SERIALIZABLE(串行化):这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。
Spring事务分为:编程式事务和声明式事务
编程式事务:就是自己在方法前后加上事务代码
声明式事务:通过配置方式实现
1, tx标签配置
2, @Transactional注解
事务的配置参数:
属性 | 必要 | 默认值 | 描述 |
name | 是 |
| 与事务属性关联的方法名。通配符(*)可以用来指定一批关联到相同的事务属性的方法。 如:'get*'、'handle*'、'on*Event'等等。 |
propagation | 不 | REQUIRED | 事务传播行为 |
isolation | 不 | DEFAULT | 事务隔离级别 |
timeout | 不 | -1 | 事务超时的时间(以秒为单位) |
read-only | 不 | false | 事务是否只读? |
rollback-for | 不 |
| 将被触发进行回滚的 Exception(s);以逗号分开。 |
no-rollback-for | 不 |
| 不 被触发进行回滚的 Exception(s);以逗号分开。 |
<tx:method name="save*" rollback-for="Exception"/>
<tx:method name="insert*" rollback-for="Exception"/>
<tx:method name="update*" rollback-for="Exception"/>
<tx:method name="remove*" rollback-for="Exception"/>
<tx:method name="delete*" rollback-for="Exception"/>
<tx:method name="batch*" rollback-for="Exception"/>
<tx:method name="cancel*" rollback-for="Exception"/>
<tx:method name="*" propagation="SUPPORTS" read-only="true"/>
<tx:method name="*" propagation="REQUIRED" read-only="true"/>
举例:
list(){}
save(){insert语句; int i=1/0;}
在list方法中调用this.save()方法,数据库是否插入成功?
在list方法中调用其他servier的save方法,数据库是否插入成功?
在save方法中使用了try cache,事务?
如果使用读写分离??
事务不起作用总结:
1, 查看表结构是否使用的InnoDB存储引擎
2, 是否在带事务的方法中捕获了异常
3, 扫描配置问题
在application.xml 中扫描需要排除@Controller
在servlet.xml中扫描只包含@Controller