Как откатить транзакцию, которая начинается в многопоточности при использовании Spring Transaction Management? - PullRequest
1 голос
/ 17 апреля 2020

Spring Transcation не поддерживает многопоточность, это означает, что каждый поток будет иметь свое собственное соединение / транзакцию.

Я хотел бы знать, как откатить метод Thread () () в следующем примере когда внутри него есть исключение. (точно так же как require_new или вложенное распространение)

Мой ожидаемый результат - только 'start' и 'end'.


Основной класс:

@SpringBootApplication
public class Application implements CommandLineRunner {

    @Autowired
    private TestService testService;

    public static void main(String[] args) {

        SpringApplication.run(Application.class, args);

    }

    @Bean
    public DriverManagerDataSource createDriverManagerDataSource() {

        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
        dataSource.setUrl("jdbc:oracle:thin:@url:port/schema");
        dataSource.setUsername("xxxx");
        dataSource.setPassword("xxxx");

        return dataSource;

    }

    @Bean
    public JdbcTemplate createJdbcTemplate() {

        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(createDriverManagerDataSource());

        return jdbcTemplate;

    }

    @Override
    public void run(String... args) throws Exception {

        testService.test1();

    }

}

Класс обслуживания :

@Service
public class TestService {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Transactional(rollbackFor = Exception.class)
    public void test1() throws Exception {

        jdbcTemplate.batchUpdate("INSERT INTO TB_MYTEST(MYKEY, MYVALUE) VALUES ('start', 'start')");

        ExecutorService executorService = Executors.newFixedThreadPool(5);

        for (int i = 1; i <= 5; i++) {

            executorService.submit(new TestRunner(i));

        }

        executorService.shutdown();
        executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);

        jdbcTemplate.batchUpdate("INSERT INTO TB_MYTEST(MYKEY, MYVALUE) VALUES ('end', 'end')");
    }

    private class TestRunner implements Runnable {

        private Integer id;

        public TestRunner(Integer id) {

            this.id = id;

        }

        @Override
        public void run() {

            String sqlString = String.format("INSERT INTO TB_MYTEST(MYKEY, MYVALUE) VALUES ('%d', '%d')", id, id);
            jdbcTemplate.batchUpdate(sqlString);

            // Insert Into Unknown Table, But Rollback Nothing!
            jdbcTemplate.batchUpdate("INSERT INTO UNKNOWN_TABLE(MYKEY, MYVALUE) VALUES ('no', 'no')");

        }

    }

}

Мой ожидаемый результат:

enter image description here

Результат прямо сейчас:

enter image description here

Любой ответ приветствуется! Спасибо!

...