Как избежать Транзакция была отмечена только для отката;не может выполнить в асинхронной задаче - PullRequest
0 голосов
/ 30 октября 2019

Я разработал API для интеграции файла в базу данных в асинхронной задаче. Я хочу, чтобы весь мой файл был обработан, и я записываю каждую ошибку в базу данных.

Мой API вызывает эту услугу

@Service
public class ImportFichier {

    @Async("taskExecutor")
    public void importReference(ImportFichierDTO importFichierDTO,
                                List<Reference> references,
                                Long idEntite,
                                Long currentUserId,
                                boolean update){
        log.debug("Request to importReference pour entite : {}", idEntite);

        for(Reference reference : references) {
            if (update) {
                referentielService.update(idEntite, reference, currentUserId, importFichierDTO.getId());
            } else {
                referentielService.add(idEntite, reference, currentUserId, importFichierDTO.getId());
            }
        }

        // mise à jour de l'heure de fin du traitement d'import
        importFichierDTO.setDateFin(ZonedDateTime.now());
        importFichierService.save(importFichierDTO);

        return;
    }

Для добавления данных, лечение вызывает эту услугу:

@Service
@Transactional
public class ReferentielCompteurServiceImpl implements ReferentielCompteurService {
 ....

@Override
@Transactional(noRollbackFor = {CustomException.class, ConstraintViolationException.class})
public Compteur add(Compteur compteur, Long entiteMereId, Long entiteId, Long userId, Long importId) {

    Optional<ArticleEtat> articleEtat = articleEtatRepository.findOneByCode(compteur.getCodeEtat());
    if (!articleEtat.isPresent()) {
        if (importId > 0) {
            importFichierTraceService.add(importId, compteur.getUuidReference().toString(), CustomError.ERROR_ARTICLE_ETAT_NOT_FOUND.getErrorDescription());
            return compteur;
        } else {
            throw new CustomException(CustomError.ERROR_ARTICLE_ETAT_NOT_FOUND);
        }
    }

    ....
    ReferentielCompteurDTO result = save(referentielCompteurDTO, importId);

И метод "сохранить" в той же службе:

@Override
@Transactional(noRollbackFor = {CustomException.class, ConstraintViolationException.class})
public ReferentielCompteurDTO save(ReferentielCompteurDTO referentielCompteurDTO, Long importId) {
    log.debug("Request to save ReferentielCompteur : {}", referentielCompteurDTO);

    if (referentielCompteurDTO.getDateCreation() == null) {
        referentielCompteurDTO.setDateCreation(ZonedDateTime.now());
    }
    referentielCompteurDTO.setDateModification(ZonedDateTime.now());

    ReferentielCompteur referentielCompteur = referentielCompteurMapper.toEntity(referentielCompteurDTO);

    try {
        referentielCompteur = referentielCompteurRepository.save(referentielCompteur);
    } catch (ConstraintViolationException cve) {
        importFichierTraceService.add(importId, referentielCompteurDTO.getReferenceId().toString(), cve.getMessage());
    }

    return referentielCompteurMapper.toDto(referentielCompteur);
}

Когда я генерирую исключение ConstraintViolationException, у меня возникает следующее исключение:

 Transaction was marked for rollback only; cannot commit' and exception = 'Transaction was marked for rollback only; cannot commit; nested exception is org.hibernate.TransactionException: Transaction was marked for rollback only; cannot commit'

org.springframework.orm.jpa.JpaSystemException: Transaction was marked for rollback only; cannot commit; nested exception is org.hibernate.TransactionException: Transaction was marked for rollback only; cannot commit
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:312)
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:223)
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:540)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:746)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:714)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:532)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:304)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)

Я вижу несколько сообщений, но я не понимаю, как решить эту проблему, и возможно ли это

Можете ли вы помочь мне, пожалуйста?

1 Ответ

0 голосов
/ 30 октября 2019

Следуя совету M.Deinum, я пытаюсь:

для importFichierTraceService.add

@Transactional(propagation = REQUIRES_NEW)
public void add(Long importId, String line, String message) {

Я удаляю @Transactional и ловлю Exception

@Override
public ReferentielCompteurDTO save(ReferentielCompteurDTO referentielCompteurDTO, Long importId) {

Идобавить улов Исключение в:

@Override
public Compteur add(Compteur compteur, Long entiteMereId, Long entiteId, Long userId, Long importId) { 

try {
        result = save(referentielCompteurDTO, importId);
    } catch (ConstraintViolationException cve) {
        importFichierTraceService.add(importId, referentielCompteurDTO.getReferenceId().toString(), cve.getMessage());
        return compteur;
    }

Результат тот же

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...