У меня есть Entity, у которого есть первичный ключ /id, например:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
Это хорошо работает. Я использую EclipseLink для создания DDL-схемы, и столбец правильно создается следующим образом:
`id` bigint(20) NOT NULL AUTO_INCREMENT
Однако у меня есть несколько объектов, для которых я хочу сам указать PK (это небольшое приложение, которое передает данные из старой базы данных в новую, которую мы создаем). Если я укажу ID для POJO (используя setId(Long id)
) и сохраняю его, EclipseLink не сохраняет его (т.е. Запись сохраняется, но идентификатор автоматически генерируется eclipseLink).
Можно ли вручную указать значение столбца с именем @GeneratedValue?
Вот некоторые мысли по этому вопросу:
Я попытался обойти проблему, вообще не используя @GeneratedValue, но просто вручную определите столбец AUTO_INCREMENTed. Однако это заставляет меня вручную предоставлять идентификаторы всегда, поскольку EclipseLink проверяет первичный ключ (поэтому он может быть не нулевым, нулевым или отрицательным числом). Сообщение об исключении читает, что я должен указать eclipselink.id_validation, однако это, похоже, не имеет никакого значения (я аннотировал @PrimaryKey(validation = IdValidation.NONE)
, но все же получил то же сообщение).
Чтобы уточнить: Я использую EclipseLink (2.4.0) как провайдер персистентности, и я не могу отказаться от него (большие части проекта зависят от подсказок конкретных запросов, аннотаций, и классы).
EDIT (В ответ на ответы):
Пользовательское упорядочение: Я попытался реализовать свою собственную последовательность. Я попробовал подклассифицировать DefaultSequence, но EclipseLink скажет мне Internal Exception: org.eclipse.persistence.platform.database.MySQLPlatform could not be found
. Но я проверил: класс находится в пути к классам.
Итак, я подклассифицировал другой класс, NativeSequence:
public class MyNativeSequence extends NativeSequence {
public MyNativeSequence() {
super();
}
public MyNativeSequence(final String name) {
super(name);
}
@Override
public boolean shouldAlwaysOverrideExistingValue() {
return false;
}
@Override
public boolean shouldAlwaysOverrideExistingValue(final String seqName) {
return false;
}
}
Однако я получаю следующее:
javax.persistence.RollbackException: Exception [EclipseLink-7197] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null or zero primary key encountered in unit of work clone [de.dfv.datenbank.domain.Mitarbeiter[ id=null ]], primary key [null]. Set descriptors IdValidation or the "eclipselink.id-validation" property.
at org.eclipse.persistence.internal.jpa.transaction.EntityTransactionImpl.commitInternal(EntityTransactionImpl.java:102)
...
Caused by: Exception [EclipseLink-7197] (Eclipse Persistence Services - 2.4.0.v20120608-r11652): org.eclipse.persistence.exceptions.ValidationException
Exception Description: Null or zero primary key encountered in unit of work clone [de.dfv.datenbank.domain.Mitarbeiter[ id=null ]], primary key [null]. Set descriptors IdValidation or the "eclipselink.id-validation" property.
at org.eclipse.persistence.exceptions.ValidationException.nullPrimaryKeyInUnitOfWorkClone(ValidationException.java:1451)
...
(трассировка стека сокращена для ясности). Это то же самое сообщение, которое я получил раньше. Должен ли я подкласс NativeSequence? Если это так, я не знаю, что реализовать для абстрактных методов в Sequence или StandardSequence.
Также стоит отметить, что просто подклассификация (без переопределения каких-либо методов) класс работает так, как ожидалось. Тем не менее, returing false в shouldAlwaysOverrideExistingValue(...)
не генерирует ни одного значения вообще (я прошел через программу и getGeneratedValue()
не вызывается один раз).
Кроме того, когда я вставляю как 8 объектов определенного типа в транзакцию, он привел к 11 записям в базе данных (какого черта?!).
EDIT (2012-09-01): У меня все еще нет решения проблемы. Реализация моей собственной последовательности не помогла. Мне нужно, чтобы я мог явно не указывать идентификатор (поэтому он будет автоматически сгенерирован) и иметь возможность явно указывать идентификатор (поэтому он будет использоваться для создания записи в базе данных).
Я попытался определить столбец как auto_increment самостоятельно и ommit @GeneratedValue, однако проверка будет удалена и не позволит мне сохранить такую сущность. Если я укажу значение!= 0 и!= Ноль, mysql будет жаловаться на дублирующий первичный ключ.
У меня заканчиваются идеи и варианты, чтобы попробовать. Любые? (начиная щедрость)