我在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 ...
我建议您考虑采用以下方法:
首先,我将方法@Transactional放在新服务中,因为它是从非事务性方法调用的,并且使用代理和注释会产生问题。然后我抓到异常: