2010-07-01 16 views
11

J'ai une page wicket, qui contient deux grains réussi printemps, on est OAC, une autre est de service Objet:Comment faire pour obtenir par programme un gestionnaire de transactions dans un thread?

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

    @SpringBean 
    private MergingService mergingService; 
} 

méthodes de mise en œuvre de la MergingService sont la plupart du temps annotés avec @Transactional, donc toutes les actions impliquant des œuvres MergingService bien.

Mais le problème vient ici:

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

Le lien appellera mergeAccoungDao.update(ma) de mettre à jour une ligne dans DB.

Mais les données ne sont pas mises à jour vers DB, je pense que c'est parce que le DAO n'est pas enveloppé dans @Transaction ni tx:advice et aop tags.

Je me demande s'il existe un moyen d'obtenir par programme le gestionnaire de transactions et d'ouvrir/fermer manuellement la transaction?

Note: Je peux résoudre le problème en ajoutant ce code dans le XML de printemps:

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

Afin que sauver/la mise à jour/suppression du DAO fonctionnera comme un charme.

Mais je ne voudrais pas ajouter cette config. Parce qu'en fait, le DAO étend un AbstractDao, et il y a d'autres DB/OTI étendons cette 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 

Par conséquent, si cette CRUD de AbstractDAO est « conseillé » par ce transactionManagerApp, d'autres OTI peuvent avoir des problèmes, parce que d'autres Les DAO peuvent dépendre de txManagerForum, txManagerBank, txManagerUser ... etc.

Retour au problème, existe-t-il un moyen d'obtenir par programme txManager? Tels que:

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

Ou existe-t-il un meilleur moyen d'emballer une transaction dans le DAO?

Merci beaucoup.

Répondre

14

Vous devez injecter le gestionnaire de transactions dans la classe que vous souhaitez utiliser. Vous pouvez utiliser l'injection basée sur le constructeur ou la propriété pour cela ou utiliser l'autowiring. Si vous obtenez le gestionnaire de transaction, vous pouvez utiliser le support de transaction par programmation dans Spring pour démarrer et valider la transaction. Voici l'exemple de code de référence Spring 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(); 
     } 
    }); 
    } 
} 

Voir la reference pour plus de détails.

+0

Merci, ça marche! – smallufo