Нарушение ограничений ограничений в JPA 2.0

Рассмотрим следующий класс сущностей, используемый, например, с EclipseLink 2.0.2, где атрибут link не является первичным ключом, но уникальным, тем не менее.

@Entity
public class Profile {  
  @Id 
  private Long id;

  @Column(unique = true)
  private String link;

  // Some more attributes and getter and setter methods
}

Когда я вставляю записи с двойным значением для атрибута link, EclipseLink не бросает EntityExistsException, а бросает a DatabaseException, с сообщением, объясняющим, что было нарушено уникальное ограничение.

Это не кажется очень полезным, так как не было бы простого независимого от базы данных способа, чтобы поймать это исключение. Каким был бы способ справиться с этим?

Несколько вещей, которые я рассмотрел, следующие:

  • Проверка кода ошибки на DatabaseException - я боюсь, что этот код ошибки является исходным кодом ошибки для базы данных;
  • Проверка наличия Profile с определенным значением для link заранее - это, очевидно, приведет к огромному количеству излишних запросов.

Ответ 1

Когда я вставляю записи с двойным значением для атрибута ссылки, EclipseLink не бросает EntityExistsException

Да, и провайдер JPA не должен бросать EntityExistException в этом случае, вы не получите EntityExistException на чем-то еще, чем первичный ключ.

(...), но генерирует исключение DatabaseException с сообщением о том, что уникальное ограничение было нарушено.

Это очень WRONG от EclipseLink, поставщик JPA должен бросить PersistenceException или подкласс, но конечно, не конкретное исключение, например o.e.p.e.DatabaseException. Это ошибка, и ее следует сообщить, как я уже упоминал в предыдущем ответе .

Это не кажется очень полезным, так как не было бы простого независимого от базы данных способа, чтобы поймать это исключение. Каким был бы способ справиться с этим?

Тот же ответ, что и выше, см. в предыдущем ответе .

Ответ 2

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

protected Boolean isUniqueConstraintViolation(PersistenceException ex, Class entity) {

    if (((NonUniqueObjectException)ex.getCause()).getEntityName().equals(entity.getName())) {
        return true;
    }

    return false;
}