Управление сложными транзакциями при сбое XAResource в Spring, Oracle DB и Hibernate-вставке - PullRequest
0 голосов
/ 21 ноября 2018

Дело: файл с более чем 1 млн записей.Прочитайте файл и сохраните записи в базе данных Oracle.

Решение: используйте интерфейс Hibernate statelessSession, поскольку в этом конкретном случае нет необходимости использовать контекст постоянства.Загружать записи из файла в цикле while 100k каждый раз и фиксировать их немедленно.

Реализация: вверху у меня есть метод loadAllDictionaries () с аннотацией @Transactionalс таймаутом 7200. Он запускает цепочку методов и попадает в цикл while:

while(!(recordList = loadIDictionariesPackage(reader)).isEmpty()){
            processRecords(recordList, dictionaryVersion, dictionaryType, filename);
        }

Теперь processRecords (...) делает некоторыевещи и в какой-то момент вызывает следующее (обратите внимание на распространение)

@Transactional(propagation = Propagation.REQUIRES_NEW, timeout = 900) //timeout is unnecessary since it takes around 2,5 minutes.  
public void saveInStatelessSession(List<T> entities) throws HibernateException {
    StatelessSession session = this.getSessionFactory().openStatelessSession();
    session.beginTransaction();

    entities.forEach(entity -> session.insert(getEntityName(), entity));

    session.getTransaction().commit();
    session.close();
}

Итак, после завершения цикла while и сохранения в БД более 1 млн. записей поток возвращается к loadAllDictionaries() и вводит другой метод @Transactional addNewLog (...)

@Transactional
public void addNewLog(AbstractLogEntry message) {

    final EventLogDefinition definition = logEntryDAO.getDefinitionForEntry(message);

    doAddNewLog(message, definition, null);
}

Здесь getDefinitionForEntry() выдает исключение

com.atomikos.datasource.ResourceException: XA resource 'dataSource': resume for XID '3139322E3136382E35362E312E746D313534323739343839373335343033363332:3139322E3136382E35362E312E746D33373939' raised -4: the supplied XID is invalid for this XA resource

Что странно.Это происходит, только если ~ 200k или более записей сохранены.Не имеет значения, если я изменю пакет с 100 КБ до 10 КБ, что увеличивает количество транзакций.Я думал, что это может быть тайм-аут Atomicos, но в моем файле контекста приложения он установлен на 3000

<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.J2eeUserTransaction" depends-on="userTransactionService">
    <property name="transactionTimeout" value="3000" />
</bean>

Если я удаляю строку

@Transactional(propagation = Propagation.REQUIRES_NEW, timeout = 900)

из saveInStatelessSession метод, чем когда loadAllDictionaries () транзакция пытается зафиксировать данные, которые я получаю

ERROR org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException: Prepare: NO vote

Есть ли у вас какие-либо мысли о том, что может бытьпроблема здесь?

...