Postgres で SEQUENCE を利用できますか?

はい、できます。でもちょっと問題もあります。

Postgres の Sequence については V2 の開発中、まるでジェットコースターに乗っているように変わったので、
どのように Glassfish と JPA で使うかに関して、様々な古い情報があります。
このページで表題の件に関して正しい情報が伝えられれば幸いです。

Sequence を使う最もシンプルな方法は、GeneratedValue アノテーションの GenerationType.IDENTITY
strategy を使うことです:

@Id
    @Column(name = "id", nullable = false)
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    private Integer id;

これを動かすには、関連するテーブルのカラムタイプを SERIAL にする必要があります。このインスタンスでは、
SERIAL フィールドが定義されたときに Postgrss データベースによって自動的に作成される SEQUENCE を
透過的に使えます。そのほかの利点としては、Glassfish で配備時にテーブルを作成するときに使用すれば、
Glassfish は適切な SERIAL カラムを生成されたテーブルに作成します。

GeneratedValue アノテーションの GenerationType.SEQUENCE を通じて、JPA は
SEQUENCE の特殊な使い方もできます。

残念ながら、これは、Glassfish の Postgres 向け JPA 実装や Toplink では直接はサポートされていません。

Toplink の内部アーキテクチャ上の制限があるため、特定のデータベースプラットフォームで IDENTITY タイプ
と SEQUENCE タイプの生成を同時にサポートすることができません。

Toplink の実装者は、標準的な Postgres DB プラットフォームの実装に、Postgres SERIAL カラムを
IDENTITY タイプを使ってサポートすることに決め、そのため SEQUENCE タイプの生成を無効にしました。

しかしながら、すべてが失われているわけではありません。Toplink は、どの DB プラットフォームを
アプリケーションから使うかを指定することができ、DB プラットフォームのデフォルト実装は容易に
拡張できます。

このメカニズムを使って、SERIAL カラムと IDENTITY をサポートするのではなく、Oracle のように
SEQUENCE をサポートする新しい Postgres プラットフォームを作成できます。

これを行うには、新しいクラスを作成する必要があります。

// Code free for any use whatsoever.
package faq.glassfish.postgres;

import oracle.toplink.essentials.queryframework.ValueReadQuery;
import oracle.toplink.essentials.sessions.DatabaseSession;

public class PostgresPlatform 
    extends oracle.toplink.essentials.platform.database.PostgreSQLPlatform {
    
    public PostgresPlatform() {
        super();
    }
        
    public boolean shouldNativeSequenceAcquireValueAfterInsert() {
        return false;
    }
    
    public ValueReadQuery buildSelectQueryForNativeSequence(String seqName, Integer size) {
        ValueReadQuery selectQuery = new ValueReadQuery();
        selectQuery.setSQLString("select nextval(\'"  + seqName + "\')");
        return selectQuery;
    }
    
    public void platformSpecificSequencingInitialization(DatabaseSession session) {
    }
}

このコードをビルドするには、Glassfish ディストリビューションの toplink jar を classpath に追加
してください。

ファイルの場所は、$glassfish_install_dir/lib/toplink-essentials.jar になります。

このコードはデフォルトの Postgres DB プラットフォームを Oracle のような振る舞いをする
SEQUENCE に切り替えます。

このクラスをプロジェクトに追加したら、persistence.xml ファイルのプロパティを追加します。

<property name="toplink.platform.class.name" 
          value="faq.glassfish.postgres.PostgresPlatform"/>

ここで、エンティティで SEQUENCE を使いましょう:

@Id
    @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="MYSEQUENCE")
    @SequenceGenerator(name="MYSEQUENCE", sequenceName="mysequence")
    @Column(name = "id", nullable = false)
    private Integer id;

副次的な効果として、sequence の allocationSize パラメータも利用できます。必要なのは、
アロケーションサイズに合わせるため、Postgres sequence の increment 値を変更するだけです。

SequenceGenerator アノテーションに allocationSize=10 を追加した場合、データベースでは次のように
します:

ALTER SEQUENCE mysequence INCREMENT 10;

日本語翻訳: shioda

英文 (翻訳したバージョン: 1)