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クライアントを介して行われた変更を覆い隠す傾向があります。どうやって知っているのか聞いてください。