Java 使用 Hibernate 映射数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4332467/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Mapping array with Hibernate
提问by danny.lesnik
Can you please help me to map this class using Hibernate?
你能帮我用 Hibernate 映射这个类吗?
public class MyClass{
private Long id;
private String name;
private int[] values;
...
}
I'm using PostgreSQL and the column type in the table is integer[] How my array should be mapped?
我正在使用 PostgreSQL 并且表中的列类型是 integer[] 我的数组应该如何映射?
采纳答案by AlexR
I have never mapped arrays to hibernate. I always use collections. So, I have slightly changed you class:
我从未将数组映射到休眠状态。我总是使用集合。所以,我稍微改变了你的课程:
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;
}
...
回答by Bozho
Hibernate (and JPA) can't directly map the PostgreSQL array type. See this questionfor how to proceed if you really need to retain your database structure as it is. This threadhas an example of the required custom type.
Hibernate(和 JPA)不能直接映射 PostgreSQL 数组类型。如果您确实需要按原样保留数据库结构,请参阅此问题以了解如何继续。该线程有一个所需自定义类型的示例。
If you can change your schema, you can let hibernate create an additional table to handle the collection - List<Integer>
. Then, depending on the version of hibernate you are using:
如果您可以更改架构,则可以让 hibernate 创建一个额外的表来处理集合 - List<Integer>
。然后,根据您使用的休眠版本:
- JPA 2.0 compliant - use
@ElementCollection
- JPA 1.0 compliant - use
@CollectionOfElements
- 符合 JPA 2.0 - 使用
@ElementCollection
- 符合 JPA 1.0 - 使用
@CollectionOfElements
回答by user3820369
Hibernate can map only the primitive types. Check under the org.hibernate.type folder of hibernate jar package. int array is not one of them. So you would have to write a custom type that can implement the UserType interface.
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;
}
}
IntArrayUserType.class
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 };
}
When you query for the MyClass entity you can add something like this:
当您查询 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();
回答by Vlad Mihalcea
This is a very good question, so I decided to write this articleto explain how you can achieve this goal using the Hibernate Types project.
这是一个很好的问题,所以我决定写这篇文章来解释如何使用Hibernate Types 项目来实现这个目标。
Maven dependency
Maven 依赖
The first thing you need to do is to set up the following Hibernate TypesMaven dependency in your project pom.xml
configuration file:
您需要做的第一件事是在您的项目配置文件中设置以下Hibernate TypesMaven 依赖项pom.xml
:
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>${hibernate-types.version}</version>
</dependency>
Maven ARRAY columns
Maven 数组列
Assuming you have this table in your database:
假设您的数据库中有此表:
create table event (
id int8 not null,
version int4,
sensor_names text[],
sensor_values integer[],
primary key (id)
)
And you want to map it like this:
你想像这样映射它:
@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
}
The string-array
and int-array
are custom types which can be defined in the BaseEntity
superclass:
的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
}
The StringArrayType
and IntArrayType
are classes offered by the Hibernate Types project.
在StringArrayType
与IntArrayType
由Hibernate的类型项目提供的课程。
Testing time
测试时间
Now, when you insert a couple of entities;
现在,当您插入几个实体时;
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 is going to generate the following SQL statements:
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
)