概念
声明式事务管理,在我们常用的交互式编程中,主要是用以下两个API。
- TransactionManager:核心接口,内含对事务的操作
- TransactionTemplate:门面接口,对复杂的manger操作进行优雅封装
以下是通过TransactionTemplate和TransactionManager对事务进行编程式管理的案例。
maven依赖
org.springframework:spring-context:5.3.24
org.springframework:spring-core:5.3.24
org.springframework:spring-beans:5.3.24
org.springframework:spring-aop:5.3.24
org.springframework:spring-tx:5.3.24
org.springframework:spring-jdbc:5.3.24
commons-dbcp:commons-dbcp:1.4
org.aspectj:aspectjweaver:1.9.7
com.mysql:mysql-connector-j:8.0.31
xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/tx
https://www.springframework.org/schema/tx/spring-tx.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<context:component-scan base-package="org.transaction.program"></context:component-scan>
</beans>
代码部分
注入bean
@Configuration
public class BeanConfig {
@Bean(name = "basicDatasource")
public DataSource dataSource() {
BasicDataSource basicDataSource = new BasicDataSource();
basicDataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
basicDataSource.setUrl("");
basicDataSource.setUsername("");
basicDataSource.setPassword("");
return basicDataSource;
}
@Bean(name = "txManager")
public DataSourceTransactionManager dataSourceTransactionManager(@Qualifier("basicDatasource") DataSource dataSource) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
@Bean(name = "jdbcTemplate")
public JdbcTemplate jdbcTemplate(@Qualifier("basicDatasource") DataSource dataSource) {
JdbcTemplate jdbcTemplate = new JdbcTemplate();
jdbcTemplate.setDataSource(dataSource);
return jdbcTemplate;
}
@Bean(name = "transactionTemplate")
public TransactionTemplate transactionTemplate(@Qualifier("txManager") DataSourceTransactionManager dataSourceTransactionManager){
TransactionTemplate transactionTemplate = new TransactionTemplate();
transactionTemplate.setTransactionManager(dataSourceTransactionManager);
transactionTemplate.setIsolationLevel(ISOLATION_READ_COMMITTED);
transactionTemplate.setPropagationBehavior(PROPAGATION_REQUIRED);
return transactionTemplate;
}
}
声明service
package org.transaction.program.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.ResultSetExtractor;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.transaction.program.entity.Bar;
import org.transaction.program.entity.Foo;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.function.Consumer;
import static org.springframework.transaction.TransactionDefinition.PROPAGATION_REQUIRED;
@Service
public class FooServiceImpl {
@Autowired
JdbcTemplate jdbcTemplate;
@Autowired
TransactionTemplate transactionTemplate;
@Autowired
DataSourceTransactionManager dataSourceTransactionManager;
/*无返回值*/
public void update() {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus status) {
jdbcTemplate.update("update foo_test set scores = scores + 1 where id = ?;", 1);
System.out.println("update success");
}
});
}
/*有返回值*/
public void updateRet() {
transactionTemplate.execute(new TransactionCallback<Integer>() {
@Override
public Integer doInTransaction(TransactionStatus status) {
int update = jdbcTemplate.update("update foo_test set scores = scores + 1 where id = ?;", 1);
System.out.println("updateRet success");
return update;
}
});
}
/*控制是否回滚*/
public void updateCommit() {
transactionTemplate.execute(new TransactionCallback<Integer>() {
@Override
public Integer doInTransaction(TransactionStatus status) {
try {
int update = jdbcTemplate.update("update foo_test set scores = scores + 1 where id = ?;", 1);
int i = 1/0; // 制造错误
System.out.println("updateCommit success");
return update;
}catch (Exception e) {
status.setRollbackOnly();
System.out.println("updateCommit fail");
return 0;
}
}
});
}
/*直接使用transactionManager进行事务操控*/
public void updateUseManager() {
DefaultTransactionDefinition definition = new DefaultTransactionDefinition(); // 类似于@Transactional(propagation=Propagation.Required)
definition.setPropagationBehavior(PROPAGATION_REQUIRED);
TransactionStatus status = dataSourceTransactionManager.getTransaction(definition);// 新建事务
try {
jdbcTemplate.update("update foo_test set scores = scores + 1 where id = ?;", 1);
System.out.println("updateUseManager success");
dataSourceTransactionManager.commit(status);
}catch (Exception e) {
System.out.println("updateUseManager fail:" + e.toString());
dataSourceTransactionManager.rollback(status);
}
}
}
启动类
package org.transaction.program;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.transaction.program.service.FooServiceImpl;
public class App {
public static void main(String[] args) throws InterruptedException {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-program.xml");
FooServiceImpl bean = ctx.getBean(FooServiceImpl.class);
bean.update();
bean.updateRet();
bean.updateCommit();
bean.updateUseManager();
}
}