Spring TX配置(声明式事务管理+annotation)
文末有本篇文章的项目源码可供下载学习
Spring的事务管理是指Spring框架提供的一套机制,用于管理数据库操作中的事务。在数据库操作中,事务是一组操作单元,要么全部成功提交,要么全部失败回滚,保证数据的一致性和完整性。
Spring的事务管理可以通过编程方式或声明式方式实现。在编程方式下,可以通过编写代码来控制事务的开始、提交或回滚;在声明式方式下,可以通过配置来定义事务的一致性和隔离级别,而不需要编写具体的事务管理代码。
Spring的事务管理提供了对多种事务管理器的支持,如JDBC事务管理器、Hibernate事务管理器、JTA事务管理器等,以适配不同的数据访问技术。
总的来说,Spring的事务管理使得数据库操作更加简单、可靠和灵活,提高了应用程序的性能和稳定性。
Spring事务管理也是利用了AOP思维,先在TransactionManager接口中中定义好事务开启,事务提交,事务回滚等方法,让事务增强类进行调用.因为TransactionManage是一个接口,所以Spring又根据数据库类型提供了多个实现,我们比较常用的就是JDBC事务管理器(DataSourceTransactionManager)
因此我们在Spring事务管理中只需做到以下两点即可:
- 确定事务管理器的实现,并将该实现类加入SpringIoC容器.
- 确定哪个方法或者哪个类中的全部方法需要事务管理即可.
0.配置思路
- 搭建项目,配置pom.xml文件,引入相关依赖.
- 创建数据库mytest,新建表customer.
- 编写CustomerDao.java/CustomerService.java/CustomerServiceImpl.java.
- 编写SpringConfig.java文件,对Spring进行相关的配置.
- 编写SpringTest.java文件,完成相关测试.
1.配置pom.xml
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>6.2.3</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.11.4</version>
<scope>test</scope>
</dependency>
<!-- 数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<!-- 连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.8</version>
</dependency>
<!-- spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>6.0.6</version>
</dependency>
<!-- 声明式事务依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>6.0.6</version>
</dependency>
</dependencies>
2.创建数据库mytest,新建表customer
3.编写Dao/Service相关文件
@Repository
public class CustomerDao {
@Autowired
private JdbcTemplate jdbcTemplate;
public void updateUsernameById(String username,String id){
String sql = "update customer set username = ? where id = ? ;";
int rows = jdbcTemplate.update(sql, username, id);
}
}
public interface CustomerService {
void changeInfo();
}
@Service
public class CustomerServiceImpl implements CustomerService {
@Autowired
private CustomerDao customerDao;
@Transactional
@Override
public void changeInfo(){
customerDao.updateUsernameById("张三","1");
int i = 1/0;
System.out.println("-----------");
customerDao.updateUsernameById("李四","1");
}
}
4.编写SpringConfig.java
@Configuration
@ComponentScan("com.my.ssm")
@PropertySource("classpath:jdbc.properties")
@EnableTransactionManagement //开启事务注解的支持
public class SpringConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
//druid连接池
@Bean
public DataSource dataSource(){
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driver);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
@Bean
//jdbcTemplate
public JdbcTemplate jdbcTemplate(DataSource dataSource){
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
/**
* 装配事务管理实现对象
* @param dataSource
* @return
*/
@Bean
public TransactionManager transactionManager(DataSource dataSource){
return new DataSourceTransactionManager(dataSource);
}
}
5.编写SpringTest.java
public class SpringTest {
@Test
public void test() {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
CustomerService customerService = context.getBean(CustomerService.class);
customerService.changeInfo();
}
}
6.测试结果
1.正常测试
当我们把 int i = 1/0;这条语句注释掉之后,changeInfo这个方法就不会发生错误,在不发生错误的情况下,就不会发生事务回滚,也就是经过两次修改,最终id为1的username为李四
@Transactional
@Override
public void changeInfo(){
customerDao.updateUsernameById("张三","1");
// int i = 1/0;
System.out.println("-----------");
customerDao.updateUsernameById("李四","1");
}
2.添加事务测试异常
我们将int i = 1/0;这条语句不加注释,让其生效的情况下,因为经过第一次测试,此时id为1的username为李四,所以因为发生了异常,并且存在事务回滚的情况下,不改变原有的数据,此时id为1的username仍为李四,如果事务不生效,不存在事务回滚的话,那么在发生除零错误之前,id为1的username已经被修改为了张三.
@Transactional
@Override
public void changeInfo(){
customerDao.updateUsernameById("张三","1");
int i = 1/0;
System.out.println("-----------");
customerDao.updateUsernameById("李四","1");
}
3.排除事务测试异常
我们将@Transactional这个注解进行注释,让该方法不存在事务处理的情况下,我们再进行测试,此时由于第二次测试,数据库中id为1的username初始数据仍为李四,因为不存在事务处理的情况,所以在发生异常之前,执行的数据库操作是生效的,此时id为1的username应该为张三
// @Transactional
@Override
public void changeInfo(){
customerDao.updateUsernameById("张三","1");
int i = 1/0;
System.out.println("-----------");
customerDao.updateUsernameById("李四","1");
}
本篇文章的项目源码,可供点击下载学习