3

Oracle 11g、Java(struts2)、および Hibernate を使用してアプリケーションを開発しています。

NUMBER(22,0) 型の列 mytemp_id を持つ mytemp という名前のテーブルがあります。

私のmytemp.hbm.xmlファイルIDでは、以下のとおりです

<id name="mytempId" type="big_decimal">
        <column name="MYTEMP_ID" precision="22" scale="0" />
        <generator class="sequence">
            <param name="sequence">MYTEMP_TEMP_ID_SEQ</param>
        </generator>
    </id>

私のOracleデータベースでは、「MYTEMP_TEMP_ID_SEQ」という名前のシーケンスが作成され、Oracleで正常に動作しています。

休止状態を使用してレコードを挿入しようとすると、次のエラーが表示されます

org.hibernate.id.IdentifierGenerationException: この ID ジェネレーターは long、integer、short、または string を生成します

私のシーケンスは Number を返すので、hibenate はそれを BigDecimal と見なし、hibernate のシーケンス ジェネレーター クラスは long、integer、short、および string のみの値を考慮しているようです。

Hibernate は BigDecimal で問題を起こすべきではありません。しかし、シーケンスジェネレーターに BigDecimal を実装していないと思います

問題の解決を手伝ってくれる人はいますか?

ありがとう。

4

3 に答える 3

13

正直に言うと、ID を long ではなく BigDecimal にすることに固執する理由が想像できません。最大 long 値は9,223,372,036,854,775,807、確かに最大 NUMBER(22) 値の約 1000 分の 1 ですが、実際には十分なはずです。毎秒100 万の識別子を生成する場合、シーケンスを使い果たすには300,000 年間それを行う必要があります。

つまり、識別子を BigDecimal として生成するには、独自のジェネレーターを作成する必要があります。これは、Hibernate のビルトイン SequenceGenerator を拡張し、そのgenerate()メソッドをオーバーライドすることで実行できます。long / int / short / String のみをサポートする を呼び出す代わりにIdentifierGeneratorFactory.get()、結果セットからシーケンス値を BigDecimal として取得します。

次に、完全なクラス名を指定してジェネレーターを宣言する必要があります。

<generator class="com.mypackage.BigDecimalGenerator">
  <param name="sequence">MYTEMP_TEMP_ID_SEQ</param>
</generator>
于 2009-08-15T00:25:08.373 に答える
2

絶対。生成できる一意のレコードの数を考慮すると、常に長い ID で十分である必要があります。特定のジェネレーターは、整数型以外の特別な値を持っているか、何らかの理由で整数型の値を制御している可能性があります (プロジェクト固有の可能性があります)。

また、ジェネレーターはオラクルのシーケンスのようにデータベース固有であるため、方言の定義も重要です。

于 2009-10-04T19:06:40.623 に答える
2

正しい方言を設定しましたか?これは、Hibernate がシーケンスの結果を理解するのに十分なはずです。

[編集] 問題は、シーケンスの型が列の型と一致しないことです。シーケンスは (Hibernate のエラー メッセージに従って) long、integer、short、または string にキャストできますが、シーケンスは BigDecimal を返します。

Oracleはそのタイプを認識していませんが、ID列のタイプを「ロング」として指定することをお勧めします。内部的には、Hibernate は全員に対してすべてを正しくキャストできるはずです。

于 2009-08-14T09:16:26.700 に答える