繁体   English   中英

如何使用JPA / Hibernate持久化一个实体,该实体声明具有几个整数的固定大小的数组的字段

[英]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,将它们持久化到一个单独的表中并执行联接并选择以检索它们似乎过于刻薄。

这可能取决于您的持久性提供程序。 但您可以尝试使用特殊的列定义,并让持久性提供程序处理转换。 如果这行不通,则很多持久性提供程序都支持自定义类型。 在休眠状态下,它们称为用户类型 ,open jpa使用自定义字段映射 您的数据库可能支持固定大小的原始字节存储。

遵循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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM