Spring事务管理
在Spring进行事务管理操作有两种方式:
编程式事务管理和声明式事务管理
编程式事务管理:
即通过try-catch等直接编程方式管理事务
1.开启事务 2.业务操作 3.没有异常则提交事务,有异常则回滚事务
声明式事务管理
1.基于注解方式
2.基于 xml 配置文件方式
在 Spring 进行声明式事务管理,底层使用 AOP 原理
**使用注解@Transactional
**配置事务
Transaction参数
- propagation:事务传播行为
多个事务直接进行调用的管理过程
- ioslation:事务隔离级别
事务的特性称为隔离性,多个事务操作不会产生影响
三个读问题:脏读、不可重复读、虚读
- 脏读:一个未提交的事务读取到另一个未提交的事务的数据
- 不可重复读:一个未提交事务读取到另一个提交事务修改数据
- 虚读:一个未提交事务读取到另一提交事务添加数据
通过设置事务隔离级别解决读问题
- timeout:超时时间
1.事务需要在一定时间内进行提交,如果不提交进行回滚
2.默认值是 -1 ,设置时间以秒单位进行计算
- readOnly:是否只读
1.读:查询操作,写:添加修改删除操作
2.readOnly 默认值 false,表示可以查询,可以添加修改删除操作
3.设置 readOnly 值是 true,设置成 true 之后,只能查询
- rollbackFor:回滚
- noRollbackFor:不回滚
举例
以银行转账服务作为事务的例子。张三李四之间进行转账
初始账户余额
现,张三向李四转账100元
<!-- 组件扫描 -->
<context:component-scan base-package="affair"></context:component-scan>
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
<property name="url" value="jdbc:mysql://localhost:3306/mydatabase?serverTimezone=UTC&
useUnicode=true&characterEncoding=UTF-8&useSSL=false"/>
<property name="username" value="root"/>
<property name="password" value="******"/>
<property name="driverClassName" value="com.mysql.jdbc.Driver"/>
</bean>
<!-- JdbcTemplate 对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<!--注入 dataSource-->
<property name="dataSource" ref="dataSource"></property>
</bean>
public interface AccountDAO {
public void addMoney();
public void delMoney();
}
@Repository
public class AccountDAOImpl implements AccountDAO {
//注入JdbcTemplate
@Autowired
private JdbcTemplate jdbcTemplate;
@Override
public void addMoney() {
String sql = "update bank set money=money-? where id=?";
int update = jdbcTemplate.update(sql, 100, 1);
System.out.println(update);
}
@Override
public void delMoney() {
String sql = "update bank set money=money+? where id=?";
int update = jdbcTemplate.update(sql, 100, 2);
System.out.println(update);
}
}
@Service
public class AccountService {
//注入dao
@Autowired
private AccountDAO accountDAO;
public void accountMoney() {
accountDAO.delMoney();
accountDAO.addMoney();
}
}
public class moneyTest {
@Test
public void test() {
ApplicationContext context = new ClassPathXmlApplicationContext("affairs.xml");
AccountService accountService = context.getBean("accountService", AccountService.class);
accountService.accountMoney();
}
}
结果:
如果在张三-100后抛出一个异常,那么就会出现问题:张三-100,而李四账户没有变化。
解决:
1.在xml文件中配置事务管理器并开启事务管理
<!--事务管理器-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--注入数据源-->
<property name="dataSource" ref="dataSource"></property>
</bean>
<!--开启事务注解-->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
2.在service文件中加入事务管理注解@Transactional
结果: