0

SpringとHibernateをJtaTransactionsで使用していますが、データベースが2つあり、トランザクション方式に問題があります。

このメソッドでは、多くのオブジェクトを挿入しますが、挿入をロールバックするために例外をスローします。ここでは、オブジェクトがデータベースに表示されないため、コードは期待どおりに機能します。

しかし、同じテーブルのオブジェクトを取得する行をメソッドに追加すると、オブジェクトはデータベースにコミットされます。

SELECTを作成すると、オブジェクトが自動コミットされると思います。これは、例外が再度スローされ、オブジェクトがデータベースに保持されるためです。

私のxmlとコード:

dao.xml

<bean
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations" value="classpath:configuracion_dao.properties" />
</bean>

<bean name="productosDAO" class="practica1.hibernate.HibernateProductosDAOImpl"
    parent="abstractPracticaBean">
    <property name="sessionFactory" ref="hibernateSessionFactory" />
</bean>

<bean name="tercerosDAO" class="${tercerosDAO.classname}" parent="abstractPracticaBean">
    <property name="dataSource" ref="dataSourceDatos" />
</bean>

<bean name="auditoriaDAO" class="practica1.hibernate.HibernateAuditoriaDAOImpl" parent="abstractPracticaBean">
    <property name="sessionFactory" ref="hibernateSessionFactory2" />
</bean>


<bean id="hibernateSessionFactory"
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSourceDatos" />
    <property name="mappingResources">
        <list>
            <value>hibernate-mappings.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=org.hibernate.dialect.HSQLDialect
  </value>
    </property>
</bean>

<bean id="hibernateSessionFactory2"
    class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSourceAuditoria" />
    <property name="mappingResources">
        <list>
            <value>hibernate-mappings-auditoria.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=org.hibernate.dialect.HSQLDialect
  </value>
    </property>
</bean>


<bean name="dataSourceDatos" class="org.enhydra.jdbc.standard.StandardXADataSource">
    <property name="driverName" value="org.apache.derby.jdbc.EmbeddedDriver" />
    <property name="url" value="jdbc:derby:/tmp/datos.db;create=true" />
    <property name="transactionManager" value="#{txManager.transactionManager}" />
</bean>

<jdbc:initialize-database data-source="dataSourceDatos"
    ignore-failures="ALL">
    <jdbc:script location="classpath:practica1/sql/creacion_derby.sql" />
    <jdbc:script location="classpath:practica1/sql/datos.sql" />
</jdbc:initialize-database>

<bean name="dataSourceAuditoria" class="org.enhydra.jdbc.standard.StandardXADataSource">
    <property name="driverName" value="org.apache.derby.jdbc.EmbeddedDriver" />
    <property name="url" value="jdbc:derby:/tmp/auditoria.db;create=true" />
    <property name="transactionManager" value="#{txManager.transactionManager}" />
</bean>

<jdbc:initialize-database data-source="dataSourceAuditoria"
    ignore-failures="ALL">
    <jdbc:script location="classpath:practica1/sql/creacion_auditoria_derby.sql" />
</jdbc:initialize-database>

<bean id="txManager"
    class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" value="#{jotm.transactionManager}" />
    <property name="userTransaction" value="#{jotm.userTransaction}" />
</bean>

<bean id="jotm" class="org.objectweb.jotm.Jotm" destroy-method="stop">
    <constructor-arg value="true" />
    <constructor-arg value="false" />
</bean>

<tx:annotation-driven transaction-manager="txManager" />

bo.xml

<bean name="tercerosBO" class="practica1.impl.TercerosBOImpl"
    parent="abstractPracticaBean" autowire="constructor">

</bean>
<bean name="productosBO" class="practica1.impl.ProductosBOImpl"
    parent="abstractPracticaBean">
    <property name="productosDAO" ref="productosDAO" />
    <property name="auditoriaDAO" ref="auditoriaDAO" />
</bean>

aplicacion.xml

<bean id="messageSource"
    class="org.springframework.context.support.ResourceBundleMessageSource">
    <property name="basenames" value="mensajes" />
</bean>

<bean id="abstractPracticaBean" class="practica1.impl.AbstractPracticaBean" abstract="true">
    <property name="messageSource" ref="messageSource"></property>
</bean>

<import resource="bo.xml" />
<import resource="dao.xml" />

トランザクション方式:

@Transactional
@Override
public void actualizaPrecio(double porcentaje) {
    internalActualizaPrecio(porcentaje);
}
private void internalActualizaPrecio(double porcentaje) {
    auditoriaDAO.insertAuditoria(getMessageSource().getMessage(
            "mensaje.actualizar_productos", new Object[] { porcentaje },
            null));
    int i = 0;
    auditoriaDAO.getAuditorias(); // Without this line its works like I expected
    List<Producto> productos = productosDAO.getProductos();
    for (Producto producto : productos) {
        i++;
        if (i > 3)
            throw new UnsupportedOperationException(
                    "Error para que veamos las transacciones");
        producto.setPrecio(producto.getPrecio().multiply(
                new BigDecimal(porcentaje).divide(new BigDecimal(100))));
        productosDAO.updateProducto(producto);
    }
}

私は、auditiaDAO.getAuditorias()を使用すると、ロールバックはProductoにのみ影響しますが、productoDAO.getProductos()を使用すると、ロールバックはAuditoriaにのみ影響することに気付きました...

4

2 に答える 2

1

ここでフラッシュコミットを混同している可能性があります。SELECTステートメントは通常、最新のデータをフェッチするために、以前のすべてのSQLステートメントをフラッシュします(txで行った以前の変更に関して)。このようなSELECTステートメントが実行される前に(私が間違っていない場合は、次のDAO呼び出しが2番目のsessionFactoryに対して行われる)、例外がフラッシュなしでメソッドを終了する可能性があります。したがって、データベースに変更はありません。

だから問題は:あなたはtxを効果的にロールバックしていると確信していますか?メソッドに注釈を付けたようです。SpringAOPprivateのプロキシベースのメカニズムはそれを処理しません!publicこの非常にプロキシベースのメカニズムのため、メソッドに注釈を付け、注釈付きメソッドのクラスの外部から呼び出す必要があります。ドキュメントの「メソッドの可視性と@Transactional」ブロックを参照してください。

別のリード:2つのsessionFactoriesがあるので、XAトランザクション/データソースを使用していると思います:confのこの部分は問題ありませんか?

于 2011-06-28T13:34:54.147 に答える
0

auditiaDAOproductosDAOを確認し、他のトランザクション アノテーションを検索してください。新しいトランザクションがどこかに作成され、UnsupportedExceptionが最後のトランザクションのみをロールバックし、親トランザクションがコミットされていると思います。私が助けてくれることを願っています!

私は2つの例を見つけました。これをチェックしてください。

spring と hibernate での JOTM トランザクション

Spring 3、Hibernate 3、Atomikos を使用して複数のデータベースにアクセスする

于 2011-06-28T12:03:41.793 に答える