[英]How to persist an entity declaring a field with a fixed-size array of a few integers using JPA/Hibernate
我有一個帶有字段的類,該字段引用固定大小的整數數組:
class Tracking{
private int[] tracks;
}
使用JPA(由Hibernate支持)將tracks字段映射到數據庫的最佳方法是什么?
tracks數組將始終包含10個元素。 我知道@ElementCollection批注,但這意味着我將得到兩個表(Tracking和Tracking_tracks),這似乎是不必要的。
想到的唯一方法是使用String字段將10個數字映射到用冒號分隔的單個String中。 我將使該字段成為持久字段(一個簡單的基本@Column),然后在getter和setter中將其解析為int []。
有什么建議么? 我只想要一種有效的方法來保留此信息。 跟蹤對象將永久生成,並且將有成千上萬個對象,並且由於整數的數量始終為10,將它們持久化到一個單獨的表中並執行聯接並選擇以檢索它們似乎過於刻薄。
遵循SpaceTrucker提出的有關Hibernate UserType的建議,以下是提供Hibernate自定義UserType所需的完整代碼(非常感謝Kunaal A Trehan的博客文章提供了此類所基於的代碼):
package org.mypackage;
import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.tool.hbm2ddl.SchemaExport.Type;
import org.hibernate.usertype.UserType;
import org.springframework.util.ObjectUtils;
/**
* An Hibernate {@link UserType} that allows persisting a list of integers in one single column in the table.
* Based in code from http://javadata.blogspot.com.ar/2011/07/hibernate-and-user-types.html.
*
* In order to use this as the mapper for a column, use the following in the field of your entity:
* @Type(type=IntegerListUserType.NAME)
* List<Integer> tracks;
*
* @author dds
* */
public class IntegerListUserType implements UserType {
public static final String NAME = "org.mypackage.IntegerListUserType"; //WARNING this must match class name!
@Override
public int[] sqlTypes() {
return new int[] { Types.VARCHAR };
}
@SuppressWarnings("rawtypes")
@Override
public Class returnedClass() {
return List.class;
}
@Override
public boolean equals(Object x, Object y) throws HibernateException {
return ObjectUtils.nullSafeEquals(x, y);
}
@Override
public int hashCode(Object x) throws HibernateException {
if (x != null)
return x.hashCode();
else
return 0;
}
@Override
public Object nullSafeGet(ResultSet rs, String[] names,
SessionImplementor session, Object owner)
throws HibernateException, SQLException {
List<Integer> list = null;
String nameVal = rs.getString(names[0]);
if (nameVal != null) {
list = new ArrayList<Integer>();
StringTokenizer tokenizer = new StringTokenizer(nameVal, ",");
while (tokenizer.hasMoreElements()) {
String number = (String) tokenizer.nextElement();
list.add(Integer.valueOf(number));
}
}
return list;
}
@SuppressWarnings("unchecked")
@Override
public void nullSafeSet(PreparedStatement st, Object value, int index,
SessionImplementor session) throws HibernateException, SQLException {
if (value == null) {
st.setNull(index, Types.VARCHAR);
} else {
st.setString(index, serialize((List<Integer>) value));
}
}
private String serialize(List<Integer> list) {
StringBuilder strbul = new StringBuilder();
Iterator<Integer> iter = list.iterator();
while (iter.hasNext()) {
strbul.append(iter.next());
if (iter.hasNext()) {
strbul.append(",");
}
}
return strbul.toString();
}
@SuppressWarnings("unchecked")
@Override
public Object deepCopy(Object value) throws HibernateException {
if (value == null)
return null;
else {
List<Integer> newObj = new ArrayList<Integer>();
List<Integer> existObj = (List<Integer>) value;
newObj.addAll(existObj);
return newObj;
}
}
@Override
public boolean isMutable() {
return false;
}
@Override
public Serializable disassemble(Object value) throws HibernateException {
Object deepCopy = deepCopy(value);
if (!(deepCopy instanceof Serializable))
return (Serializable) deepCopy;
return null;
}
@Override
public Object assemble(Serializable cached, Object owner)
throws HibernateException {
return deepCopy(cached);
}
@Override
public Object replace(Object original, Object target, Object owner)
throws HibernateException {
return deepCopy(original);
}
}
請注意,為了簡單起見,我將String轉換為List <Integer>而不是int []。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.