簡體   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