Spring база данных транзакция не фиксирует данные в БД - PullRequest
0 голосов
/ 28 апреля 2019

Я создал проект с весенней загрузкой. У меня есть hikariConfig для создания источника данных для пула соединений со свойством autocommmit, установленным как false. Выполнение пакетной вставки с использованием jdbcTemplate внутри метода, аннотированного @Transaction для DataSourceTransactionManager. Я не могу видеть, как данные вставляются в БД после выполнения программы. Если я сделаю autocommit true в hikariconfig, он будет работать нормально.

@SpringBootApplication

public class Application {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@Component

@EnableTransactionManagement

public class DataSourceConfig {

    @Bean (name = "dateSourceForSqlServer")

    public DataSource dataSourceForSqlServer () {

        HikariConfig hikariConfig = new HikariConfig();
        hikariConfig.setConnectionTimeout(10000L);
        hikariConfig.setIdleTimeout(10000L);
        hikariConfig.setMinimumIdle(1);
        hikariConfig.setMaximumPoolSize(1);
       hikariConfig.setMaxLifetime(600000L);
        hikariConfig.setConnectionTestQuery("select 1");
        hikariConfig.setValidationTimeout(4000L);


        hikariConfig.setJdbcUrl("jdbc:sqlserver://localhost:1433;database=invt_mgmt");
        hikariConfig.setUsername("sa");
        hikariConfig.setPassword("sql_server_pass_123");

         hikariConfig.setDriverClassName("com.microsoft.sqlserver.jdbc.SQLServerDriver");


    hikariConfig.setAutoCommit(false);

        return  new HikariDataSource(hikariConfig);
    }

    @Bean (name = "jdbcTemplateForSqlServer")
    public JdbcTemplate jdbcTemplateForSqlServer () {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSourceForSqlServer());

        return jdbcTemplate;
    }

    @Primary
    @Bean(name = "invtMgmtTxMangerForSqlServer")
    public DataSourceTransactionManager transactionManager() {
        DataSourceTransactionManager manager = new DataSourceTransactionManager();
        manager.setDataSource(dataSourceForSqlServer());
        return manager;
    }

}


@Component

public class startBean {

    @Autowired
    private Business Business;

    @PostConstruct
    public void startApp() throws SQLException {
        Business.insertContainerHierarchy();
        Business.insertContainerHierarchy();

    }
}

@Component

 class public Business {

    @Autowired
    @Qualifier("jdbcTemplateForSqlServer")
    private JdbcTemplate jdbcTemplateForSqlServer;

    String insertIntStudent = "INSERT INTO student (id, name) Values(?, ?)";

    @Transactional(value = "invtMgmtTxMangerForSqlServer")
    public void insertContainerHierarchy () throws SQLException {

      System.out.println(TransactionSynchronizationManager.isActualTransactionActive());
      System.out.println(TransactionSynchronizationManager.getCurrentTransactionName());


        Date start = new Date();

        for (int i = 0; i < 500; i++) {
            System.out.println(i);
            jdbcTemplateForSqlServer.batchUpdate(insertIntStudent, new BatchPreparedStatementSetter() {

                @Override
                public void setValues(PreparedStatement ps, int i) throws SQLException {
                   ps.setInt(1, i);
                   ps.setString(2, String.valueOf(i));
                }

                @Override
                public int getBatchSize() {
                    return 1000;
                }
            });
        }
        System.out.println(new Date().getTime() - start.getTime());
    } 

}

Я использовал TransactionSynchronizationManager.isActualTransactionActive(), который возвращает значение true при выполнении метода.

Q1. Почему данные не вставляются, транзакция должна автоматически выполняться после выполнения метода?

Q2. В случае использования весенней транзакции, будет ли иметь значение значение автокоммитирования соединения с базой данных?

Q3. Как в настоящее время я могу вставить с автокоммитом, установленным в true?

1 Ответ

0 голосов
/ 28 апреля 2019

Вы пытаетесь вызвать прокси с транзакцией из метода @PostConstruct. Для этого компонента вся инициализация может быть завершена, но не обязательно для остальной части контекста. Не все прокси могут быть установлены в этой точке.

Я бы предложил реализовать интерфейс ApplicationListener<ContextRefreshedEvent>, чтобы инициировать любое создание данных внутри этого класса. Это обеспечит его вызов после настройки всего контекста:

@Component
public class OnContextInitialized implements
  ApplicationListener<ContextRefreshedEvent> {

    @Autowired
    private Business Business;

    @Override public void onApplicationEvent(ContextRefreshedEvent event) {
        Business.insertContainerHierarchy();
        Business.insertContainerHierarchy();
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...