标记为“mandatory”的事务找不到现有事务 DAO 类中的异常。

7
我有一个被注释为组件的活动类,它调用一个操作类:
 @Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = NonRetryableException.class)
 public ExecuteTemplateResponse executeTemplate(ExecuteTemplateRequest request)
 {
      actionExecutionContext = action.execute(actionExecutionContext);
 }

我的Action类也使用@Component进行了注解,并具有以下execute方法:

@Transactional(propagation = Propagation.MANDATORY)
@Override
public ActionExecutionContext execute(ActionExecutionContext actionExecutionContext)
{
    iogl = ioglDao.create(iogl);
    return actionExecutionContext;
}
ioglDao类被注解为@Repository,具有以下创建方法:
@Transactional(propagation = Propagation.MANDATORY)
@Override
public InventoryOwnerGroupLocation create(InventoryOwnerGroupLocation iogl)
{
    // injected
    Session session = sessionFactory.getCurrentSession();

    session.save(iogl);

    return iogl;
}

我认为事务应该从服务层传播到dao类,但似乎并没有。我得到了标记为'mandatory'的事务的不存在异常。

为什么事务没有传播到我的DAO类?

编辑:添加了所有的activity类。

@Service("FASelfServiceMappingService")
@Component
public class ExecuteTemplateActivity extends Activity
{
    private final static Logger logger = Logger.getLogger(ExecuteTemplateActivity.class);


// mapper framework to interact with DynamoDB database
private final DynamoDBMapper dynamoDBMapper;

// class to convert external models to internal models
private final InternalModelToDynamoDBModelConverter internalToDynamoDBConverter;
private final InternalModelToOracleModelConverter internalToOracleConverter;
private final CoralModelToInternalModelConverter coralToInternalConverter;

// class to generate list of actions
private final ActionGenerator actionGenerator;

// status constants
private static final String STATUS_COMPLETED = "COMPLETED";
private static final String STATUS_FAILED = "FAILED";

@Inject
public ExecuteTemplateActivity(InternalModelToDynamoDBModelConverter internalToDynamoDBConverter,
                               InternalModelToOracleModelConverter internalToOracleConverter,
                               CoralModelToInternalModelConverter coralToInternalConverter,
                               ActionGenerator actionGenerator,
                               DynamoDBMapper dynamoDBMapper)
{
    this.internalToDynamoDBConverter = internalToDynamoDBConverter;
    this.internalToOracleConverter = internalToOracleConverter;
    this.coralToInternalConverter = coralToInternalConverter;
    this.actionGenerator = actionGenerator;
    this.dynamoDBMapper = dynamoDBMapper;
}


@Transactional(propagation = Propagation.REQUIRED, readOnly = false, rollbackFor = NonRetryableException.class)
 @Operation("ExecuteTemplate")
 public ExecuteTemplateResponse executeTemplate(ExecuteTemplateRequest request) throws RetryableException, NonRetryableException
 {
     try
     {
         logger.info("Input given: " + request);

         // convert request input to an internal request
         Request internalRequest = coralToInternalConverter.coralRequestToInternal(request);
         logger.info("Successfully converted External Request to internal Request.");

         String templateName = getTemplateName(internalRequest);
         logger.info("Template Name extracted from the request: " + templateName);

         Template template = getTemplateFromDynamo(internalRequest, templateName);
         logger.info("Template read from dynamoDB table: " + template);

         // Generate a map from string to Action objects associated with the retrieved template
         List<Action> listOfActions = actionGenerator.generateActions(template.getActions());
         logger.info("Actions generated for template " + templateName + ": " + listOfActions);

         // Generate the action context for actions to pass to each other to keep track of state
         ActionExecutionContext actionExecutionContext = internalToOracleConverter.inputsToActionExecutionContext(internalRequest.getInputs());
        logger.info("Built ActionExecutionContext:" + actionExecutionContext);

         // execute the actions
         for (Action action : listOfActions)
         {
             actionExecutionContext = action.execute(actionExecutionContext);
         }
         logger.info("All actions executed successfully.");
         // request was completed successfully, create request in Request table
         String requestId = createRequestInDynamo(internalRequest, STATUS_COMPLETED);

         ExecuteTemplateResponse executeTemplateResponse = new ExecuteTemplateResponse();
         executeTemplateResponse.setRequestId(requestId);

         logger.info("Service call "+ this.getClass() +" succeeded.");
         return executeTemplateResponse;
         }
     catch (RetryableException re)
     {
         logger.error("Retryable Exception occurred in activity.", re);
         throw re;
     }
     catch (NonRetryableException nre)
     {
         logger.error("NonRetryable Exception occurred in activity.", nre);
         throw nre;
     }
     catch (Exception e)
     {
         logger.error("Unknown Exception occurred in activity.", e);
         throw new NonRetryableException("Unexpected error", e);
     }
 }

/**
 * extracts the templateName from the internalRequest
 * @param internalRequest internal model of the request
 * @return templateName
 */
private String getTemplateName(Request internalRequest)
{
    Validate.notNull(internalRequest, "internalRequest must not be null.");

    String templateName;
    try
    {
        // extract template name from request
        templateName = internalRequest.getTemplateName();
        Validate.notNull(templateName, "templateName must not be null.");
    }
    catch (IllegalArgumentException iae)
    {
        createRequestInDynamo(internalRequest, STATUS_FAILED);
        logger.error("Invalid input: templateName is null.");
        throw new NonRetryableException("Invalid input: templateName is null.", iae);
    }

    return templateName;
}

/**
 * Retrieves the template object associated with given templateName
 * @param internalRequest internal model of request
 * @param templateName name of template to retrieve
 * @return Template object
 */
private Template getTemplateFromDynamo(Request internalRequest, String templateName)
{
    Validate.notNull(internalRequest, "internalRequest must not be null.");
    Validate.notNull(templateName, "templateName must not be null.");

    Template template;
    try
    {
        // read the template with given template name from Templates table
        template = dynamoDBMapper.load(Template.class, templateName);
    }
    catch (DynamoDBMappingException ddbme)
    {
        createRequestInDynamo(internalRequest, STATUS_FAILED);
        logger.error("Reading template from dynamoDB table failed.", ddbme);
        throw new NonRetryableException("Incorrect class annotation or incompatible with class", ddbme);
    }
    catch (AmazonClientException ace)
    {
        createRequestInDynamo(internalRequest, STATUS_FAILED);
        logger.error("Reading template from dynamoDB table failed.", ace);
        throw new RetryableException("Error when loading template from dynamoDB", ace);
    }

    return template;
}

编辑:

事务管理器配置:

   <tx:annotation-driven transaction-manager="txManager"
                          mode="proxy" proxy-target-class='true' />

    <bean id="txManager"
          class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
        <property name="dataSource" ref="dataSource" />
    </bean>

你能展示更多关于你的activity类的内容吗(尤其是在哪里注入你的动作类)? - dunni
还有调用executeTemplate方法的部分。你是从另一个类中调用它还是从你的活动类内部调用它? - dunni
我已添加了所有的活动类。我正在单元测试中测试活动类,并从单元测试中调用executeTemplate。 - CoderGuy
3个回答

2

我曾在使用Spring WebFlux时遇到同样的异常。

问题:

repository.findByUserId(id);

解决方案:
@Autowired
private TransactionTemplate transactionTemplate;

transactionTemplate.execute(transactionStatus -> identInformationRepository.findByUserId(id));

0
在某些情况下,可以通过以下方式解决问题:
尝试将代码与发生错误的事务分离开来,在单独的方法中进行注入,最好在启动时进行。
在 void 开始之前添加 @Transactional。
例如:
BEFORE
public void mainProces(){
  System.out.println("Hello, i save my name");
  SQL(select)
  SQL(save)
}

之后

@Transactional
    public void secondProces(){
            SQL(save)
    }

public void mainProces(){
  System.out.println("Hello, i save my name");
  secondProces();
  SQL(select)
}

-3

是的,我按照指南操作了。我已经更新了我的Spring事务管理问题。 - CoderGuy
谢谢。还有一些问题:在activity类中注入sessionFactory是否有效?组件扫描配置正确(<context:component-scan base-package="com.youpackage..." />)?由于您已经使用了'@Service',因此activity类上的'@Component'注释是否必要? - Vladimiro Corsi
我在activity类中没有尝试过注入sessionFactory,因为那里不需要。它直接注入到DAO类中。我应该尝试吗?是的,组件扫描已正确配置。activity类上的@Service注释来自另一个内部框架,而不是Spring。 - CoderGuy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接