栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring - @Transaction 事务

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring - @Transaction 事务

文章目录

前言配置

XML 配置 代码@Transactional资源


前言

研究 Spring 事务。

配置
package xianzhan.spring.jdbc.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.transaction.annotation.TransactionManagementConfigurer;


@Configuration
@EnableTransactionManagement
public class JdbcConfig implements TransactionManagementConfigurer {

    @Bean
    public DriverManagerDataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/lxz");
        dataSource.setUsername("root");
        dataSource.setPassword("root");

        return dataSource;
    }

    @Bean
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return new DataSourceTransactionManager(dataSource());
    }

    @Bean
    public JdbcTemplate jdbcTemplate(DriverManagerDataSource dataSource) {
        return new JdbcTemplate(dataSource);
    }
}

上面配置相当于在 XML 开启了事务注解,即:


XML 配置

那么如果使用 XML 配置如何写呢?




    
    

    
    
        
        
            
            
            
            
        
    

    
    
        
        
    

    
    
        
        
        
        
    

    
    
        
    

    


https://docs.spring.io/spring-framework/docs/current/reference/html/data-access.html#transaction-declarative-first-example

代码

接下来看下业务代码:

@Service
public class StudentScoreServiceImpl implements IStudentScoreService {

    
    @Autowired
    private PlatformTransactionManager txManager;
    @Autowired
    private JdbcTemplate               jdbcTemplate;

    @Override
    public void saveScore() {
        TransactionDefinition td = new DefaultTransactionAttribute();
        TransactionStatus transaction = txManager.getTransaction(td);

        try {
            long l = System.currentTimeMillis();
            String sql = "INSERT INTO student_score(name, subject, score) VALUE(?, ?, ?)";
            jdbcTemplate.update(sql, Long.toString(l), Long.toString(l), 1);
            jdbcTemplate.update(sql, Long.toString(l + 1), Long.toString(l + 1), 1);

            txManager.commit(transaction);
        } catch (Exception e) {
            e.printStackTrace();
            txManager.rollback(transaction);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveScoreWithTransaction() {
        long l = System.currentTimeMillis();
        String sql = "INSERT INTO student_score(name, subject, score) VALUE(?, ?, ?)";
        jdbcTemplate.update(sql, Long.toString(l), Long.toString(l), 1);
        jdbcTemplate.update(sql, Long.toString(l + 1), Long.toString(l + 1), 1);
    }
}

第一个方法 saveScore 是手动控制事务放在一个 try 代码块里,发生异常则进行回滚,如果其他方法也有多个更新操作,那么也需要写相同的代码;第二个方法 saveScoreWithTransaction 则使用 @Transactional 进行拦截处理,只需写相关的业务代码即可。

可以看出,Spring 的事务注解可以帮我们解决掉很多重复的代码。

@Transactional

调用模型

Caller: 调用类调用业务接口 IXxxServiceAOP Proxy: TransactionProxyFactoryBean 生成代理类Transaction Advisor: TransactionInterceptor 执行业务方法前拦截执行事务Custom Advisor(s): 自定义织入(一般没用)Target Method: IXxxService 实现类的业务方法,不过是由代理类执行

为什么默认需要 public 修饰的方法才能触发 @Transaction 呢?原因就是:

public abstract class AbstractFallbackTransactionAttributeSource
		implements TransactionAttributeSource, EmbeddedValueResolverAware {
	// ...
	
	@Nullable
	protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class targetClass) {
		// Don't allow non-public methods, as configured.
		if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
			return null;
		}

		// The method may be on an interface, but we need attributes from the target class.
		// If the target class is null, the method will be unchanged.
		Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);

		// First try is the method in the target class.
		TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
		if (txAttr != null) {
			return txAttr;
		}

		// Second try is the transaction attribute on the target class.
		txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
		if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
			return txAttr;
		}

		if (specificMethod != method) {
			// Fallback is to look at the original method.
			txAttr = findTransactionAttribute(method);
			if (txAttr != null) {
				return txAttr;
			}
			// Last fallback is the class of the original method.
			txAttr = findTransactionAttribute(method.getDeclaringClass());
			if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
				return txAttr;
			}
		}

		return null;
	}
	// ...
}
资源

spring-jdbc 代码
Spring AOP APIs
Transaction Management

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/727774.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号