Как мне перехватить исключение нарушения ограничения из EclipseLink? - PullRequest
12 голосов
/ 12 сентября 2011

Я использую EclipseLink в своем веб-приложении, и мне трудно изящно ловить и обрабатывать исключения, которые оно генерирует.Я вижу из этой темы , что похоже на подобную проблему, но я не вижу, как ее обойти или исправить.

Мой код выглядит так:

public void persist(Category category) {
    try {
        utx.begin();
        em.persist(category);
        utx.commit();
    } catch (RollbackException ex) {
           // Log something
    } catch (HeuristicMixedException ex) {
           // Log something
    } catch (HeuristicRollbackException ex) {
           // Log something
    } catch (SecurityException ex) {
           // Log something
    } catch (IllegalStateException ex) {
           // Log something
    } catch (NotSupportedException ex) {
           // Log something
    } catch (SystemException ex) {
           // Log something
    }
}

Когда persist () вызывается с сущностью, которая нарушает ограничение уникальности, я получаю взрыв исключений, которые регистрируются и регистрируются контейнером.

Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504):
  org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLIntegrityConstraintViolationException: The statement
  was aborted because it would have caused a duplicate key value in a unique or 
  primary key constraint or unique index identified by 'SQL110911125638570' 
   defined on 'CATEGORY'.
 Error Code: -1
 (etc)

Я пробовал следующее:

    try {
        cc.persist(newCategory);        
    } catch (PersistenceException eee) {
        // Never gets here
        System.out.println("MaintCategory.doNewCateogry(): caught: " + eee);
    } catch (DatabaseException dbe) {
        // Never gets here neither
        System.out.println("MaintCategory.doNewCateogry(): caught: " + dbe);            
    }

Я понимаю, что использование DataBaseException непереносимо, но мне нужно с чего-то начать.Исключения никогда не ловятся.Есть предложения?

Ответы [ 5 ]

8 голосов
/ 14 сентября 2011

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

Как выясняется в этом условии с EclipseLink, исключение, которое вы можете поймать при нарушении ограничения SQL, это RollBackException , который является результатом вызова em.commit () .Поэтому я изменил свой постоянный метод следующим образом:

public void persist(Category category) throws EntityExistsException {
    try {
        utx.begin();
        em.persist(category);
        utx.commit();
    } catch (RollbackException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
        throw new EntityExistsException(ex);
    } catch (HeuristicMixedException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (HeuristicRollbackException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (SecurityException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (IllegalStateException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (NotSupportedException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    } catch (SystemException ex) {
        Logger.getLogger(CategoryControl.class.getName()).log(Level.SEVERE, null, ex);
    }
}

Так что вызывающая сторона перехватывает EntityExistsException и предпринимает соответствующее действие.Журнал по-прежнему заполняется внутренними исключениями, но его можно отключить позже.

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

Если у кого-то есть лучший подход, пожалуйста, оставьте новый ответ или комментарий.

4 голосов
/ 13 апреля 2017

Отредактируйте свой файл persistence.xml, добавив следующее свойство:

имя свойства = "eclipselink.exception-handler" value = "your.own.package.path.YourOwnExceptionHandler"

Теперь создайтекласс YourOwnExceptionHandler (на правильном пакете).Требуется реализовать org.eclipse.persistence.exceptions.ExceptionHandler.

Создать конструктор без аргументов и требуемый метод handleException (...).

Внутри этого метода вы можете пойматьисключения!

3 голосов
/ 12 сентября 2011

EclipseLink должен генерировать исключение PersitenceException или RollbackException только в зависимости от среды и порядка операций, которые вы вызываете в EntityManager.Каков ваш уровень регистрации?Вполне вероятно, что вы видите, что эти исключения регистрируются EclipseLink, но генерируются только как причины RollbackException.

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

1 голос
/ 04 июня 2015

Я использую это.

if (!ejbGuardia.findByPkCompuestaSiExiste(bean.getSipreTmpGuardiaPK())) {
    ejbGuardia.persist(bean);
    showMessage(ConstantesUtil.MENSAJE_RESPUESTA_CORRECTA, SEVERITY_INFO);
} else {
    showMessage("Excel : El registro ya existe. (" + bean.toString() + ")  ", SEVERITY_ERROR);
}

и мою функцию сверху:

public boolean findByPkCompuestaSiExiste(Object clasePkHija) throws ClassNotFoundException {
    if (null != em.find(this.clazz, clasePkHija)) {
        return true;
    }
    return false;
}

При этом мне не нужно программировать валидацию для каждого Persist, что обычно в моем DAOКлассы.

1 голос
/ 22 ноября 2014

Я использую Spring Boot 1.1.9 + EclipseLink 2.5.2. Это единственный способ, которым я могу поймать ConstraintViolationException. Обратите внимание, что моя handleError(ConstraintViolationException) - очень простая реализация, которая просто возвращает первое найденное нарушение.

Обратите внимание, что этот код также был необходим при переходе на Hibernate 4.3.7 и Hibernate Validator 5.1.3.

Похоже, что добавление PersistenceExceptionTranslationPostProcessor exceptionTranslation() к моему классу персистентности JavaConfig также не имеет никакого эффекта.


import javax.persistence.RollbackException;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.TransactionSystemException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
class GlobalExceptionHandler
{
    @ExceptionHandler(TransactionSystemException.class)
    public ResponseEntity<Object> handleError(final TransactionSystemException tse)
    {
        if(tse.getCause() != null && tse.getCause() instanceof RollbackException)
        {
            final RollbackException re = (RollbackException) tse.getCause();

            if(re.getCause() != null && re.getCause() instanceof ConstraintViolationException)
            {
                return handleError((ConstraintViolationException) re.getCause());
            }
        }

        throw tse;
    }


    @ExceptionHandler(ConstraintViolationException.class)
    @SuppressWarnings("unused")
    public ResponseEntity<Object> handleError(final ConstraintViolationException cve)
    {
        for(final ConstraintViolation<?> v : cve.getConstraintViolations())
        {
            return new ResponseEntity<Object>(new Object()
            {
                public String getErrorCode()
                {
                    return "VALIDATION_ERROR";
                }


                public String getMessage()
                {
                    return v.getMessage();
                }
            }, HttpStatus.BAD_REQUEST);
        }

        throw cve;
    }
}
...