Использование enum в качестве идентификатора - PullRequest
5 голосов
/ 15 сентября 2010

Используя JPA, можем ли мы определить перечисление как идентификатор сущности?

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

public enum AssetType {
   ....
}

@Entity
@IdClass(AssetType.class)
public class Adkeys {

   private AssetType type;

   @Id
   @Enumerated(EnumType.STRING)
   @Column(nullable = false)
   public AssetType getType() {
      return type;
   }

}

Используя OpenJPA, он жалуется:

org.apache.openjpa.persistence.ArgumentException: класс id "class aa.AssetType", определенный типом "class aa.Adkeys", не имеет открытого конструктора без аргументов.

Итак, мои вопросы:

  • можем ли мы использовать enum в качестве идентификатора для сущности в JPA?(т.е. есть ошибка в OpenJPA)
  • или я где-то ошибаюсь?
  • и есть ли способ обойти эту проблему?

Ответы [ 4 ]

7 голосов
/ 15 сентября 2010

Спецификация JPA не говорит, что это возможно:

2.1.4 Первичные ключи и идентификация объекта

Первичный ключ (или поле или свойство составного первичного ключа)) должен быть одного из следующих типов: любой тип примитива Java;любой примитивный тип обертки;java.lang.String;java.util.Date;java.sql.Date.В целом, однако, приблизительные числовые типы (например, типы с плавающей запятой) никогда не должны использоваться в первичных ключах.Объекты, чьи первичные ключи используют типы, отличные от этих, не будут переносимыми.

Если вы действительно хотите иметь фиксированное количество записей во время компиляции для данного объекта, вы можете использовать String илиint первичный ключ и присвоение ему AssetType.FOO.name() или AssetType.FOO.ordinal()

И непереносимый здесь означает, что некоторый поставщик сохраняемости может поддерживать другие функции, но он может не работать для другого поставщика.Как и в enum - если поставщик персистентности имеет специальную поддержку для него, он не пытается создать его экземпляр, а обрабатывает его специально после проверки, если class.isEnum(), тогда он может работать.Но, похоже, ваш поставщик персистентности этого не делает.

4 голосов
/ 15 сентября 2010

Нет, вы не можете использовать перечисления как ID, потому что JPA не позволяет определять ваше собственное отображение для столбцов идентификаторов (они должны быть int или long или что-то, что JPA может создать с new).

Идентификаторы не должны быть бизнес-ключом (в вашем случае: тип). Использование бизнес-ключа в качестве идентификатора является распространенной ошибкой при проектировании БД, и его следует избегать, поскольку в дальнейшем это вызовет всевозможные проблемы.

Добавьте независимый столбец идентификатора для решения проблемы.

2 голосов
/ 28 мая 2011

OpenJPA - единственный поставщик JPA, который не поддерживает это.См. Поддержка Enum в качестве типа первичного ключа

0 голосов
/ 15 сентября 2010

Вы действительно хотите это сделать?Эта конструкция не позволяет изменять ключи перечисления базы данных без обновления перечисления в коде (сбой при загрузке) и наоборот (сбой ограничения).Почему бы вам просто не создать таблицу AssetType с int pk и name, а Adkeys иметь внешний ключ для AssetType.id как pk?

Вы можете загрузить AssetTypes из БД при запуске, если вам нужноперечислить их в вашем приложении.

...