35

私は hibernate 3 、oracle 10g を使用しています。私はテーブルを持っています:件名。定義はこちら

CREATE TABLE SUBJECT
    ( 
     SUBJECT_ID NUMBER (10), 
     FNAME VARCHAR2(30)  not null, 
     LNAME VARCHAR2(30)  not null, 
     EMAILADR VARCHAR2 (40),
     BIRTHDT  DATE       not null,
     constraint pk_sub primary key(subject_id) USING INDEX TABLESPACE data_index
    ) 
;

新しいサブジェクトを挿入するとき、サブジェクト ID を作成するために sub_seq が使用されます。定義はここにあります

create sequence sub_seq
       MINVALUE 1 
       MAXVALUE 999999999999999999999999999 
       START WITH 1
       INCREMENT BY 1 
       CACHE 100 
       NOCYCLE ;

Subject クラスは次のようになります。

@Entity
@Table(name="ktbs.syn_subject")
public class Subject {

    @Id 
    @Column(name="subject_id")
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SUB_SEQ")
    @SequenceGenerator(name="SUB_SEQ", sequenceName = "SUB_SEQ")
    private long subjectId;
    private String fname;
    private String lname;
    private String emailadr;
    private Date birthdt;
}

subject テーブルには、Excel から plsql スクリプトによってロードされたデータベースに 4555 件のサブジェクトがあり、sub_sequence は正常に機能しました。サブジェクト ID の範囲は 1 ~ 4555 です。

ただし、休止状態を使用してアプリケーションからサブジェクトを追加すると、シーケンス番号が 255050 に跳ね上がりました。数日間実行した後、休止状態によって生成されたサブジェクト ID は次のようになります。

270079
270078
270077
270076
270075
270074
270073
270072
270071
270070
270069
270068
270067
270066
270065
270064
270063
270062
270061
270060
270059
270058
270057
270056
270055
270054
270053
270052
270051
270050
265057
265056
265055
265054
265053
265052
265051
265050
260059
260058
260057
260056
260055
260054
260053
260052
260051
260050
255067
255066
255065
255064
255063
255062
255061
255060
255059
255058
255057
255056
255055
255054
255053
255052
255051
255050
4555
4554
4553
.
.
.
.
1

いくつかの大きなギャップがあります: 4555 から 255051、255067 から 260051、265057 から 270051

これは無駄であり、望ましい動作ではありません。

なぜこれが起こり、それを修正するのが難しいのか誰もが知っていますか

ありがとう

4

9 に答える 9

45

問題は、シーケンスジェネレーターが実際にはシーケンスジェネレーターではなく、デフォルトの割り当てサイズが 50 のシーケンスヒロジェネレーターであるという事実に起因すると思います。ドキュメントで示されているように: http://docs.jboss.org/ hibernate/stable/annotations/reference/en/html_single/#entity-mapping-identifier

これは、シーケンス値が 5000 の場合、次に生成される値が 5000 * 50 = 250000 になることを意味します。シーケンスのキャッシュ値を式に追加すると、初期の巨大なギャップが説明される可能性があります。

シーケンスの値を確認してください。最後に生成された識別子よりも小さい必要があります。この最後に生成された値 + 1 にシーケンスを再初期化しないように注意してください。これは、生成された値が指数関数的に増加するためです (この問題があり、オーバーフローのために負の整数 ID がありました)。

于 2011-03-17T23:22:44.183 に答える
38

JBさんに同意。それでも、PaulJ には感謝しています。

以下の注釈コードをより具体的にするには:

@Entity
@Table(name="ktbs.syn_subject")
public class Subject {

  @Id 
  @Column(name="subject_id")
  @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SUB_SEQ")
  @javax.persistence.SequenceGenerator(name="SUB_SEQ", sequenceName = "SUB_SEQ")
  private long subjectId;
  private String fname;
  private String lname;
  private String emailadr;
  private Date birthdt;
}

を使用する場合javax.persistence.SequenceGenerator、hibernate は hilo を使用し、シーケンスに大きなギャップが生じる可能性があります。この問題に対処する投稿があります: https://forum.hibernate.org/viewtopic.php?t=973682

この問題を解決するには2つの方法があります

  1. SequenceGenerator アノテーションで、追加しますallocationSize = 1, initialValue= 1
  2. javax.persistence.SequenceGenerator を使用する代わりに、次のように org.hibernate.annotations を使用します。

    @javax.persistence.SequenceGenerator(
        name = "Question_id_sequence", 
        sequenceName = "S_QUESTION"
    )
    
    @org.hibernate.annotations.GenericGenerator(
        name="Question_id_sequence", 
        strategy = "sequence", 
        parameters = { 
            @Parameter(name="sequence", value="S_QUESTION") 
        }
    )
    

私は両方の方法をテストしましたが、うまくいきました。

于 2011-03-17T23:58:31.033 に答える
6

別の解決策は次のとおりです。

以下のように、「GenerationType.SEQUENCE」の代わりに「GenerationType.AUTO」を戦略として使用@GeneratedValueします。

@Id
@SequenceGenerator(name = "studentId", sequenceName = "student_Id")
@GeneratedValue(strategy = GenerationType.AUTO, generator="studentId")  
private int studentId;
于 2012-11-22T18:15:18.237 に答える
5

次のリンクを読むと、シーケンス作成コマンドの CACHE 設定が問題の原因であることがわかります。キャッシュ設定を削除すると、問題はある程度解決されますが、ロールバックなどの可能性は考慮されていません。

リンクは: http://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:369390500346406705

シーケンスを再同期する唯一の方法は、シーケンスを再作成し、現在のテーブルの名前を変更してテーブルを再作成し、古いテーブルのレコードを新しいテーブルに再挿入することです。

注: シーケンスのキャッシュ値は、'x' 個のシーケンス値が一度に割り当てられる大規模なロードに役立ちます。一度に 1 つの挿入を行うトランザクション システムを使用している場合、キャッシングは役に立ちません (つまり、有用だとは思いませんでした)。

注: これは、シーケンスのキャッシュ オプションに関する私の理解です。詳細については、CREATE SEQUENCE コマンドに関する Oracle ドキュメントを参照してください。しかし、上記のリンクはあなたの質問に対する合理的な答えを提供するはずです.

ありがとう。ポール

于 2011-03-17T22:45:25.367 に答える
1

同様の問題がありました。シーケンス ジェネレーターとシーケンス hilo ジェネレーターは非常に似ていますが、違いがあります。hibernate 3 では、hilo ジェネレーターはデフォルト値 50 で乗算します。したがって、DB シーケンスをインクリメントする必要はありません。一方、休止状態の新しいバージョンでは、デフォルトでシーケンス ジェネレーターが使用されます。したがって、DB を 50 ずつ増やす必要があります。

https://access.redhat.com/documentation/en-US/JBoss_Enterprise_Application_Platform/6.3/html/Migration_Guide/Preserve_the_Existing_Behavior_of_the_Hibernate_Identity_Auto_Generated_Value1.html

複数の休止状態バージョン (3 および 5) があるこの問題がありました。同じ構成が正常に機能しました (DB で 1 ずつ増加)。しかし、休止状態 5 で失敗しました。したがって、persistence.xml を以下のように更新します。これにより、hilo の生成が保証されます

        <property name="hibernate.id.new_generator_mappings" value="false" />
于 2016-05-05T10:51:03.350 に答える