Вступление
Проект hibernate-types
открытым исходным кодом позволяет отображать JSON, ARRAY, YearMonth
, Month
или столбцы, специфичные для базы данных (например, адреса INET).
В этой статье мы рассмотрим, как можно сопоставить тип Enum PostgreSQL с массивом Java при использовании JPA и Hibernate.
Maven зависимость
Прежде всего, вам нужно настроить следующую зависимость Maven в pom.xml
конфигурации вашего проекта pom.xml
:
1
2
3
4
5
|
< dependency > < groupId >com.vladmihalcea</ groupId > < artifactId >hibernate-types-52</ artifactId > < version >2.3.5</ version > </ dependency > |
Если вы используете более старые версии Hibernate, обратитесь к репозиторию GitHub hibernate-types
для получения дополнительной информации о зависимости соответствия для текущей версии Hibernate.
Модель предметной области
Давайте предположим, что в нашей схеме базы данных есть следующее перечисление sensor_state
PostgreSQL:
1
2
3
4
5
|
CREATE TYPE sensor_state AS ENUM ( 'ONLINE' , 'OFFLINE' , 'UNKNOWN' ); |
Наше приложение должно хранить События в следующей таблице базы данных:
1
2
3
4
5
6
7
|
CREATE TABLE event ( id bigint NOT NULL , sensor_names text[], sensor_values integer [], sensor_states sensor_state[], CONSTRAINT event_pkey PRIMARY KEY (id) ) |
Обратите внимание, что sensor_names
, sensor_values
и sensor_states
хранятся в виде массивов. Чтобы сопоставить типы столбцов массива PostgreSQL с массивами Java, вам нужен собственный тип Hibernate, поскольку встроенные типы не поддерживают сохранение специфичных для базы данных массивов.
Однако благодаря библиотеке hibernate-types
вы можете легко сопоставить таблицу event
со следующей сущностью Event
:
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
|
@Entity (name = "Event" ) @Table (name = "event" ) @TypeDefs ({ @TypeDef ( typeClass = StringArrayType. class , defaultForType = String[]. class ), @TypeDef ( typeClass = IntArrayType. class , defaultForType = int []. class ), @TypeDef ( typeClass = EnumArrayType. class , defaultForType = SensorState[]. class , parameters = { @Parameter ( name = EnumArrayType.SQL_ARRAY_TYPE, value = "sensor_state" ) } ) }) public class Event { @Id private Long id; @Column ( name = "sensor_names" , columnDefinition = "text[]" ) private String[] sensorNames; @Column ( name = "sensor_values" , columnDefinition = "integer[]" ) private int [] sensorValues; @Column ( name = "sensor_states" , columnDefinition = "sensor_state[]" ) private SensorState[] sensorStates; public Long getId() { return id; } public Event setId( Long id) { this .id = id; return this ; } public String[] getSensorNames() { return sensorNames; } public Event setSensorNames( String[] sensorNames) { this .sensorNames = sensorNames; return this ; } public int [] getSensorValues() { return sensorValues; } public Event setSensorValues( int [] sensorValues) { this .sensorValues = sensorValues; return this ; } public SensorState[] getSensorStates() { return sensorStates; } public Event setSensorStates( SensorState[] sensorStates) { this .sensorStates = sensorStates; return this ; } } |
Обратите внимание на API в стиле Fluent, используемый сущностью Event
. В то время как JPA является более строгим, когда дело доходит до определения сеттеров, Hibernate позволяет вам определять сеттеры, чтобы вы могли строить сущность, используя API в стиле Fluent. Для более подробной информации, проверьте эту статью .
Аннотация @TypeDef
используется для определения соответствия между типами классов массива Java и связанными с ними типами Hibernate:
- Тип массива Java
String[]
обрабатываетсяStringArrayType
. - Тип массива Java
int[]
обрабатываетсяIntArrayType
- Java
SensorState[]
обрабатываетсяEnumArrayType
. ПараметрEnumArrayType.SQL_ARRAY_TYPE
используется для описания специфичного для базы данных типа столбца, используемого для хранения Enum.
SensorState
Java SensorState
отображается следующим образом:
1
2
3
4
5
|
public enum SensorState { ONLINE, OFFLINE, UNKNOWN; } |
Время тестирования
Теперь при сохранении следующего объекта Event
:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
entityManager.persist( new Event() .setId(1L) .setSensorNames( new String[]{ "Temperature" , "Pressure" }) .setSensorValues( new int []{ 12, 756 } ) .setSensorStates( new SensorState[]{ SensorState.ONLINE, SensorState.OFFLINE, SensorState.ONLINE, SensorState.UNKNOWN } ) ); |
Hibernate выполняет следующую инструкцию SQL INSERT:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
|
Query:[ " insert into event ( sensor_names, sensor_states, sensor_values, id ) values ( ?, ?, ?, ? ) " ], Params:[( { "Temperature" , "Pressure" }, { "ONLINE" , "OFFLINE" , "ONLINE" , "UNKNOWN" }, { "12" , "756" }, 1 )] |
И когда мы выбираем сущность Event
, мы видим, что все свойства выбраны правильно
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
|
Event event = entityManager.find(Event.class, 1L); assertArrayEquals( new String[]{ "Temperature" , "Pressure" }, event.getSensorNames() ); assertArrayEquals( new int []{ 12, 756 }, event.getSensorValues() ); assertArrayEquals( new SensorState[]{ SensorState.ONLINE, SensorState.OFFLINE, SensorState.ONLINE, SensorState.UNKNOWN }, event.getSensorStates() ); |
Круто, верно?
Если вам понравилась эта статья, держу пари, что вам понравятся и мои книжные и видео курсы .
Вывод
Проект hibernate-types
поддерживает больше, чем типы ARRAY. Вы можете отобразить специфичные для PostgreSQL Enums, Nullable Character
, JSON или даже предоставить свои собственные неизменяемые пользовательские Types
Hibernate.
Чтобы узнать больше о проекте hibernate-types
, ознакомьтесь с этой статьей .
Опубликовано на Java Code Geeks с разрешения Влада Михалча, партнера нашей программы JCG. См. Оригинальную статью здесь: Как отобразить PostgreSQL Enums на свойства сущностей JPA с помощью Hibernate
Мнения, высказанные участниками Java Code Geeks, являются их собственными. |