0

SessionCustomizerを使用して、特別な命名規則に従ってデータベースに既に存在する EclipseLink のシーケンスを自動的に生成しようとしています。たとえば、というエンティティは、4 文字のエイリアスと一意の ID 生成のために呼び出されるデータベース シーケンスを持つItemというテーブルにマップされます。ITEMSITEMITEM_ID_SEQ

他の目的にも使用しているため、エンティティ クラスのエイリアス名を保持するためのマーカーとして注釈を使用しています。

package jpa.namingsupport;

// imports omitted

@Target(TYPE)
@Retention(RUNTIME)
public @interface Alias {
    String name();
}

エンティティは次のようになります。

package jpa.entities;

// imports omitted

@Entity
@Table(name = "ITEMS")
@Alias(name = "ITEM")
public class Item {

    @Id
    private Long id;

    @Version
    private Long version;

    private String name;

    // setters and getters omitted
}

正しく登録され、起動時に実行されることが確認された SessionCustomizer を使用して、シーケンスを作成し、エンティティに追加します。

package jpa.namingsupport;

// imports omitted

public class AliasCustomizer implements SessionCustomizer {

    @Override
    public void customize(Session session) throws Exception {
        Map<Class, ClassDescriptor> entities = session.getDescriptors();
        for (Class entity : entities.keySet()) {
            customizeSequence(aliasNameFor(entity), entities.get(entity), session);
        }
    }

    private String aliasNameFor(Class entity) {
        Alias alias = (Alias) entity.getAnnotation(Alias.class);
        return alias.name();
    }

    private void customizeSequence(String alias, ClassDescriptor descriptor, Session session) {
        NativeSequence sequence = new NativeSequence(underscores(alias, "ID", "SEQ"), 1);
        session.getLogin().addSequence(sequence);
        descriptor.setSequenceNumberName(sequence.getName());
        descriptor.setSequenceNumberField(descriptor.getPrimaryKeyFields().get(0));
        descriptor.setSequence(sequence);
    }

    private String underscores(String... parts) {
        return StringUtils.arrayToDelimitedString(parts, "_");
    }

}

しかし、テストを実行しているときに、保存する前にシーケンスから ID が割り当てられません。

[EL Warning]: 2013-07-14 20:32:32.571--UnitOfWork(1908148255)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.h2.jdbc.JdbcSQLException: NULL nicht zulässig für Feld "ITEM_ID"
NULL not allowed for column "ITEM_ID"; SQL statement:
INSERT INTO ITEMS (ITEM_NAME, ITEM_VERSION) VALUES (?, ?) [23502-172]

コードに欠けているヒントやアイデアはありますか? 私が見ているのは、生成された挿入ステートメントに ITEM_ID 列への参照がないことです。

4

1 に答える 1

1

ID に @GeneratedValue(strategy=SEQUENCE, generator="ITME_ID_SEQ") を付けてみませんか?

カスタマイザーでは、descriptor.setSequence() を呼び出さないでください。これは初期化時に行う必要があります。

SQL は、ID が IDENTITY 値を使用していることを期待しています。これには、テーブルを構成する必要があります。代わりに SEQUENCE を使用する場合は、false を new NativeSequence(name, increment, false) に渡します。H2 は IDENTITY と SEQUENCE の両方をサポートし、NativeSequence はデフォルトで IDENTITY を使用します。false は SEQUENCE を意味します。

于 2013-07-15T14:07:10.897 に答える