2010-07-01 10 views
11

Ho una pagina wicket, che contiene due chicchi gestito Primavera-, uno è DAO, un altro è oggetto di servizio:Come ottenere a livello di programmazione il gestore delle transazioni in una discussione?

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

    @SpringBean 
    private MergingService mergingService; 
} 

metodi di implementazione s' The MergingService sono per lo più annotati con @Transactional, quindi ogni azione che coinvolge opere MergingService bene.

Ma il problema viene qui:

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(...); 
    } 
}; 

Il link viene chiamata mergeAccoungDao.update(ma) di aggiornare una riga nel DB.

Ma i dati non vengono aggiornati in DB, penso che sia perché il DAO non è stato inserito in tag @Transaction né tx:advice e aop.

Mi chiedo se esiste un modo per ottenere a livello di programmazione il gestore delle transazioni e aprire/chiudere manualmente la transazione?

Nota: posso risolvere il problema aggiungendo questo codice XML di 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> 

In modo che il DAO salvare/aggiornare/cancellare funzionerà come un fascino.

Ma non vorrei aggiungere questa configurazione. Perché in realtà, il DAO si estende un AbstractDao, e ci sono altri DB/DAO estendere questa 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 

Pertanto, se CRUD di questo AbstractDAO è "CONSIGLIATO" da questo transactionManagerApp, altri DAO possono avere problemi, perché gli altri I DAO possono dipendere da txManagerForum, txManagerBank, txManagerUser ... ecc.

Torna al problema, c'è un modo per ottenere txManager a livello di codice? Ad esempio:

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

Oppure c'è un modo migliore per concludere una transazione con DAO?

Grazie mille.

risposta

14

È necessario inserire il gestore delle transazioni nella classe che si desidera utilizzare. È possibile utilizzare il costruttore o l'iniezione basata sulla proprietà o utilizzare l'autowiring. Una volta ottenuto il gestore delle transazioni, in primavera è possibile utilizzare il supporto per le transazioni programmatiche per avviare e registrare la transazione. Ecco il codice di esempio dalla primavera di riferimento 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(); 
     } 
    }); 
    } 
} 

Vedere la reference per maggiori dettagli.

+0

Grazie, funziona! – smallufo

Problemi correlati