Spring / JTA / модульный тест JPA: Откат, не работающий

Я нашел блог через Google с некоторыми яркими примерами о том, как сделать это:

  1. Осуществляют рефакторинг класс, чтобы быть классом экземпляра и реализовать интерфейс.

    Вы уже заявили, что не хотите делать это.

  2. Использование класс экземпляра обертки с делегатами к статическим участникам классов

    Выполнение этого можно моделировать статический интерфейс через делегатов.

  3. Использование класс экземпляра обертки с защищенными участниками, которые называют статический класс

    , который Это является, вероятно, самым легким дразнить/управлять, не осуществляя рефакторинг, поскольку это может просто быть наследовано от и расширено.

5
задан Michel 5 October 2009 в 13:10
поделиться

3 ответа

Мне удалось заставить его работать, используя Bitronix вместо JOTM. Bitronix предоставляет LrcXADataSource, который позволяет базе данных, отличной от XA, участвовать в транзакции JTA.

Я думаю, что проблема заключалась в том, что H2 не совместим с XA, а enhydra StandardXADataSource не делает это волшебным образом (я также закончил использование HSQLDB, но это не имеет отношения к проблеме).

Вот мой контекст Spring, который работает:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config />
    <tx:annotation-driven transaction-manager="transactionManager" />

    <!--  Bitronix Transaction Manager embedded configuration -->
    <bean id="btmConfig" factory-method="getConfiguration"
        class="bitronix.tm.TransactionManagerServices">
        <property name="serverId" value="spring-btm" />
        <property name="journal" value="null" />
    </bean>

    <!-- create BTM transaction manager -->
    <bean id="BitronixTransactionManager" factory-method="getTransactionManager"
        class="bitronix.tm.TransactionManagerServices" depends-on="btmConfig,dataSource"
        destroy-method="shutdown" />

    <bean id="transactionManager"
        class="org.springframework.transaction.jta.JtaTransactionManager">
        <property name="transactionManager" ref="BitronixTransactionManager" />
        <property name="userTransaction" ref="BitronixTransactionManager" />
        <property name="allowCustomIsolationLevels" value="true" />
    </bean>


    <!-- DataSource definition -->

    <bean id="dataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource"
        init-method="init" destroy-method="close">
        <property name="className" value="bitronix.tm.resource.jdbc.lrc.LrcXADataSource" />
        <property name="uniqueName" value="unittestdb" />
        <property name="minPoolSize" value="1" />
        <property name="maxPoolSize" value="3" />
        <property name="allowLocalTransactions" value="true" />
        <property name="driverProperties">
            <props>
                <prop key="driverClassName">org.hsqldb.jdbcDriver</prop>
                <prop key="url">jdbc:hsqldb:mem:unittestdb</prop>
                <prop key="user">sa</prop>
                <prop key="password"></prop>
            </props>
        </property>
    </bean>

    <!-- Entity Manager Factory -->
    <bean id="emf"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="showSql" value="true" />
                <property name="generateDdl" value="true" />
                <property name="database" value="HSQL" />
            </bean>
        </property>
        <property name="jpaPropertyMap">
            <map>
                <entry key="hibernate.transaction.manager_lookup_class"
                    value="org.hibernate.transaction.BTMTransactionManagerLookup" />
                <entry key="hibernate.transaction.auto_close_session" value="false" />
                <entry key="hibernate.current_session_context_class" value="jta" />
            </map>
        </property>

    </bean>
2
ответ дан 14 December 2019 в 19:18
поделиться

Когда я пытался интегрировать JOTM и Hibernate, мне в конечном итоге пришлось кодировать свою реализацию ConnectionProvider. Вот как это выглядит прямо сейчас: http://pastebin.com/f78c66e9c

Затем вы указываете свою реализацию в качестве привайдера соединения в свойствах гибернации, и транзакции волшебным образом начинают работать.

Дело в том, что поставщик подключения по умолчанию вызывает getConnection () для источника данных. В вашей собственной реализации вы вызываете getXAConnection (). GetConnection (). В этом разница

2
ответ дан 14 December 2019 в 19:18
поделиться

Редактировать: (Извините, я, кажется, проснулся только наполовину, когда писал этот абзац. Конечно, вы правы, все должно быть откатано по умолчанию.)

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

Предполагая log4j:

log4j.logger.org.springframework.transaction=DEBUG

Диспетчер транзакций дает очень хороший вывод журнала о созданных и объединенных транзакциях, а также о фиксациях и откатах. Это должно помочь вам выяснить, что не работает в вашей настройке.

1
ответ дан 14 December 2019 в 19:18
поделиться
Другие вопросы по тегам:

Похожие вопросы: