dan*_*nik 9 java postgresql hibernate java-ee
你可以帮我映射一下Hbernate吗?
public class MyClass{
private Long id;
private String name;
private int[] values;
...
}
Run Code Online (Sandbox Code Playgroud)
我正在使用PostgreSQL,表格的列类型是整数[]我的数组应该如何映射?
Boz*_*zho 15
Hibernate(和JPA)无法直接映射PostgreSQL数组类型.如果您确实需要保留数据库结构,请参阅此问题以了解如何继续.此线程具有所需自定义类型的示例.
如果你可以改变你的模式,你可以让hibernate创建一个额外的表来处理集合 - List<Integer>.然后,根据您使用的hibernate的版本:
@ElementCollection@CollectionOfElements您需要做的第一件事是在您的项目配置文件中设置以下Hibernate Types Maven 依赖项pom.xml:
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>${hibernate-types.version}</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)
假设您的数据库中有此表:
create table event (
id int8 not null,
version int4,
sensor_names text[],
sensor_values integer[],
primary key (id)
)
Run Code Online (Sandbox Code Playgroud)
你想像这样映射它:
@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
}
Run Code Online (Sandbox Code Playgroud)
的string-array和int-array是可在被定义的自定义类型的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
}
Run Code Online (Sandbox Code Playgroud)
在StringArrayType与IntArrayType由Hibernate的类型项目提供的课程。
现在,当您插入几个实体时;
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);
Run Code Online (Sandbox Code Playgroud)
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
)
Run Code Online (Sandbox Code Playgroud)
我从未将数组映射到休眠状态.我总是使用收藏品.所以,我稍微改变了你的课程:
public class MyClass{
private Long id;
private String name;
private List<Integer> values;
@Id
// this is only if your id is really auto generated
@GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;
}
@OneToMany(cascade=CascadeType.ALL, fetch=FetchType.LAZY)
public List<Integer> getValues() {
return values;
}
...
Run Code Online (Sandbox Code Playgroud)
Hibernate只能映射原始类型.检查hibernate jar包的org.hibernate.type文件夹下.int数组不是其中之一.因此,您必须编写可以实现UserType接口的自定义类型.
public class MyClass{
private Long id;
private String name;
private Integer[] values;
@Type(type = "com.usertype.IntArrayUserType")
public Integer[] getValues(){
return values;
}
public void setValues(Integer[] values){
this.values = values;
}
}
Run Code Online (Sandbox Code Playgroud)
IntArrayUserType.class
package com.usertype.IntArrayUserType;
public class IntArrayUserType implements UserType {
protected static final int[] SQL_TYPES = { Types.ARRAY };
@Override
public Object assemble(Serializable cached, Object owner) throws HibernateException {
return this.deepCopy(cached);
}
@Override
public Object deepCopy(Object value) throws HibernateException {
return value;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
return (Integer[]) this.deepCopy(value);
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
if (x == null) {
return y == null;
}
return x.equals(y);
}
@Override
public int hashCode(Object x) throws HibernateException {
return x.hashCode();
}
@Override
public boolean isMutable() {
return true;
}
@Override
public Object nullSafeGet(ResultSet resultSet, String[] names, SessionImplementor session, Object owner)
throws HibernateException, SQLException {
if (resultSet.wasNull()) {
return null;
}
if(resultSet.getArray(names[0]) == null){
return new Integer[0];
}
Array array = resultSet.getArray(names[0]);
Integer[] javaArray = (Integer[]) array.getArray();
return javaArray;
}
@Override
public void nullSafeSet(PreparedStatement statement, Object value, int index, SessionImplementor session)
throws HibernateException, SQLException {
Connection connection = statement.getConnection();
if (value == null) {
statement.setNull(index, SQL_TYPES[0]);
} else {
Integer[] castObject = (Integer[]) value;
Array array = connection.createArrayOf("integer", castObject);
statement.setArray(index, array);
}
}
@Override
public Object replace(Object original, Object target, Object owner) throws HibernateException {
return original;
}
@Override
public Class<Integer[]> returnedClass() {
return Integer[].class;
}
@Override
public int[] sqlTypes() {
return new int[] { Types.ARRAY };
}
Run Code Online (Sandbox Code Playgroud)
当您查询MyClass实体时,您可以添加如下内容:
Type intArrayType = new TypeLocatorImpl(new TypeResolver()).custom(IntArrayUserType.class);
Query query = getSession().createSQLQuery("select values from MyClass")
.addScalar("values", intArrayType);
List<Integer[]> results = (List<Integer[]>) query.list();
Run Code Online (Sandbox Code Playgroud)