Hibernateを使用してこのクラスをマップするのを手伝ってくれませんか?
public class MyClass{
private Long id;
private String name;
private int[] values;
...
}
PostgreSQLを使用していて、テーブルの列タイプはinteger []です。配列をどのようにマッピングする必要がありますか?
配列を休止状態にマップしたことはありません。私はいつもコレクションを使います。だから、私はあなたのクラスを少し変更しました:
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;
}
...
Hibernate(およびJPA)は、PostgreSQL配列型を直接マップすることはできません。 この質問を参照 データベース構造をそのまま保持する必要がある場合の進め方について。 このスレッド には、必要なカスタムタイプの例があります。
スキーマを変更できる場合は、hibernateにコレクションを処理するための追加のテーブルを作成させることができます-List<Integer>
。次に、使用しているHibernateのバージョンに応じて:
@ElementCollection
@CollectionOfElements
Hibernateは、プリミティブ型のみをマップできます。 hibernatejarパッケージのorg.hibernate.typeフォルダーの下を確認してください。 int配列はそれらの1つではありません。したがって、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
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 };
}
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();
これは非常に良い質問なので、 Hibernate Typesプロジェクト を使用してこの目標を達成する方法を説明するために この記事 と書くことにしました。
最初に行う必要があるのは、次の設定です Hibernateタイプ プロジェクトでの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-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
}
StringArrayType
とIntArrayType
は、HibernateTypesプロジェクトによって提供されるクラスです。
ここで、いくつかのエンティティを挿入すると、
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は次の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
)