2010-07-01 15 views
11

Tengo una página portillo, que contiene dos granos de primavera gestionados, uno es DAO, otro es objeto de servicio:¿Cómo obtener programmatically manager de transacciones en un hilo?

public class MergeAccountsPage extends WebPage 
{ 
    @SpringBean 
    private MergeEmailDao mergeEmailDao; 

    @SpringBean 
    private MergingService mergingService; 
} 

métodos de implementación La MergingService 's se anotan en su mayoría con @Transactional, por lo que cada acción que implique trabajos MergingService multa.

Pero el problema viene aquí:

Link<Void> link = new Link<Void>("cancelLink") { 
    @Override 
    public void onClick() { 
    ma.setNewEmail(null); 
    ma.setNewEmailClicked(null); 
    ma.setNewEmailSentTime(null); 
    mergeAccoungDao.update(ma); //not written to DB 
    setResponsePage(...); 
    } 
}; 

El enlace se llame mergeAccoungDao.update(ma) para actualizar una fila en la base de datos.

Pero los datos no se actualizan a DB, creo que es porque el DAO no está envuelto en etiquetas @Transaction ni tx:advice y aop.

Me pregunto si hay alguna forma de obtener programáticamente el administrador de transacciones y abrir/cerrar manualmente la transacción.

Nota: Puedo resolver el problema agregando este código en XML de la primavera:

<tx:advice id="txAdviceApp" transaction-manager="transactionManagerApp"> 
    <tx:attributes> 
     <tx:method name="get*" read-only="true"/> 
     <tx:method name="save*" propagation="REQUIRED"/> 
     <tx:method name="update*" propagation="REQUIRED"/> 
     <tx:method name="delete*" propagation="REQUIRED"/> 
     <tx:method name="*" propagation="SUPPORTS"/> 
    </tx:attributes> 
    </tx:advice> 

    <aop:config> 
    <aop:pointcut id="methods" expression="execution(* destiny.utils.AbstractDao+.*(..))"/> 
    <aop:advisor advice-ref="txAdviceApp" pointcut-ref="methods"/> 
    </aop:config> 

Así que de la DAO guardar/actualizar/eliminar funciona como un encanto.

Pero no me gustaría agregar esta configuración. Porque, de hecho, la DAO se extiende un AbstractDao, y hay otras DB/DAO extender esta AbstractDao:

public interface AbstractDao<T> { 
    public T get(Serializable id); 
    public T save(T t); 
    public T update(T t); 
    public void delete(T t); 
} 

public abstract class AbstractDaoJpaImpl<T> implements AbstractDao<T> 

public interface MergeAccountDao extends AbstractDao<MergeAccount> 

@Repository 
public class MergeAccountDaoImpl extends AbstractDaoJpaImpl<MergeAccount> implements MergeAccountDao 

Por lo tanto, si CRUD de este AbstractDAO es "aconsejado" por esta transactionManagerApp, otros DAOs pueden tener problema, porque otra Los DAO pueden depender de txManagerForum, txManagerBank, txManagerUser ... etc.

Volviendo al problema, ¿hay alguna forma de obtener programáticamente txManager? Por ejemplo:

TransactionManager txManager = TxManagerThreadLocal.get(); 
txManager.begin(); 
ma.setNewEmailSentTime(null); 
mergeAccoungDao.update(ma); 
txManager.commit(); 

¿O hay alguna manera mejor de envolver una transacción al DAO?

Muchas gracias.

Respuesta

14

Tiene que insertar el administrador de transacciones en la clase que desea usar. Puede usar una inyección basada en el constructor o la propiedad o usar el autoencendido. Una vez que obtiene el administrador de transacciones, puede utilizar el soporte de transacciones programáticas en Spring para iniciar y confirmar la transacción. Aquí está el código de ejemplo del muelle de referencia 2.5:

public class SimpleService implements Service { 

    // single TransactionTemplate shared amongst all methods in this instance 
    private final TransactionTemplate transactionTemplate; 

    // use constructor-injection to supply the PlatformTransactionManager 
    public SimpleService(PlatformTransactionManager transactionManager) { 
    Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null."); 
    this.transactionTemplate = new TransactionTemplate(transactionManager); 
    } 

    public Object someServiceMethod() { 
    return transactionTemplate.execute(new TransactionCallback() { 

     // the code in this method executes in a transactional context 
     public Object doInTransaction(TransactionStatus status) { 
     updateOperation1(); 
     return resultOfUpdateOperation2(); 
     } 
    }); 
    } 
} 

Véase el reference para más detalles.

+0

¡Gracias, funciona! – smallufo

Cuestiones relacionadas