ACID(事务的基本要素):
原子性(atomic):事务操作的最小单位,要么全成功要么全失败,如果全失败,就会回滚到操作前的样子
一致性(consistency):一个操作(增删改)前后,总的数据不变(转帐前双方卡余额加起来是多少转账后加起来还是多少)
易错:一般都是并发导致的(多线程),所以功能上线前,都要做系统压力测试-
脏读:查询数据库查到了别人操作后未提交的数据
幻读:两次读取的结果不同,其中有一次读到了别人新增的数据
不可重复读:两次读取的结果不同,侧重于一次读到了别人修改的数据
每种数据库都有自己的解决方案,数据库回根据自身设置的隔离级别来控制/避免出现以上问题(mysql默认的事务隔离级别为repeatable-read)
隔离性(isolation):一个操作中的增删改不受别的方法中的增删改的影响
持久性(Persistence):把数据进行持久化,保存到具体的位置
Spring传播机制
PROPAGATION_REQUIRED
PROPAGATION_REQUIRES_NEW
PROPAGATION_SUPPORTIS
PROPAGATION_MANDATORY
PROPAGATION_NESTED
PROPAGATION_NEVER
PROPAGATION_NOT_SUPPORTED
@Override
public boolean transfer(String from, String to, Double amount) {
//先转出
boolean f = mapper.from(from, amount);
if (f) {
int a=3;
//设置异常
a/=0;
return mapper.to(to, amount);
}
return f;
}
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
AccountService bean = context.getBean("accountService", AccountService.class);
System.out.println(bean.transfer("张三", "李四", 100d));
}
如果在spring核心配置文件中加入事务
<!--事务,无论是xml事务还是注解事务都需要该配置-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--spring事务本质是用到了spring aop-->
<!-- 编写通知:对事务进行增强(通知),需要编写对切入点和具体执行事务细节 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!--
为切入点方法添加事务详情
name:方法名,*表示任意方法名称
propagation:设置传播行为
isolation:设置隔离级别
read-only:是否只读
-->
<tx:method name="transfer" isolation="REPEATABLE_READ" propagation="REQUIRED"/>
<tx:method name="trans*"/>
<tx:method name="add*"/>
<tx:method name="update*"/>
<tx:method name="*"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="p1" expression="execution(
* sm.hp.service.impl.AccountServiceImpl.transfer(..)
)"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="p1"/>
</aop:config>
数据库中的数据则不会发生变化