Автор оригинала: Vlad Mihalcea.
Вступление
В этой статье мы рассмотрим, как можно сопоставить массивы SQL с атрибутами сущностей JPA при использовании Hibernate.
Пользовательские типы гибернации позволяют сопоставлять все типы столбцов, зависящих от базы данных , такие как IP-адрес , столбцы JSON, наборы битов или массивы SQL.
Однако, хотя вы можете создавать свои собственные типы гибернации, для сопоставления массивов PostgreSQL вам не нужно реализовывать свой собственный тип гибернации. Все, что вам нужно сделать, это использовать Типы гибернации проект с открытым исходным кодом.
Таблица базы данных
Учитывая, что у нас есть следующая таблица в нашей схеме базы данных PostgreSQL:
create table event (
id int8 not null,
version int4,
sensor_names text[],
sensor_values integer[],
primary key (id)
)
Мы хотим сопоставить эту таблицу с помощью JPA и гибернации. Однако ни JPA, ни Hibernate по умолчанию не поддерживают массивы SQL, и мы хотим сопоставить эти массивы с Строка и int Массивы Java, соответственно. Итак, мы собираемся использовать проект “Типы гибернации” для достижения этой цели.
Зависимость от Maven
Первое, что вам нужно сделать, это настроить следующую зависимость Maven в вашем проекте pom.xml файл конфигурации:
com.vladmihalcea hibernate-types-55 ${hibernate-types.version}
Сопоставление объектов JPA
Сопоставление JPA для таблицы базы данных событие будет выглядеть следующим образом:
@Entity(name = "Event")
@Table(name = "event")
public class Event extends BaseEntity {
@Type(type = "string-array")
@Column(
name = "sensor_names",
columnDefinition = "text[]"
)
private String[] sensorNames;
@Type(type = "int-array")
@Column(
name = "sensor_values",
columnDefinition = "integer[]"
)
private int[] sensorValues;
//Getters and setters omitted for brevity
}
string-массив и int-массив являются пользовательскими типами, которые могут быть определены в суперклассе BaseEntity :
@TypeDefs({
@TypeDef(
name = "string-array",
typeClass = StringArrayType.class
),
@TypeDef(
name = "int-array",
typeClass = IntArrayType.class
)
})
@MappedSuperclass
public class BaseEntity {
@Id
private Long id;
@Version
private Integer version;
//Getters and setters omitted for brevity
}
Тип массива String и IntArrayType – это классы, предлагаемые проектом “Типы гибернации”.
Вот и все!
Время тестирования
При сохранении этих двух Событий сущностей:
Event nullEvent = new Event();
nullEvent.setId(0L);
entityManager.persist(nullEvent);
Event event = new Event();
event.setId(1L);
event.setSensorNames(
new String[] {
"Temperature",
"Pressure"
}
);
event.setSensorValues(
new int[] {
12,
756
}
);
entityManager.persist(event);
Hibernate создаст следующую инструкцию SQL:
INSERT INTO event (
version,
sensor_names,
sensor_values,
id
)
VALUES (
0,
NULL(ARRAY),
NULL(ARRAY),
0
)
INSERT INTO event (
version,
sensor_names,
sensor_values,
id
)
VALUES (
0,
{"Temperature","Pressure"},
{"12","756"},
1
)
Отлично! Теперь мы также можем обновить объекты Событие :
Event event = entityManager.find(Event.class, 1L);
assertArrayEquals(
new String[] {
"Temperature",
"Pressure"
},
event.getSensorNames()
);
assertArrayEquals(
new int[] {
12,
756
},
event.getSensorValues()
);
event.setSensorNames(
new String[] {
"Temperature",
"Pressure",
"Volume"
} );
event.setSensorValues(
new int[] {
12,
756,
76
}
);
И Hibernate создаст следующую инструкцию обновления SQL:
UPDATE
event
SET
version = 1,
sensor_names = {"Temperature","Pressure","Volume"},
sensor_values = {"12","756","76"}
WHERE
id = 1
AND
version = 0
Поскольку типы массивов Hibernate изменчивы, мы даже можем обновлять их, не переопределяя объект массива:
Event event = entityManager.find(Event.class, 1L); event.getSensorValues()[2] = 84;
Спящий режим, генерирующий соответствующую инструкцию UPDATE SQL:
UPDATE
event
SET
version = 2,
sensor_names = {"Temperature","Pressure","Volume"},
sensor_values = {"12","756","84"}
WHERE
id = 1
AND
version = 1
Вот и все!
Вывод
В то время как JPA определяет интерфейс AttributeConverter , стандартные преобразователи слишком ограничены, когда дело доходит до сопоставления массивов или типов JSON. Вот почему проект Hibernate Types использует API Hibernate для предоставления дополнительных сопоставлений типов столбцов.