淘先锋技术网

首页 1 2 3 4 5 6 7
postgresql

postgresql

介绍

开源的hibernate-types项目允许您映射JSON,ARRAY, YearMonthMonth或特定于数据库的列(例如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_namessensor_valuessensor_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