2010-03-15 7 views
5

sto usando Spring.net 1.2 con NHibernate 2.0.1.
All'interno del mio progetto sto affrontando alcuni problemi di deadlock e oltre alle modifiche del database per ridurre al minimo l'occorrenza vorrei implementare Springs RetryAdvice per gestire questo.
Non riesco a trovare alcun esempio funzionante su come configurare questo. Il riferimento sembra essere chiaro su come usarlo, ma in qualche modo non riesco a farlo funzionare.Come configurare RetryAdvice ed ExceptionTranslation per Deadlocks usando NHibernate e Spring

<!--Used to translate NHibernate exception to Spring.DataAccessExceptions-->  
<object type="Spring.Dao.Attributes.PersistenceExceptionTranslationPostProcessor, Spring.Data"/> 

<!--ExceptionHandler performing Retry on Deadlocks--> 
<object name="ExceptionHandlingAdvice" type="Spring.Aspects.RetryAdvice, Spring.Aop"> 
    <property name="retryExpression" value="on exception name DeadLockLoserException retry 3x rate (1*#n + 0.5)"/> 
</object> 

ho aggiunto l'attributo [repository] ai miei DAO per ottenere ExceptionTranslation abilitato e ha cercato di aggiungere il RetryAdvice al TransactionProxyFactoryObject sto usando, ma non funzionerà. Non capisco dove mettere questo consiglio. Devo dichiarare un PointCut per aggiungerlo o come posso farlo funzionare come previsto.

Thx in anticipo - qualsiasi aiuto apprezzato.

risposta

9

Dopo un mese e mezzo di attesa per qualcuno che risolve il problema, ho finalmente trovato il tempo di elaborare da solo la soluzione. In realtà non era così difficile pensavo che fosse. Forse è per questo che non sono riuscito a trovare alcun buon esempio. Quindi qui si va: Il seguente test mostrerà l'utilizzo:

Configurazione: (SessionFactory e TransactionManager ecc omesso per brevità)

<!-- Retries the Tx after DeadlockExceptions --> 
    <object name="ExceptionHandlingAdvice" type="Spring.Aspects.RetryAdvice, Spring.Aop"> 
    <property name="retryExpression" value="on exception name DeadlockLoserDataAccessException retry 3x delay 1s"/> 
    </object> 

    <!--A Transaction-Configuration for our DAO-MOCK--> 
    <object id="TxProxyConfigurationTemplate" abstract="true" type="Spring.Transaction.Interceptor.TransactionProxyFactoryObject, Spring.Data"> 
    <property name="PlatformTransactionManager" ref="HibernateTransactionManager"/> 

    <property name="TransactionAttributes"> 
     <name-values> 
     <add key="ThrowDeadLock*" value="PROPAGATION_REQUIRED"/> 
     </name-values> 
    </property> 
    </object> 

    <object id="MockDaoTxPFO" parent="TxProxyConfigurationTemplate"> 
    <property name="Target" ref="MockDao"/> 
    </object> 

    <!--The ProxyFactoryObject based on the DAO-Mock interface--> 
    <object id="MockDao" type="Spring.Aop.Framework.ProxyFactoryObject, Spring.Aop" > 
    <property name="proxyInterfaces" value="RetryAdvice.IDaoMock"/> 
    <property name="target" ref="MockDaoImpl"/> 
    <property name="interceptorNames"> 
     <list> 
     <value>ExceptionHandlingAdvice</value> 
     </list> 
    </property> 
    </object> 

    <!--Mocked DAO Implementation --> 
    <object id="MockDaoImpl" type="RetryAdvice.DaoMock, RetryAdvice"> 
    <constructor-arg name="maxExceptionCount" value="2" /> 
    </object> 

deriso Dao: Questo DAO getterà DeadLockLooserExceptions due volte e poi passare.

public interface IDaoMock 
{ 
    void ThrowDeadLock(); 
    int MethodCallCount { get; } 
} 

[Repository] 
public class DaoMock : IDaoMock 
{ 
    private int maxExceptionCount; 
    public int MethodCallCount { get; private set; } 

    public DaoMock(int maxExceptionCount) 
    { 
     this.maxExceptionCount = maxExceptionCount; 
    } 

    public void ThrowDeadLock() 
    { 
     MethodCallCount++; 
     if (MethodCallCount <= maxExceptionCount) 
     { 
      throw new DeadlockLoserDataAccessException("FAKE", new HibernateException("This is a fake Exception.", null)); 
     } 
    } 

Il Test:

[Test] 
public void RetryAdviceTest() 
{ 
    IDaoMock mockDao = (IDaoMock)this.appContext.GetObject("MockDaoTxPFO"); 
    mockDao.ThrowDeadLock(); 
    Assert.That(mockDao.MethodCallCount, Is.EqualTo(3)); 
} 

Eventuali suggerimenti o osservazioni apprezzati.

+0

Per completare questo: ExceptionTranslation si ottiene automaticamente quando si utilizza HibernateTemplate come effettivamente faccio. – zoidbeck