1

固定サイズの整数配列を参照するフィールドを持つクラスがあります。

class Tracking{
    private int[] tracks;
}

JPA (Hibernate に支えられている) を使用して、トラック フィールドをデータベースにマッピングする最良の方法は何ですか?

トラック配列には、常に 10 個の要素が含まれます。@ElementCollection アノテーションについては知っていますが、それは 2 つのテーブル (Tracking と Tracking_tracks) になることを意味し、不要なようです。

頭に浮かぶ唯一の方法は、10 個の数値をコロンで区切られた単一の文字列にマッピングする文字列フィールドを使用することです。そのフィールドを永続化 (単純な基本的な @Column) にしてから、getter と setter で int[] への解析を実行します。

助言がありますか?この情報を永続化する効率的な方法が欲しいだけです。Tracking オブジェクトは永続的に生成され、数千のオブジェクトがあり、整数の数は常に 10 であるため、それらを別のテーブルに永続化し、結合と選択を実行してそれらを取得するのはやり過ぎのようです。

4

2 に答える 2

2

これは、永続化プロバイダーによって異なる場合があります。ただし、特別な列定義を使用して、永続化プロバイダーに変換を処理させることもできます。これがうまくいかない場合は、多くの永続化プロバイダーがカスタム型をサポートしています。hibernate ではユーザー タイプと呼ばれ、open jpa はカスタム フィールド マッピングを使用します。お使いのデータベースが未加工の固定サイズのバイト ストレージをサポートしている場合があります。

于 2013-05-31T20:31:05.467 に答える
0

Hibernate UserType に関する SpaceTrucker の提案に従って、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);
    }

}

簡単にするために、int[] ではなく String を List < Integer > に変換していることに注意してください。

于 2013-07-26T18:02:00.717 に答える