1概要

このチュートリアルでは、Spring BootでMongoDB用の順次自動生成フィールドを実装する方法を学習します。

  • MongoDBをSpring Bootアプリケーションのデータベースとして使用している場合は、モデルで

    @ GeneratedValue

    アノテーションを使用できないため使用できません。 JPAとSQLデータベースを使用しています。

この問題に対する一般的な解決策は簡単です。他のコレクション用に生成されたシーケンスを格納するコレクション(テーブル)を作成します。新しいレコードの作成中に、次の値を取得するためにそれを使用します。


2依存関係

次のspring-bootスターターを

pom.xml

に追加しましょう。

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
        <versionId>2.1.0.RELEASE</versionId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
        <versionId>2.1.0.RELEASE</versionId>
    </dependency>
</dependencies>

依存関係の最新バージョンはhttps://search.maven.org/classic/#search%7Cga%7C1%7Cg%3Aorg.springframework.boot%20a%3Aspring-boot-starter-parent[

spring-boot-によって管理されていますstarter-parent

]。


3コレクション

概要で説明したように、他のコレクションの自動増分シーケンスを格納するコレクションを作成します。このコレクションを

__database

sequencesと呼びます。

__mongo

シェルまたはMongoDB Compassを使用して作成できます。対応するモデルクラスを作成しましょう。

@Document(collection = "database__sequences")
public class DatabaseSequence {

    @Id
    private String id;

    private long seq;

   //getters and setters omitted
}

それでは、

users

コレクションとそれに対応するモデルオブジェクトを作成してみましょう。これには、システムを使用している人々の詳細が格納されます。

@Document(collection = "users")
public class User {

    @Transient
    public static final String SEQUENCE__NAME = "users__sequence";

    @Id
    private long id;

    private String email;

   //getters and setters omitted
}

上記で作成した

User

モデルに、静的フィールド

SEQUENCE

NAMEを追加しました。これは、

users

コレクションの自動増分シーケンスへの一意の参照です。

また、モデルの他のプロパティと一緒に永続化されないように、

@ Transient

という注釈を付けます。


4新しいレコードを作成する

これまでに、必要なコレクションとモデルを作成しました。これで、エンティティの

id

として使用できる自動増分値を生成するサービスを作成しましょう。


generateSequence()

を持つ

SequenceGeneratorService

を作成しましょう。

public long generateSequence(String seqName) {
    DatabaseSequence counter = mongoOperations.findAndModify(query(where("__id").is(seqName)),
      new Update().inc("seq",1), options().returnNew(true).upsert(true),
      DatabaseSequence.class);
    return !Objects.isNull(counter) ? counter.getSeq() : 1;
}

これで、新しいレコードを作成しながら

generateSequence()

を使用できます。

User user = new User();
user.setId(sequenceGenerator.generateSequence(User.SEQUENCE__NAME));
user.setEmail("[email protected]");
userRepository.save(user);

すべてのユーザーを一覧表示するには、

UserRepository

を使用します。

List<User> storedUsers = userRepository.findAll();
storedUsers.forEach(System.out::println);

  • 今のところ、モデルの新しいインスタンスを作成するたびにidフィールドを設定する必要があります。 Spring Data MongoDBのライフサイクルイベントのリスナーを作成することで、このプロセスを回避できます。

  • これを行うには、

    AbstractMongoEventListener <User>

    を拡張する

    UserModelListener

    を作成してから、

    onBeforeConvert()

    をオーバーライドします。

@Override
public void onBeforeConvert(BeforeConvertEvent<User> event) {
    event.getSource().setId(sequenceGenerator.generateSequence(User.SEQUENCE__NAME));
}

これで、新しい

Userを保存するたびに、

id__が自動的に設定されます。


5結論

結論として、idフィールドに対して連続的な自動インクリメント値を生成し、SQLデータベースで見られるのと同じ動作をシミュレートする方法を見ました。

Hibernateはデフォルトで自動インクリメント値を生成するために同様の方法を使用します。

いつものように、完全なソースコードはhttps://github.com/eugenp/tutorials/tree/master/persistence-modules/spring-boot-persistence-mongodb[over Github]から入手できます。