简体   繁体   English

@Async 和 @Transactional

[英]@Async and @Transactional

Question about @Transactional working in @Async working关于@Transactional 在@Async 中工作的问题

This is a code sketch for an example:这是一个示例的代码草图:

@Async
@Transactional
 public void data(List<Pass> pass) {
        //code
        for(City city : city) {
            for(Dep dep: city.getDeps()) {
                //code
                setXor(user, xor);
                //code
            }
        }
    }


@Transactional
public void setXor(User user, Xor xor) {
        //code
        user.setXor(xor);
    }

The question is, how will this work, does @Transactional extend from the data method to the setXor method (if you put an annotation on the data method, then maybe you don't need to put it on setXor? And it will automatically switch to this method)问题是,这将如何工作,@Transactional 是否从 data 方法扩展到 setXor 方法(如果你在 data 方法上放了注解,那么也许你不需要将它放在 setXor 上?它会自动切换到这个方法)

Also a question about @Async, will setXor work on a new thread along with Async?还有一个关于@Async 的问题,setXor 会与 Async 一起在新线程上工作吗? That is, there will be a main thread, a new one is created, which includes the data method, and since the data method called another method, it will be executed on the same thread as the data method, there will be no third thread.也就是会有一个主线程,新建一个,里面包含data方法,由于data方法调用了另外一个方法,所以会和data方法在同一个线程上执行,不会有第三个线程. Or vice versa and the setXor method is executed in the main thread?或者反之亦然,并且 setXor 方法在主线程中执行?

Spring doesn't create transactions for calls in the same class so the setXor will be executed in the same Transaction as data no matter if you annotate it with transactional or not. Spring 不会为同一 class 中的调用创建事务,因此无论您是否使用事务性注释,setXor 都将在与数据相同的事务中执行。

I think also setXor and data will be executed in one Thread other than the main.我认为 setXor 和数据也将在除主线程之外的一个线程中执行。

As per Spring Transaction Documentation根据 Spring 交易文档

All code within a transaction scope runs in that transaction.事务 scope 中的所有代码都在该事务中运行。 However, you can specify the behavior if a transactional method is run when a transaction context already exists.但是,您可以指定在事务上下文已存在时运行事务方法时的行为。 For example, code can continue running in the existing transaction (the common case), or the existing transaction can be suspended and a new transaction created.例如,代码可以在现有事务中继续运行(常见情况),或者可以暂停现有事务并创建新事务。

@Transactional commonly works with thread-bound transactions managed by PlatformTransactionManager , exposing a transaction to all data access operations within the current execution thread. @Transactional通常与PlatformTransactionManager管理的线程绑定事务一起使用,将事务公开给当前执行线程中的所有数据访问操作。 Note: This does not propagate to newly started threads within the method.注意:这不会传播到方法中新启动的线程。

@Transactional is powered by Aspect-Oriented Programming. @Transactional由面向方面的编程提供支持。 Therefore, processing occurs when a bean is called from another bean.因此,当从另一个 bean 调用一个 bean 时,就会发生处理。 In the example above, the method is called from the same class so that no proxies can be applied.在上面的示例中,该方法是从同一个 class 调用的,因此不能应用代理。

When a method without @Transactional is called within a transaction block, the parent transaction will continue to exist for the new method.当在事务块中调用不带@Transactional的方法时,新方法的父事务将继续存在。 It will use the same connection from the parent method (method with @Transactional) and any exception caused in the called method (method without @Transactional) will cause the transaction to rollback as configured in the transaction definition.它将使用来自父方法(带有@Transactional 的方法)的相同连接,并且在被调用方法(不带@Transactional 的方法)中引起的任何异常都将导致事务按照事务定义中的配置回滚。

If the @Async annotation is being used extra care should be taken with respect to transaction.如果正在使用@Async注释,则应特别注意事务。 When a @Transactional Spring @Component calls a method annotated with @Async the call to the asynchronous method is being scheduled and executed at a later time by a task executor and is thus handled as a 'fresh' call, ie without a transactional context.@Transactional Spring @Component调用带有@Async注释的方法时,对异步方法的调用将由任务执行器安排并在稍后执行,因此作为“新”调用处理,即没有事务上下文。 If the @Async method (or the @Component in which it is declared) is not @Transactional by itself Spring will not manage any needed transactions.如果@Async方法(或声明它的@Component )本身不是@Transactional, @Transactional将不会管理任何需要的事务。

In order to make Spring manage the transaction of the @Async method either the @Component or the method itself should declare the @Transactional annotation, this way Spring will manage the transaction even if a method is being executed asynchronous.为了使 Spring 管理@Async方法的事务, @Component Component 或方法本身应声明@Transactional注释,这样 Spring 将管理事务,即使方法正在异步执行。

i was successful, only when i used jdbc template(this is so sad:() Note: in this case @Scheduled and @Async have the same result我成功了,只有当我使用 jdbc 模板时(这太可悲了:()注意:在这种情况下@Scheduled 和@Async 有相同的结果

   @Configuration
    @PropertySource("")
    @EnableJpaRepositories(basePackages = "com.foo.myapp")
    public class DataSourceConfig {

@Bean
public LocalContainerEntityManagerFactoryBean transpEntityManager() {
final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();    
return em;
}   
    
    @Bean
    @ConfigurationProperties(prefix = "app.datasource.transp")
    public DataSourceProperties transpDataSourceProperties() {
        return new DataSourceProperties();
    }


@Bean(name = "datasource_transp")
public DataSource transpDataSource() {
return transpDataSourceProperties().initializeDataSourceBuilder().type(HikariDataSource.class).build();
}


@Bean(name = "tm_transp")
@Autowired
DataSourceTransactionManager tmTransp(@Qualifier("datasource_transp") DataSource datasource) {
DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
return txm;
}


@Bean(name = "jdbcTemplateTransp")
public JdbcTemplate jdbcTemplateTransp(@Qualifier("datasource_transp") DataSource ds) {
        return new JdbcTemplate(ds);
}
       
}




@Service
@EnableScheduling
public class ScheduledService {

    @Autowired
    private ReportDataService reportDataService;

    @Autowired
    private AsyncService async;

    @Autowired
    @Qualifier("movProcTPTE")
    private TaskExecutor movProcTaskExecutor;

    @Scheduled(fixedDelay = 1000 * 60,initialDelay = 60000)
    public void agendamentoImportacaoMovProcessual(){
        movProcTaskExecutor.execute(
                () -> {
                    myService.methodWithDatabasePersist();
                }
        );

    }

}


@Service
public class ReportDataService {
    

    @Autowired
    @Qualifier("jdbcTemplateTransp")
    private JdbcTemplate jdbc;

    

    public void jdbcSave(List<ReportData> list){
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime date = LocalDateTime.now();
        String dateStr = date.format(fmt);
        ReportData report = list.get(0);
        String sql = "INSERT INTO .....";
        jdbc.update(sql);
    }

    public void methodWithDatabasePersist(){        
                    jdbcSave(relatorios);   

    }


}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM