@@ Transactional方法在异常和多线程Wildlfy CDI上插入值

问题描述 投票:1回答:2

我在CDI bean中有一个方法,它是事务性的,如果出错,它将在数据库中创建带有异常消息的条目。 RESTendpoint可以以多线程方式调用此方法。

我们有一个SQL约束来避免数据库重复”>

    @Transactional
public RegistrationRuleStatus performCheck(RegistrationRule rule, User user) {

    try {
        //check if rule is dependant of other rules and if all proved, perform check
        List<RegistrationRule> rules = rule.getRuleParentDependencies();
        boolean parentDependenciesAreProved = true;

        if (!CollectionUtils.isEmpty(rules)) {
            parentDependenciesAreProved = ruleDao.areParentDependenciesProved(rule,user.getId());
        }

        if (parentDependenciesAreProved) {
            Object service = CDI.current().select(Object.class, new NamedAnnotation(rule.getProvider().name())).get();
            Method method = service.getClass().getMethod(rule.getProviderType().getMethod(), Long.class, RegistrationRule.class);

            return (RegistrationRuleStatus) method.invoke(service, user.getId(), rule);

        } else {
            RegistrationRuleStatus status = statusDao.getStatusByUserAndRule(user, rule);
            if (status == null) {
                status = new RegistrationRuleStatus(user, rule, RegistrationActionStatus.START, new Date());
                statusDao.create(status);
            }

            return status;
        }
    } catch (Exception e) {
        LOGGER.error("could not perform check {} for provider {}", rule.getProviderType().name(), rule.getProvider().name(), e.getCause()!=null?e.getCause():e);

        return statusDao.createErrorStatus(user,rule,e.getCause()!=null?e.getCause().getMessage():e.getMessage());
    }
}

创建错误方法:

@Transactional
public RegistrationRuleStatus createErrorStatus(User user, RegistrationRule rule, String message) {
     RegistrationRuleStatus status = getStatusByUserAndRule(user, rule);
     if (status == null) {
         status = new RegistrationRuleStatus(user, rule, RegistrationActionStatus.ERROR, new Date());
         status.setErrorCode(CommonPropertyResolver.getMicroServiceErrorCode());
         status.setErrorMessage(message);
         create(status);
     }else {
         status.setStatus(RegistrationActionStatus.ERROR);
         status.setStatusDate(new Date());
         status.setErrorCode(CommonPropertyResolver.getMicroServiceErrorCode());
         status.setErrorMessage(message);
         update(status);
     }
     return status;
}

问题是方法同时被调用了两次,记录的错误是DuplicateException,但我们不希望这样。我们在一开始就验证对象是否已经存在,但是我认为它是在同一时间被调用的。

JAVA8 / wildlfy / CDI / JPA / eclipselink

任何主意吗?

我在CDI bean中有一个方法,它是事务性的,如果出错,它将在数据库中创建带有异常消息的条目。 RESTendpoint可以以多线程方式调用此方法。我们有一个SQL ...

java jdbc eclipselink cdi wildfly-11
2个回答
0
投票

我建议您考虑采用以下方法:


0
投票

首先,我将方法@Transactional放在新服务中,因为它是从非事务性方法调用的,并且使用代理和注释会产生问题。然后我抓到异常:

© www.soinside.com 2019 - 2024. All rights reserved.