1.事务的ACID性
·原子性:事务是由一个活多个活动所组成的一个工作单元。院子想确保事务中的所有操作全部发生或全部不发生。
·一致性:一旦事务完成(不管是成功还是失败)系统必须确保它所建立的业务处理一致的状态。实现的数据不应该被损坏
·隔离性:事务允许多个用户对相同的数据进行操作,每个用户的操作不会与其他用户纠缠在一起。因此事务应该是被隔离的,避免发生同步读写相同数据的事情
·持久性:一旦事务完成,事务的结果应该持久化,这样就能从任何的系统崩溃中恢复过来。这一般会 涉及将结果存储到数据或其他形式的持久化存储中
2.选择事务管理器 (这里使用jdbc管理器)
·jdbc事务
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close" p:driverClassName="com.mysql.jdbc.Driver"
p:url="jdbc:mysql://127.0.0.1:3306/test" p:username="root" p:password="root"
p:maxActive="10" p:maxIdle="10">
</bean>
3.定义事务的属性。在Spring中声明式事务是通过事务属性来定义的。事务属性面熟了事务策略如何应用到方法上。事务属性包含了5个方面。传播行为,隔离级别,回滚原则,事务超时,是否只读
传播行为定义了客户端与被调用方法之间的事务边界,传播规则回到了,新的事务应该被启动还是被挂起,或者方法是否要在事务环境中运行。
隔离级别:
1.脏读:脏读放生在一个事务读取了另一个事务改写但是尚未提交的数据时。如果改写在稍后被回滚了,那么第一个失误获取的数据就是无效的。
2.不可重复读:发生在一个事务执行相同的查询两次或两次以上,但是每次都得到不同的数据时。这通常是因为另一个并发事务在两次查询期期间更新了数据
3.幻读:和不可重复读类似。他繁盛在一个事务读取了几行数据,接着另一个并发事务插入了一些数据时,在随后的查询中,第一个事务就会发现先多了一些原本不存在的记录
回滚规则:
默认情况下,事务只有在遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚。
但是可以声明事务在遇到特定的检查性异常时想遇到运行期异常那样回滚。同样,你还可可以声明事务遇到特定的异常不回滚,即使这些异常时运行期异常。
3.定义注解驱动的事务
applicationContext.xml中
<tx:annotation-driven transaction-manager="transactionManager"/>
<context:component-scan base-package="com.qunar.controller">
<context:exclude-filter type="annotation"
expression="org.springframework.stereotype.Controller" />
</context:component-scan>
表示不再扫面Controller包了 因为在我的xxx-servlet.xml中已经加载到容器,如果再次扫面 spring中cglib将不能产生代理
add方法 声明为事务 然后抛出异常看是否回滚
@RequestMapping(value = "/add", method = RequestMethod.GET)
@Transactional(propagation = Propagation.REQUIRED, readOnly = false)
public String add(User user) {
try {
userMapper.addUser(user);
throw new ClassCastException();
} catch (Exception e) {
e.printStackTrace();
}
return "login";
}
不知为何 ,事务老是不会滚,用的mysql 引擎为InnoDB 程序也没有报错,可是就是不能回滚,有待研究