12

タイトルでほとんどそれを言います。次のようなクラスがあります。

@Entity
@Table(name="FOO")
public class Foo {

  private String theId;

  @Id
  @Column(name = "FOO_ID")
  @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "fooIdSeq")
  @SequenceGenerator(name = "fooIdSeq", sequenceName = "SQ_FOO_ID", allocationSize = 10)
  public String getTheId() { return theId; }

  public String setTheId(String theId) { this.theId = theId; }
}

Oracle 11gを使用すると、FOO_ID列は。になりますVARCHAR2が、シーケンスSQ_FOO_IDは。になりNUMBERます。データベースは明らかにこれに満足していますが、アプリケーションは、アプリケーションの外部でこの列に挿入された可能性のある非数値IDをサポートできる必要があります。

上記のコードを考慮すると、が得られますorg.hibernate.id.IdentifierGenerationException: Unknown integral data type for ids : java.lang.String。このマッピングを行う方法はありますか?

Hibernate3.6の使用。

4

2 に答える 2

11

カスタムIdentifierGeneratorクラスを実装します。ブログ投稿から:

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.IdentifierGenerator;

public class StringKeyGenerator implements IdentifierGenerator {

    @Override
    public Serializable generate(SessionImplementor session, Object collection) throws HibernateException {
        Connection connection = session.connection();
        PreparedStatement ps = null;
        String result = "";

        try {
            // Oracle-specific code to query a sequence
            ps = connection.prepareStatement("SELECT TABLE_SEQ.nextval AS TABLE_PK FROM dual");
            ResultSet rs = ps.executeQuery();

            if (rs.next()) {
                int pk = rs.getInt("TABLE_PK");

                // Convert to a String
                result = Integer.toString(pk);
            }
        } catch (SQLException e) {
            throw new HibernateException("Unable to generate Primary Key");
        } finally {
            if (ps != null) {
                try {
                    ps.close();
                } catch (SQLException e) {
                    throw new HibernateException("Unable to close prepared statement.");
                }
            }
        }

        return result;
    }
}

次のようにエンティティPKに注釈を付けます。

@Id
@GenericGenerator(name="seq_id", strategy="my.package.StringKeyGenerator")
@GeneratedValue(generator="seq_id")
@Column(name = "TABLE_PK", unique = true, nullable = false, length = 20)
public String getId() {
    return this.id;
}

Eclipseのバグが原因で、ジェネレーター(seq_id)が永続性ユニットで定義されていないというエラーが発生する場合があります。次のようにこれを警告に設定します。

  1. ウィンドウ»設定を選択
  2. JavaPersistenceを展開する»JPA»エラー/警告
  3. [クエリとジェネレータ]をクリックします
  4. Set Generatorは、永続性ユニットで次のように定義されていませんWarning
  5. [ OK ]をクリックして変更を適用し、ダイアログを閉じます
于 2012-09-20T17:11:37.253 に答える
6

これは別のアプローチです。

import java.io.Serializable;

import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.IdentifierGeneratorHelper.BigDecimalHolder;
import org.hibernate.id.IntegralDataTypeHolder;
import org.hibernate.id.SequenceGenerator;

public class StringSequenceGenerator extends SequenceGenerator {
    @Override
    public Serializable generate(SessionImplementor session, Object obj) {
        return super.generate( session, obj ).toString();
    }

    protected IntegralDataTypeHolder buildHolder() {
        return new BigDecimalHolder();
    }
}

次の例のように、シーケンスパラメータをidプロパティで指定する必要があります。

@Id
@GenericGenerator(name = "STRING_SEQUENCE_GENERATOR", strategy = "mypackage.StringSequenceGenerator", parameters = { @Parameter(name = "sequence", value = "MY_SEQUENCE_NAME") })
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "STRING_SEQUENCE_GENERATOR")
@Column(name = "MY_ID")
public String getMyId() {
    return this.myId;
}
于 2013-12-21T12:44:07.347 に答える