Spring XA транзакции с драйвером JDBC Oracle - PullRequest
1 голос
/ 26 мая 2011

Я пытаюсь включить распределенные транзакции с помощью диспетчера транзакций bitronix.Подробности конфигурации включают

  1. Использование драйвера JDBC OCI и oracle.jdbc.xa.client.OracleXADataSource.Этот источник данных обернут источником данных пула соединений UCP - oracle.ucp.jdbc.PoolDataSourceImpl
  2. Использование Spring JdbcTemplate для выполнения запросов.
  3. Использование Bitronix Transaction Manager для обработки распределенных транзакций
  4. Весенние декларативные транзакции с использованием аннотаций

Проблема, с которой я сталкиваюсь, заключается в том, что запросы, выполняемые с использованием JDBCTemplate, не выполняютсявыполнено в транзакции.Мой тестовый пример выполняет два запроса, используя JDBCTemplate, и они не откатываются, когда метод генерирует исключение времени выполнения после выполнения запроса.Я также мог видеть, что для состояния автоматической фиксации соединения установлено значение true.

</p> <pre><code><tx:annotation-driven transaction-manager="distributedTransactionManager"/> <bean id="distributedTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager" ref="bitronixTransactionManager"/> <property name="userTransaction" ref="bitronixTransactionManager"/> <property name="allowCustomIsolationLevels" value="true"/> </bean> <bean id="bitronixTransactionManager" factory-method="getTransactionManager" class="bitronix.tm.TransactionManagerServices" depends-on="bitronixConfiguration" destroy-method="shutdown"> </bean>

Источник данных создается следующим образом

    PoolDataSourceImpl pds = new PoolDataSourceImpl();
    try {
        pds.setConnectionPoolName(dataSourceName);
        pds.setConnectionFactoryClassName("oracle.jdbc.xa.client.OracleXADataSource");
        pds.setConnectionFactoryProperties(getOracleDataSourceProperties());
        pds.setDataSourceName(dataSourceName);
        pds.setServerName("v-in-sd-tst-12");
        pds.setPortNumber(1521);
        pds.setUser("ForTestCasesAmit");
        pds.setPassword("adept");
        pds.setMinPoolSize(10);
        pds.setMaxPoolSize(100);
        pds.setMaxIdleTime(1800);

        pds.startPool();
    } catch (SQLException e) {
        throw new RuntimeException("Cannot create project datasource " + dataSourceName, e);
    }
    return pds;

Любые предложения о том, что может быть причиной, по которойзапросы не выполняются в транзакции?

Обновление 1

Добавление метода, который выполняет запросы с использованием jdbcTemplate и выдает исключение в конце

</p> <pre><code>@Transactional(propagation = Propagation.REQUIRED) public void execute() { System.out.println("Starting with the service method"); jdbcTemplateForDSOne.update("UPDATE T1 SET COL1 = 'Date1' WHERE COL2 = 1"); jdbcTemplateForDSOne.update("UPDATE T1 SET COL1 = 'Start Date1' WHERE COL2 = 2"); waitForUserInput(); throw new RuntimeException("Rollback Now"); }

Обновление 2

Руководство разработчика Oracle JDBC упоминает, что

"Статус автоматической фиксации по умолчанию для соединения, полученного из XAConnection, равен false во всех выпусках, предшествующих Oracle Database 10g. Начиная с Oracle Database 10g, статус по умолчанию равен true. "

Я использую Oracle 11g r2.Любая идея, какие изменения конфигурации должны быть сделаны при использовании распределенных транзакций, чтобы иметь статус автоматической фиксации как ложный?

Обновление 3

Транзакции работают, если я использую пул bitronixисточник данных вместо оракула ucp PoolDataSource.Использование bitronix PoolingDataSource дало Bitronix возможность установить для состояния автоматической фиксации значение false.Будем исследовать больше, чтобы понять разницу между ними.

Ответы [ 2 ]

0 голосов
/ 26 мая 2011

Насколько я вижу, они выполняются в транзакции, но транзакция не соответствует вашим ожиданиям.Когда autoCommit равно true, каждый запрос становится транзакцией.Чтобы избежать этого, необходимо правильно настроить соединение.

Тем не менее, комментарий о XA: XA не работает в крайних случаях, таких как проблемы с сетью и тайм-ауты.То есть, он будет работать 99,9995% раз, но в некоторых критических случаях это не сработает, и это те случаи, о которых вы заботитесь.

Убедитесь, что ваши структуры данных не повреждены, когда в конечном итоге XAВам не удается.

Вместо XA я предлагаю оценить методы, позволяющие снова запускать транзакции.Пример: вы хотите перенести некоторые записи из базы данных A в B. Итак, вы читаете строки с FOR UPDATE и для каждой переданной строки вы устанавливаете для столбца processed значение true.

С другой стороны,Вы добавляете только те строки, которых еще нет.

После фиксации передачи в B удалите строки в A where processed = 'true' или отметьте их другим способом.

Это означает, что выможете запускать это так часто, как вам нужно.

[EDIT]

Чтобы отключить автоматическую фиксацию, вы должны позвонить con.setAutoCommit(false); Проблема, конечно, в том, что выИспользуете Spring, поэтому вы никогда нигде явно не запрашиваете соединение.

Мое предложение: расширьте PoolDataSourceImpl и переопределите различные get*Connection() методы.Перед тем как вернуть их, установите автоматическую фиксацию на false.Вы также можете декомпилировать код драйвера JDBC, чтобы увидеть, содержит ли PoolDataSourceImpl что-то подобное, но, очевидно, его нет.

0 голосов
/ 26 мая 2011

Есть ли у вас метод, который содержит этот код, аннотированный @Transactional или определяющий какие-либо аспекты, которые сообщат Spring, чтобы этот метод выполнялся в транзакции?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...