Spring Bootを使ったMongoDB用の自動生成フィールド

Spring Bootを使用したMongoDBの自動生成フィールド

1. 概要

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

When we’re using MongoDB as the database for a Spring Boot application, we can’t use @GeneratedValue annotation in our models as it’s not available.したがって、JPAとSQLデータベースを使用している場合と同じ効果を生み出すメソッドが必要です。

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

2. 依存関係

次のSpring-Bootスターターをpom.xmlに追加しましょう。


    
        org.springframework.boot
        spring-boot-starter-web
        2.1.0.RELEASE
    
    
        org.springframework.boot
        spring-boot-starter-data-mongodb
        2.1.0.RELEASE
    

依存関係の最新バージョンはspring-boot-starter-parentによって管理されます。

3. コレクション

概要で説明したように、他のコレクションの自動インクリメントシーケンスを格納するコレクションを作成します。 このコレクションをdatabase_sequences. と呼びます。これは、mongoシェルまたはMongoDBコンパスのいずれかを使用して作成できます。 対応するモデルクラスを作成しましょう。

@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 storedUsers = userRepository.findAll();
storedUsers.forEach(System.out::println);

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

これを行うには、AbstractMongoEventListener<User>を拡張するUserModelListenerを作成してから、onBeforeConvert()をオーバーライドします。

@Override
public void onBeforeConvert(BeforeConvertEvent event) {
    if (event.getSource().getId() < 1) {
        event.getSource().setId(sequenceGenerator.generateSequence(User.SEQUENCE_NAME));
    }
}

これで、新しいUser,を保存するたびに、idが自動的に設定されます。

5. 結論

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

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

いつものように、完全なソースコードはover on Githubで利用できます。