2011-06-28 19 views
0

我使用Spring和Hibernate與Jta Transactions,我有2個數據庫,並且在事務性方法中有問題。獲取元素後提交的Spring全局事務

在這個方法中,我插入了很多對象,但是我拋出了一個異常來回滾插入,在這裏代碼按照我的預期工作,因爲對象不會出現在數據庫中。

但是,如果我在獲取同一個表的對象的方法中添加一行,則這些對象將被提交到數據庫中。

我認爲當我做一個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); 
    } 
} 

我意識到,如果我使用auditoriaDAO.getAuditorias()回滾隻影響到PRODUCTO但如果我用productoDAO.getProductos()回滾隻影響到禮堂......

回答

0

請檢查auditoriaDAOproductosDAO搜索其他交易註釋。我認爲在某處創建了一個新事務,並且UnsupportedException 僅回退最後一個事務,並且提交了父事務。希望我幫助!

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

JOTM transactions in spring and hibernate

Access Multiple Database Using Spring 3, Hibernate 3 and Atomikos

+0

我只有一個事務註釋,所以它是不可能的......謝謝 – Michel

+0

@lepike我意識到,如果我使用auditoriaDAO.getAuditorias()回滾隻影響Producto,但如果我使用productoDAO.getProductos()僅回滾影響Auditoria ... – Michel

+0

auditoriaDAO和productoDAO是否使用相同的數據源?如果沒有,我認爲這個交易對於兩個數據源來說並不是全球性的,所以這兩個交易有兩個交易。 – lepike

1

你可能會混淆沖洗提交這裏:SELECT語句通常刷新以前的所有SQL語句,以彌補最新數據(關於您在tx中所做的更改)。在完成這樣的SELECT語句之前(如果我沒有弄錯,以下DAO調用會話工廠對話框),則異常退出該方法而沒有flush。因此在數據庫中沒有修改。

所以問題是:你確定你有效回滾tx?我看到你註釋了一個private方法:Spring AOP的基於代理的機制不能處理這個問題!由於這種基於代理的機制,您必須註釋一個public方法並從註釋方法類的外部調用它。請參閱documentation中的「方法可見性和@Transactional」塊。

另一個導致:你有2個sessionFactories,所以我假設你正在使用XA transactions/datasources:你確定這部分conf是好的嗎?

+0

你對私有方法是正確的,我把事務註釋放在那個方法中,但是註解是在一個公用方法中調用私有方法。 SORRY – Michel

+0

我正在使用XA事務,但我擁有的所有配置都是在我發佈的XML上,我以爲我還沒有配置任何更多... – Michel