Сохранение перечислений с JPA 2.0 возможно, но нет хорошего способа сделать это. Используя аннотацию @Enumerated , вы можете использовать EnumType.ORDINAL или EnumType.STRING для сопоставления значения перечисления с его представлением в базе данных. Но оба варианта имеют некоторые недостатки, которые мы обсудим в первой части этой статьи. Во второй части я покажу вам, как избежать этих недостатков с помощью конвертера типов JPA 2.1.
Сохранение перечислений с JPA 2.0
EnumType.ORDINAL использует возвращаемое значение Enum.ordinal () для сохранения перечисления. Таким образом, первое значение перечисления будет отображаться в 0, второе в 1 и так далее. Хотя это выглядит компактным и простым в использовании, оно вызывает проблемы при изменении перечисления. Удаление перечислимых значений или добавление нового значения где-то между ними изменит отображение всех следующих значений, например:
перед:
1
2
3
4
|
Vehicle: CAR -> 0 TRAIN -> 1 PLANE -> 2 |
после:
1
2
3
4
5
|
Vehicle: CAR -> 0 BUS -> 1 TRAIN -> 2 PLANE -> 3 |
Добавление Bus во второй позиции потребует обновления базы данных для исправления отображения enum.
EnumType.STRING выглядит как лучший вариант. Он использует строковое представление перечисления, чтобы сохранить его в базе данных. Таким образом, добавление или удаление значений не изменит отображение. Но это представление может быть довольно многословным, и переименование значения enum нарушит отображение.
перед:
1
2
3
4
|
Vehicle: CAR -> CAR TRAIN -> TRAIN PLANE -> PLANE |
после:
1
2
3
4
5
|
Vehicle: CAR -> CAR BUS -> BUS TRAIN -> TRAIN PLANE -> PLANE |
Использование конвертера типов JPA 2.1
JPA 2.1 Type Converter предоставляет третий и, на мой взгляд, лучший вариант. Преобразователь типов позволяет нам реализовывать методы для преобразования значения атрибута сущности в его представление базы данных и обратно. Я не буду вдаваться в подробности о том, как реализовать конвертер типов, потому что я уже делал это в одной из моих предыдущих статей .
Реализуя наше собственное отображение, мы можем выбрать компактное представление базы данных и убедиться, что изменение перечисления никоим образом не нарушит существующее отображение. В следующем примере показано, как реализовать преобразователь типов для перечисления Vehicle:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
|
@Converter (autoApply = true ) public class VehicleConverter implements AttributeConverter<Vehicle, String> { @Override public String convertToDatabaseColumn(Vehicle vehicle) { switch (vehicle) { case BUS: return "B" ; case CAR: return "C" ; case PLANE: return "P" ; case TRAIN: return "T" ; default : throw new IllegalArgumentException( "Unknown value: " + vehicle); } } @Override public Vehicle convertToEntityAttribute(String dbData) { switch (dbData) { case "B" : return Vehicle.BUS; case "C" : return Vehicle.CAR; case "P" : return Vehicle.PLANE; case "T" : return Vehicle.TRAIN; default : throw new IllegalArgumentException( "Unknown value: " + dbData); } } } |
VehicleConverter отображает значение перечисления в односимвольную строку. Объявляя его с помощью @Converter (autoApply = true), мы сообщаем провайдеру JPA использовать этот Type Mapper для сопоставления всех перечислений Vehicle. Поэтому нам не нужно указывать конвертер для каждого атрибута сущности типа Vehicle.
Но есть одна вещь, о которой мы должны позаботиться, и если вы читали мою предыдущую статью о JPA Type Converter, вы, возможно, уже подумали. Преобразователь типов нельзя применять к атрибутам, помеченным @Enumerated. Таким образом, мы должны убедиться, что в наших атрибутах сущности типа Vehicle нет аннотации @Enumerated.
Вывод
Мы реализовали простой конвертер типов, который использует наши собственные правила для преобразования перечисления Vehicle в его представление базы данных. Таким образом, мы можем быть уверены, что изменение значений перечисления Vehicle не нарушит существующие / оставшиеся отображения.
- Если вы хотите попробовать это самостоятельно, вы можете найти исходный код на github: https://github.com/someblytsonjava/JPA2.1-EnumConverter
Ссылка: | Преобразователь типов JPA 2.1 — лучший способ сохранить перечисления от нашего партнера по JCG Торбена Янссена из блога Некоторые мысли о Java (EE) . |