目录
一、事务概念
1.什么是事务?
事务是数据库操作最基本单元,逻辑上是一组操作,要么同时成功,要么同时失败
典型场景:银行转账
2.事务四大特性
1)原子性:是不可以分割的最小操作单位,要么同时成功,要么同时失败
2)一致性:事务前后,事务总量不变
3)持久性:当事务提交或回滚后,数据库会持久化保存数据
4)隔离性:多个事务间相互独立
3.事务的隔离级别
-
概念:多个事务之间隔离的,相互独立的。但如果多个事务操作同一批数据,则会引发一些问题,设置不同的隔离级别就可以解决这些问题
-
存在问题:
1. 脏读:一个事务,读取到另一个事务中没有提交的数据
2. 不可重复读(虚读):在同一个事务中,两次读取到的数据不一样
3. 幻读:一个事务操作(DML)数据表中所有记录,另一个事务添加了一条数据,则第一个事务查询不到自己的修改 -
隔离级别:
1. read uncommitted:读未提交
产生问题:脏读、不可重复读、幻读
2. read committed:读已提交(oracle默认)
产生问题:不可重复读、幻读
3. repeatable read :可重复读(mysql默认)
4. serialICable:串行话
解决所有问题 -
注意:隔离级别从小到大安全性越来越高,但是效率越来越低
二、事务管理操作(搭建环境)
1. Spring事务管理操作方式:
编程式事务控制和声明式事务控制。
注意:Spring声明式事务控制底层就是AOP
2.声明式事务管理
1)基于注解方式(常用)
2)基于xml方式
3.Spring事务管理API
提供一个接口,代表事务管理器,这个接口针对不同的框架提供不同的实现类
三、注解方式
1.在spring配置文件配置事务管理器
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"/>
</bean>
2.在spring配置文件,开启事务注解
1)在spring配置文件中引入名称空间
2)开启事务注解
<tx:annotation-driven transaction-manager="transactionManager"/>
3.具体操作
Dao层:创建两个方法
1)少钱方法 2)多钱方法
public interface UserDao {
public abstract void addMoney();
public abstract void reduceMoney();
}
@Repository
public class UserImpl implements UserDao {
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void addMoney() {
String sql = "update from account set money=money+? where name=?";
jdbcTemplate.update(sql,1000,"tom");
}
@Override
public void reduceMoney() {
String sql = "update from account set money=money-? where name=?";
jdbcTemplate.update(sql,1000,"lucy");
}
}
Service层:调用到两个方法,并添加事务注解@Transactional
@Service
@Transactional(isolation = Isolation.REPEATABLE_READ)
public class UserService {
@Autowired
private UserDao userDao;
public void accountMoney(){
userDao.reduceMoney();//lucy少1000
int a = 1/0; //制造异常
userDao.addMoney();//tom多1000
}
}
注意:
1)@Transactional,这个注解既可以添加到类上,也可以添加到方法上。
2)添加到类上面,这个里面所有的方法都添加事务。
3)添加到方法上,为这个方法添加事务。
4. @Transactional相关参数
1)propagation:事务传播行为
2)ioslation:事务隔离级别
3)timeout:超时时间
默认值是-1,没有超时限制。如果有,以秒为单位进行设置
4)readOnly:是否只读
建议查询时设置为只读
5)rollbackFor:回滚
设置出现哪些异常进行事务回滚
6)noRollbackFor:不回滚
四、XML声明式事务管理
1.在spring配置文件中进行配置
第一步:配置事务管理器
第二步:配置通知
第三步:配置切点和切面
<!--1.配置平台事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!--2.配置通知-->
<tx:advice id="txadvice">
<!--配置事务参数-->
<tx:attributes>
<!--制定哪种规则方法上面添加事务-->
<tx:method name="*" isolation="REPEATABLE_READ"/>
<!-- <tx:method name="accountMoney" isolation="REPEATABLE_READ"/> -->
</tx:attributes>
</tx:advice>
<!--3.配置切面-->
<aop:config>
<aop:pointcut id="pt" expression="execution(* spring.xml.service.UserService.accountMoney(..))"/>
<!--配置切面-->
<aop:advisor advice-ref="txadvice" pointcut-ref="pt"/>
</aop:config>
五、完全注解开发
@Configuration
@ComponentScan(basePackages = "spring.anno")
@EnableTransactionManagement()//开启事务
public class TxConfig {
//创建数据库连接池
@Bean
public DruidDataSource getDruidDataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///test");
dataSource.setUsername("root");
dataSource.setPassword("root");
return dataSource;
}
//创建JdbcTemplate对象
@Bean
public JdbcTemplate getJdbcTemplate(DataSource dataSource){
//到IOC容器中根据类型找到dataSource
JdbcTemplate jdbcTemplate = new JdbcTemplate();
//注入dataSource
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
//创建事务管理器
@Bean
public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}