postgresql
介绍
开源的hibernate-types
项目允许您映射JSON,ARRAY, YearMonth
, Month
或特定于数据库的列(例如INET地址)。
在本文中,我们将看到使用JPA和Hibernate时如何将PostgreSQL Enum类型映射到Java数组。
Maven依赖
首先,您需要在项目pom.xml
配置文件中设置以下Maven依赖项:
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>2.3.5</version>
</dependency>
如果您使用的是Hibernate的旧版本,请查看hibernate-types
GitHub存储库,以获取有关当前Hibernate版本的匹配依赖项的更多信息。
领域模型
假设我们在数据库模式中具有以下sensor_state
PostgreSQL枚举:
CREATE TYPE sensor_state AS ENUM (
'ONLINE',
'OFFLINE',
'UNKNOWN'
);
我们的应用程序需要将事件存储在以下数据库表中:
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
实体:
@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;
}
}
注意Event
实体使用的Fluent风格的API。 尽管JPA在定义设置器方面更为严格,但是Hibernate允许您定义设置器,以便您可以使用Fluent风格的API来构建实体。 有关更多详细信息,请参阅本文。
@TypeDef
批注用于定义Java数组类类型及其关联的Hibernate类型之间的映射:
- Java
String[]
数组类型由StringArrayType
处理。 - Java
int[]
数组类型由IntArrayType
处理 - Java
SensorState[]
由EnumArrayType
处理。EnumArrayType.SQL_ARRAY_TYPE
参数用于描述用于存储Enum的特定于数据库的列类型。
SensorState
Java枚举映射如下:
public enum SensorState {
ONLINE,
OFFLINE,
UNKNOWN;
}
测试时间
现在,当存储以下Event
实体时:
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语句:
Query:["
insert into event (
sensor_names,
sensor_states,
sensor_values,
id
)
values (
?,
?,
?,
?
)
"],
Params:[(
{"Temperature","Pressure"},
{"ONLINE","OFFLINE","ONLINE","UNKNOWN"},
{"12","756"},
1
)]
而且,当我们获取Event
实体时,我们可以看到所有属性均已正确获取
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,可为空的Character
,JSON,甚至提供自己的不可变Hibernate自定义Types
。
有关hibernate-types
项目的更多详细信息,请参阅本文。
翻译自: https://www.javacodegeeks.com/2018/12/map-postgresql-jpa-entity-hibernate.html
postgresql