sql >> データベース >  >> RDS >> PostgreSQL

hibernateは次のシーケンス値を取得できませんでした

    HibernateのPostgreSQL方言はあまり明るくありません。 SERIALごとのシーケンスについては認識せず、使用できる「hibernate_sequence」と呼ばれるデータベース全体のグローバルシーケンスがあると想定しています。

    更新GenerationType.IDENTITYの場合、新しいHibernateバージョンはデフォルトのテーブルごとのシーケンスを使用する可能性があるようです が指定されています。バージョンをテストし、問題がなければ、以下の代わりにこれを使用してください。)

    各シーケンスを明示的に指定するには、マッピングを変更する必要があります。煩わしく、反復的で、無意味です。

    @Entity
    @Table(name = "JUDGEMENTS")
    public class Judgement implements Serializable, Cloneable {
    
        private static final long serialVersionUID = -7049957706738879274L;
    
        @Id
        @GeneratedValue(strategy = GenerationType.SEQUENCE, generator="judgements_id_seq")
        @SequenceGenerator(name="judgements_id_seq", sequenceName="judgements_id_seq", allocationSize=1)
        @Column(name = "JUD_ID")
        private Long _judId;
    ...
    

    allocationSize=1 非常に重要です。これを省略すると、HibernateはシーケンスがINCREMENT 50で定義されていると盲目的に想定します。 したがって、シーケンスから値を取得するときは、その値とその下の49個の値を使用できます 一意に生成されたキーとして。データベースシーケンスが1(デフォルト)ずつ増加する場合、Hibernateが既存のキーを再利用しようとするため、これにより一意の違反が発生します。

    一度に1つのキーを取得すると インサートごとに追加の往復が発生します。私が知る限り、HibernateはINSERT ... RETURNINGを使用できません。 生成されたキーを効率的に返すため、または明らかにJDBCで生成されたキーインターフェイスを使用することもできません。シーケンスを使用するように指示すると、nextvalが呼び出されます。 値を取得するには、insert それは明示的に、2回の往復になります。そのコストを削減するために、多くの挿入を含むキーシーケンスに大きな増分を設定できます。これは、マッピングに設定することを忘れないでください 基礎となるデータベースシーケンス。これにより、Hibernateはnextvalを呼び出します。 頻度を減らし、キーのブロックをキャッシュして配布します。

    上記から、少なくともPostgreSQLで使用するという観点からは、ここで行ったHibernateの設計の選択に同意できないことがわかると思います。 getGeneratedKeysを使用する必要があります またはINSERT ... RETURNINGを使用します DEFAULTを使用 キーについては、Hibernateがシーケンスの名前やシーケンスへの明示的なアクセスについて問題を起こすことなく、データベースにこれを処理させることができます。

    ところで、PgでHibernateを使用している場合は、Pgのoplockトリガーを使用して、Hibernateの楽観的ロックが通常のデータベースロックと安全に相互作用できるようにすることもできます。それまたはそのようなものがないと、Hibernateの更新は他の通常のSQLクライアントを介して行われた変更を覆い隠す傾向があります。どうやって知っているのか聞いてください。



    1. SQLステートメントを使用してテーブルに列が存在するかどうかをテストするにはどうすればよいですか?

    2. 制約を変更する方法

    3. Partition ByまたはMaxの使用方法は?

    4. データベースサイズが2ギガバイトを超えると、SQLiteのパフォーマンスが低下しますか?