Spring Data Jpa @异步和@事务

v8wbuo2f  于 2022-11-23  发布在  Spring
关注(0)|答案(3)|浏览(273)

关于@事务性工作在@异步工作中的问题
这是一个示例的代码草图:

@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);
    }

问题是,这将如何工作,@Transactional是否从data方法扩展到setXor方法(如果您在data方法上添加了注解,那么可能不需要在setXor上添加注解?它将自动切换到该方法)
还有一个关于@Async的问题,setXor会和Async沿着在新线程上工作吗?也就是说,会有一个主线程,一个新的线程被创建,其中包含了data方法,由于data方法调用了另一个方法,它会和data方法在同一个线程上执行,不会有第三个线程。或者反之亦然,setXor方法在主线程中执行?

jbose2ul

jbose2ul1#

根据Spring事务处理Documentation
事务范围内的所有代码都在该事务中运行。但是,如果在事务上下文已存在时运行事务方法,则可以指定行为。例如,代码可以继续在现有事务中运行(常见情况),或者可以挂起现有事务并创建新事务。
@Transactional通常与PlatformTransactionManager管理的线程绑定事务一起工作,将事务公开给当前执行线程中的所有数据访问操作。这不会传播至方法内新启动的执行绪。
@Transactional由面向方面的编程提供支持。因此,当从另一个Bean调用一个Bean时,就会进行处理。在上面的示例中,从同一个类调用该方法,因此无法应用代理。
在事务块中调用不带@Transactional的方法时,父事务将继续存在于新方法中。它将使用父方法(带@Transactional的方法)中的相同连接,并且所调用方法(不带@Transactional的方法)中导致的任何异常都将导致事务按照事务定义中的配置回滚。
如果正在使用@Async注解,则应特别注意事务。当@Transactional Spring @Component调用用@Async注解的方法时,对异步方法的调用将由任务执行器调度并在稍后执行,因此将作为"新鲜"调用处理。如果@Async方法(或者声明它的@Component)本身不是@Transactional,Spring将不会管理任何需要的事务。
为了让Spring管理@Async方法的事务,@Component或方法本身都应该声明@Transactional注解,这样,即使方法是异步执行的,Spring也会管理事务。

hxzsmxv2

hxzsmxv22#

Spring不会为同一个类中的调用创建事务,因此setXor将在与data相同的Transaction中执行,无论您是否使用transactional对其进行注解。
我认为setXor和数据也将在主线程之外的一个线程中执行。

s4chpxco

s4chpxco3#

我是成功的,只有当我使用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);   

    }

}

相关问题