如何使用 Hibernate 映射 PostgreSQL 数组

2022-08-31 16:06:42

有没有人通过Hibernate成功地将PostgreSQL中的数字数组映射到java中的数字数组?

sql:

CREATE TABLE sal_emp (name text, pay_by_quarter integer[]);
INSERT INTO sal_emp VALUES ('one', '{1,2,3}');
INSERT INTO sal_emp VALUES ('two', '{4,5,6}');
INSERT INTO sal_emp VALUES ('three', '{2,4,6}');

映射:

<hibernate-mapping>
    <class name="SalEmp" table="sal_emp">
        <id name="name" />
        <property name="payByQuarter" column="pay_by_quarter" />
    </class>
</hibernate-mapping>

类:

public class SalEmp implements Serializable{
    private String name;
    private Integer[] payByQuarter;
    ...// getters & setters
}

我在查询表时遇到异常。


答案 1

对专家的依赖性

您需要做的第一件事是在项目配置文件中设置以下休眠类型 Maven 依赖项:pom.xml

<dependency>
    <groupId>com.vladmihalcea</groupId>
    <artifactId>hibernate-types-52</artifactId>
    <version>${hibernate-types.version}</version>
</dependency>

假设您的数据库中有此表:

create table event (
    id int8 not null, 
    version int4, 
    sensor_names text[], 
    sensor_values integer[], 
    primary key (id)
)

你想像这样映射它:

@Entity(name = "Event")
@Table(name = "event")
@TypeDefs({
    @TypeDef(
        name = "string-array", 
        typeClass = StringArrayType.class
    ),
    @TypeDef(
        name = "int-array", 
        typeClass = IntArrayType.class
    )
})
public static 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-arrayint-arrayBaseEntity

@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
}

和 是休眠类型项目提供的类。StringArrayTypeIntArrayType

测试时间

现在,当您插入几个实体时;

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);

休眠将生成以下 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
)

答案 2

Hibernate 不支持开箱即用的数据库数组(例如映射到 的数据库数组)。java.sql.Array

arrayHibernate提供的类型用于将Java数组映射到支持表中 - 它们基本上是一对多/元素集合映射的变体,所以这不是你想要的。primitive-array

最新的PostgreSQL JDBC驱动程序(8.4.whatever)支持JDBC4 Connection.createArrayOf()方法以及ResultSet.getArray()ReadyStatement.setArray()方法,因此您可以编写自己的方法来提供数组支持。UserType

这是一个处理Oracle数组的UserType实现,它提供了一个很好的起点,调整它来处理它是相当简单的。java.sql.Array