2010-09-15 2 views
5

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

Я попытался следующие:

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: идентификатор класса "класса aa.AssetType" указано по типу «класс aa.Adkeys» не имеет открытого конструктора no-args.

Так что мои вопросы:

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

@Nathan: Значит, это должно быть ошибкой. –

ответ

7

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

2.1.4 Первичные ключи и Entity Идентичность

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

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

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

+0

Он не говорит, что это возможно, но не говорит, что это невозможно. Он просто говорит: «Объекты, чьи первичные ключи используют типы, отличные от них, не будут переносимыми». Фактически, он также не говорит, что класс может использоваться как первичный ключ, но это возможно. – nanda

+0

это другое дело - встраиваемый id. см. мое обновление для части переносимости. – Bozho

+0

, поэтому я думаю, что это действительный запрос на повышение, не так ли? – nanda

4

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

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

Добавьте независимую колонку идентификатора, чтобы решить эту проблему.

+0

Я работаю со старой базой данных. Это может быть неплохой дизайн, но он есть. Перечисление - всего лишь куча жесткой ценности. – nanda

0

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

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

+0

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

Смежные вопросы