簡體   English   中英

Spring 獲取元素后提交的全局事務

[英]Spring global transaction committed after getting an element

我將 Spring 和 Hibernate 與 Jta Transactions 一起使用,我有 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" />

博.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>

應用程序.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);
    }
}

我意識到,如果我使用auditoriaDAO.getAuditorias(),回滾只會影響Producto,但如果我使用productoDAO.getProductos(),回滾只會影響Auditoria...

您可能在這里混淆了刷新提交:SELECT 語句通常會刷新所有以前的 SQL 語句,以便獲取最新數據(關於您在 tx 中所做的先前更改)。 有可能在這樣的 SELECT 語句完成之前(如果我沒記錯的話,對第二個sessionFactory 進行以下 DAO 調用),異常退出該方法而沒有flush 因此無需修改數據庫。

所以問題是:你確定你正在有效地回滾 tx 嗎? 我看到你注釋了一個private方法:Spring AOP 的基於代理的機制不處理這個! 由於這種非常基於代理的機制,您必須注釋public方法並從注釋方法的 class 外部調用它。 請參閱文檔中的“方法可見性和@Transactional”塊。

另一個線索:你有 2 個 sessionFactories,所以我假設你正在使用 XA 事務/數據源:你確定這部分的 conf 沒問題嗎?

請檢查auditoriaDAOproductosDAO搜索其他事務性注釋 我認為在某處創建了一個新事務,並且 UnsupportedException僅回滾最后一個事務,並且父事務已提交。 希望我有所幫助!

我找到了兩個例子。 請檢查一下。

spring 和 hibernate 中的 JOTM 事務

使用 Spring 3、Hibernate 3 和 Atomikos 訪問多個數據庫

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM