Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/dart/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用JPA/Hibernate将声明字段的实体持久化为几个整数的固定大小数组_Java_Hibernate_Jpa_Collections_Persistence - Fatal编程技术网

Java 如何使用JPA/Hibernate将声明字段的实体持久化为几个整数的固定大小数组

Java 如何使用JPA/Hibernate将声明字段的实体持久化为几个整数的固定大小数组,java,hibernate,jpa,collections,persistence,Java,Hibernate,Jpa,Collections,Persistence,我有一个类,它有一个引用固定大小整数数组的字段: class Tracking{ private int[] tracks; } 使用JPA(由Hibernate支持)将tracks字段映射到数据库的最佳方法是什么 轨迹数组将始终包含10个元素。我知道@ElementCollection注释,但这意味着我将得到两个表(Tracking和Tracking_tracks),这似乎是不必要的 想到的唯一方法是使用一个字符串字段将10个数字映射为一个由冒号分隔的字符串。我将使该字段持久化(一个

我有一个类,它有一个引用固定大小整数数组的字段:

class Tracking{
    private int[] tracks;
}
使用JPA(由Hibernate支持)将tracks字段映射到数据库的最佳方法是什么

轨迹数组将始终包含10个元素。我知道@ElementCollection注释,但这意味着我将得到两个表(Tracking和Tracking_tracks),这似乎是不必要的

想到的唯一方法是使用一个字符串字段将10个数字映射为一个由冒号分隔的字符串。我将使该字段持久化(一个简单的basic@Column),然后在getter和setter中执行对int[]的解析


有什么建议吗?我只是想要一种有效的方法来保存这些信息。跟踪对象将永久生成,将有数千个跟踪对象,而且由于整数的数量始终为10,因此将跟踪对象持久化到单独的表中,并执行连接和选择以检索跟踪对象,似乎有点过分。

这可能取决于您的持久化提供程序。但是,您可以尝试使用一种特殊的方法,让持久性提供者处理转换。如果这不起作用,很多持久性提供程序都支持自定义类型。在hibernate中,它们被称为OpenJPA使用。您的数据库可能支持原始固定大小字节存储。

根据SpaceTrucker关于Hibernate用户类型的建议,以下是提供Hibernate自定义用户类型所需的完整代码(非常感谢此类所基于的代码):

package org.mypackage;
导入java.io.Serializable;
导入java.sql.PreparedStatement;
导入java.sql.ResultSet;
导入java.sql.SQLException;
导入java.sql.Types;
导入java.util.ArrayList;
导入java.util.Iterator;
导入java.util.List;
导入java.util.StringTokenizer;
导入org.hibernate.hibernateeexception;
导入org.hibernate.engine.spi.SessionImplementor;
导入org.hibernate.tool.hbm2ddl.SchemaExport.Type;
导入org.hibernate.usertype.usertype;
导入org.springframework.util.ObjectUtils;
/**
*一种Hibernate{@link UserType},允许在表中的一列中持久化整数列表。
*基于源代码http://javadata.blogspot.com.ar/2011/07/hibernate-and-user-types.html.
* 
*要将其用作列的映射器,请在实体的字段中使用以下命令:
*@Type(Type=IntegerListUserType.NAME)
*列出曲目;
*  
*@author-dds
* */
公共类IntegerListUserType实现UserType{
public static final String NAME=“org.mypackage.IntegerListUserType”;//警告这必须与类名匹配!
@凌驾
公共int[]sqlTypes(){
返回新的int[]{Types.VARCHAR};
}
@抑制警告(“原始类型”)
@凌驾
公共类returnedClass(){
返回列表.class;
}
@凌驾
公共布尔等于(对象x,对象y)抛出HibernateException{
返回ObjectUtils.nullSafeEquals(x,y);
}
@凌驾
public int hashCode(对象x)抛出HibernateeException{
如果(x!=null)
返回x.hashCode();
其他的
返回0;
}
@凌驾
公共对象nullSafeGet(结果集rs,字符串[]名称,
SessionImplementor会话,对象所有者)
抛出HibernateeException、SQLException{
List=null;
String nameVal=rs.getString(名称[0]);
如果(nameVal!=null){
列表=新的ArrayList();
StringTokenizer tokenizer=新的StringTokenizer(nameVal,“,”);
while(tokenizer.hasMoreElements()){
字符串编号=(字符串)标记器.nextElement();
list.add(整数.valueOf(number));
}
}
退货清单;
}
@抑制警告(“未选中”)
@凌驾
public void nullSafeSet(PreparedStatement st,Object value,int index,
SessionImplementor会话)引发HibernateeException、SQLException{
如果(值==null){
st.setNull(索引,类型.VARCHAR);
}否则{
st.setString(索引,序列化((列表)值));
}
}
私有字符串序列化(列表){
StringBuilder strbul=新的StringBuilder();
迭代器iter=list.Iterator();
while(iter.hasNext()){
strbul.append(iter.next());
if(iter.hasNext()){
strbul.追加(“,”);
}
}
返回strbul.toString();
}
@抑制警告(“未选中”)
@凌驾
公共对象deepCopy(对象值)引发HibernateException{
如果(值==null)
返回null;
否则{
List newObj=newarraylist();
List existObj=(List)值;
newObj.addAll(existObj);
返回newObj;
}
}
@凌驾
公共布尔可交换(){
返回false;
}
@凌驾
公共可序列化反汇编(对象值)引发HibernateException{
对象deepCopy=deepCopy(值);
if(!(可序列化的deepCopy实例))
返回(可序列化)deepCopy;
返回null;
}
@凌驾
公共对象汇编(可序列化缓存,对象所有者)
抛出冬眠异常{
返回deepCopy(缓存);
}
@凌驾
公共对象替换(对象原始、对象目标、对象所有者)
抛出冬眠异常{
返回副本(原件);
}
}

请注意,为了简单起见,我将字符串转换为List而不是int[]。

谢谢@SpaceTrucker,我正在考虑使用Hibernate用户类型。有很多例子,但大多数都涉及到声明一个额外的类来映射自定义类型。此外,我不知道在哪里定义映射器代码,大多数示例只提到一个可嵌入类型,其中该类型映射到一个新类,而它只映射到
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);
    }

}