Нарушение ограничений ограничений в 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;
}