RetryingTransactionHandler在露天中的作用是什么

时间:2011-07-31 06:41:12

标签: alfresco

一旦您需要在存储库中创建事务以使用RetryingTransactionHandler来实现事务,Alfresco会建议程序员。

有人能给我一个澄清吗?

特别是我在谈论像这样的代码

RetryingTransactionCallback<String> callback = new RetryingTransactionCallback<String>(){
 public String execute() throws Throwable {
     // doProcess must be invoked within user context.
 AuthenticationUtil.runAs(new RunAsWork<String>(){
 public String doWork()throws Exception{
 try {      
     if(getOperationType().equals(OperationTypes.CREATE_ORGANIZATION_OPERATION)){
 RetryingTransactionHelper txnHelper = 
     Repository.getRetryingTransactionHelper(FacesContext.getCurrentInstance());
     txnHelper.doInTransaction(doProcessActionCallbackOperations.CreateOrganizationCallback, false, true);
                        }
                    } catch(Throwable e){

                    }
                    return "";
                }
            }, AuthenticationUtil.getSystemUserName());
            return "";
        }
    };  
    try {
        RetryingTransactionHelper txnHelper = Repository.getRetryingTransactionHelper(FacesContext.getCurrentInstance());
        txnHelper.doInTransaction(callback, false, true);
    } catch (Throwable e) {
        if (e instanceof ReportedException == false) {
            Utils.addErrorMessage(formatErrorMessage(e), e);
        }
        ReportedException.throwIfNecessary(e);
    }

此外,正如您所知,我使用AuthenticationUtils.runAs()。

那么你可以帮我理解这段代码中的不同键,如RetryingTransaction&amp; AuthenticationUtils?

2 个答案:

答案 0 :(得分:5)

RetryingTransactionHelper确保您提供的callback在交易中执行。此外,顾名思义,如果事务因某些原因失败(例如,callback代码中没有正确捕获异常,或者您尝试从两个不同的线程同时更改存储库中的相同内容) ,相同的事务将被适当地回滚并重新执行(“重试”)一段可配置的次数(默认值:20)。这比手动处理交易更容易。

在您发布的代码中,您在两个事务中将调用嵌套到doProcessActionCallbackOperations.CreateOrganizationCallback(因为doInTransaction的最后一个参数始终为true,即requiresNew) ,在callback执行之前创建的外部,在callback本身内创建的内部。在我看来,你可以摆脱内部交易,但这取决于你。事务可以嵌套,即使内部事务中的失败很可能使整个事务堆无效。

AuthenticationUtils.runAs工具允许您使用与当前用户不同的权限来执行逻辑部分。在内部,用户凭据存储为ThreadLocal个参数。在您的情况下,AuthenticationUtil.runAs负责临时更改此类ThreadLocal以允许内部回调始终以最高权限级别(即系统)执行,而不管哪个用户正在执行代码。还存在当前没有登录用户的情况,例如在预定的工作。然后,AuthenticationUtils.runAs允许您访问存储库中的内容,通常指定systemadmin个用户。

答案 1 :(得分:4)

为了澄清一点,RetryingTransactionHelper只有在抛出的异常属于特定类型时才会重试该操作。主要是与并发情况下的输家有关的例外:

 /**
 * Exceptions that trigger retries.
 */
@SuppressWarnings({ "rawtypes" })
public static final Class[] RETRY_EXCEPTIONS;
static
{
    Class<?>[] coreClasses = new Class[] {
                ConcurrencyFailureException.class,
                DeadlockLoserDataAccessException.class,
                StaleObjectStateException.class,
                JdbcUpdateAffectedIncorrectNumberOfRowsException.class,     // Similar to StaleObjectState
                LockAcquisitionException.class,
                ConstraintViolationException.class,
                UncategorizedSQLException.class,
                SQLException.class,
                BatchUpdateException.class,
                DataIntegrityViolationException.class,
                StaleStateException.class,
                TooManyResultsException.class,              // Expected one result but found multiple (bad key alert)
                ObjectNotFoundException.class,
                CacheException.class,                       // Usually a cache replication issue
                SQLGrammarException.class, // Actually specific to MS SQL Server 2005 - we check for this
                LockTryException.class
                };

我认为这足以让其中一个事务处于异常堆栈中,而不是最后一个事务。我还认为你可以通过放置一个实现org.alfresco.repo.transaction.DoNotRetryException接口的异常来避免重试。