声明式事务
指使用注解或 XML 配置的方式来控制事务的提交和回滚
Spring声明式事务准备工作
1. 配置环境
<!-- 声明式事务依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>5.3.22</version>
</dependency>
<!--AOP-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.3.22</version>
</dependency>
<!--mysql驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.25</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.22</version>
</dependency>
2. 外部配置文件
jdbc.properties
wind.url=jdbc:mysql://localhost:3306/studb
wind.driver=com.mysql.cj.jdbc.Driver
wind.username=root
wind.password=root
#尽量加前缀 xx.url 避免报错
3. spring配置类
@Component
@Configuration //声明 配置类
@ComponentScan("com.wind") // 包扫描
@PropertySource("classpath:jdbc.properties")//引入配置文件 注解
@EnableTransactionManagement //开启事务注解 的支持
public class JavaConfig {
@Bean //实例化dataSource加入到ioc容器
public DruidDataSource dataSource(@Value("${wind.url}") String url,
@Value("${wind.driver}") String driver,
@Value("${wind.username}") String username,
@Value("${wind.password}") String password) {
DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setDriverClassName(driver);
druidDataSource.setUrl(url);
druidDataSource.setUsername(username);
druidDataSource.setPassword(password);
return druidDataSource;
}
@Bean //实例化JdbcTemplate对象,需要使用ioc中的DataSource
public JdbcTemplate jdbcTemplate(DruidDataSource druidDataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(druidDataSource);
return jdbcTemplate;
}
@Bean //装配事务管理实现对象
public TransactionManager dataSourceTransactionManager(DruidDataSource druidDataSource) {
// 内部进行事务操作 基于连接池
DataSourceTransactionManager dataSourceTransactionManager =
new DataSourceTransactionManager();
//需要连接池对象
dataSourceTransactionManager.setDataSource(druidDataSource);
return dataSourceTransactionManager;
}
}
哪些类需要事务,使用声明事务注解@Transactional
@Service
public class StudentService {
@Autowired //自动装配
private StudentDao studentDao;
@Transactional
public void changeInfo(){
studentDao.updateAgeById(100,1);
System.out.println("-----------");
int i = 1/0;
studentDao.updateNameById("test1",1);
}
}
事务属性 -->只读 @Transactional(readOnly = true) 把当前事务设置为只读 默认是false!
声明 事务注解 一般我们将 事务 注解加入到类上
这样类中的方法都具有事务
在类级别@Transactional注解中设置只读,这样类中所有的查询方法都不需要设置@Transactional注解
然后在这个基础上,对增删改方法设置@Transactional注解 readOnly 属性为 false
事务属性 -->超时时间 @Transactional(timeout = 3)
事务在执行过程中,有可能因为遇到某些问题,导致程序卡住,从而长时间占用数据库资源。而长时间占用资源,大概率是因为程序运行出现了问题(可能是Java程序或MySQL数据库或网络连接等等)
此时这个很可能出问题的程序应该被回滚,撤销它已做的操作,事务结束,把资源让出来,让其他正常程序可以执行 (超时回滚,释放资源)
timeout设置事务超时时间,单位秒! 默认: -1 永不超时,不限制事务时间
事务属性 -->事务异常 @Transactional(rollbackFor = Exception.class)
事务异常分为: 指定异常回滚 指定异常不会滚
指定异常回滚 默认是 RuntimeException and Error 异常方可回滚
为了控制事物的回滚 我们可以将 事务异常的范围放大 实现控制事务异常 指定回滚
@Transactional(rollbackFor = Exception.class)
而 noRollbackFor 这个属性 则是在控制范围内 指定某个特定的异常发生时 不会回滚
事务属性 -->事务隔离级别设置 @Transactional(isolation = Isolation.READ_COMMITTED)
数据库事务的隔离级别是指在多个事务并发执行时,数据库系统为了保证数据一致性所遵循的规定。常见的隔离级别包括:
- 读未提交(Read Uncommitted):事务可以读取未被提交的数据,容易产生脏读、不可重复读和幻读等问题。实现简单但不太安全,一般不用。
- 读已提交(Read Committed):事务只能读取已经提交的数据,可以避免脏读问题,但可能引发不可重复读和幻读。
- 可重复读(Repeatable Read):在一个事务中,相同的查询将返回相同的结果集,不管其他事务对数据做了什么修改。可以避免脏读和不可重复读,但仍有幻读的问题。
- 串行化(Serializable):最高的隔离级别,完全禁止了并发,只允许一个事务执行完毕之后才能执行另一个事务。可以避免以上所有问题,但效率较低,不适用于高并发场景。
不同的隔离级别适用于不同的场景,需要根据实际业务需求进行选择和调整
事务属性 -->事务传播行为 @Transactional(propagation = Propagation.REQUIRES_NEW)
在被调用的子方法中设置传播行为,代表如何处理调用的事务! 是加入,还是新事务等
@Transactional 注解通过 propagation 属性设置事务的传播行为
REQUIRED : 默认值 如果父方法有事务,就加入,如果没有就新建自己独立
REQUIRES_NEW : 不管父方法是否有事务,我都新建事务,都是独立的
注意事项:
在同一个类中,对于@Transactional注解的方法调用,事务传播行为不会生效。这是因为Spring框架中使用代理模式实现了事务机制,在同一个类中的方法调用并不经过代理,而是通过对象的方法调用,因此@Transactional注解的设置不会被代理捕获,也就不会产生任何事务传播行为的效果
标签:事务,spring,Transactional,回滚,druidDataSource,注解,wind From: https://www.cnblogs.com/weifengfuxiufa/p/17704766.html