Spring Data MongoDBの紹介

Spring Data MongoDBの紹介

1. 概要

この記事は、すばやく実用的なintroduction to Spring Data MongoDBになります。

MongoTemplateMongoRepositoryの両方を使用して基本を説明し、実際の例を使用して各操作を説明します。

参考文献:

MongoDBの地理空間サポート

MongoDBで地理空間データを保存、インデックス付け、検索する方法をご覧ください

組み込みMongoDBを使用したSpring Boot統合テスト

Flapdoodleの組み込みMongoDBソリューションをSpringBootと一緒に使用して、MongoDB統合テストをスムーズに実行する方法を学びます。

2. MongoTemplateand MongoRepository

The MongoTemplateは、Springの標準テンプレートパターンに従い、基盤となる永続化エンジンにすぐに使用できる基本的なAPIを提供します。

The repositoryは、Spring Data中心のアプローチに従い、すべてのSpring Dataプロジェクトでよく知られているアクセスパターンに基づいて、より柔軟で複雑なAPI操作を備えています。

どちらの場合も、依存関係を定義することから始める必要があります。たとえば、pom.xmlでMavenを使用します。


    org.springframework.data
    spring-data-mongodb
    2.1.9.RELEASE



    org.springframework.data
    spring-data-releasetrain
    Lovelace-SR9
    pom
    import

ライブラリの新しいバージョンがリリースされているかどうかを確認するには–track the releases here

3. MongoTemplateの構成

3.1. XML構成

Mongoテンプレートの単純なXML構成から始めましょう。


まず、Mongoインスタンスの作成を担当するファクトリBeanを定義する必要があります。

次に-実際にテンプレートBeanを定義(および構成)する必要があります。


    

そして最後に、@Repositoryアノテーション付きクラスでスローされたMongoExceptionsを変換するポストプロセッサを定義する必要があります。

3.2. Java設定

ここで、MongoDB構成AbstractMongoConfigurationの基本クラスを拡張して、Java構成を使用して同様の構成を作成しましょう。

@Configuration
public class MongoConfig extends AbstractMongoConfiguration {

    @Override
    protected String getDatabaseName() {
        return "test";
    }

    @Override
    public MongoClient mongoClient() {
        return new MongoClient("127.0.0.1", 27017);
    }

    @Override
    protected String getMappingBasePackage() {
        return "org.example";
    }
}

注:AbstractMongoConfigurationで既に定義されているため、以前の構成でMongoTemplateBeanを定義する必要はありませんでした。

次のように、AbstractMongoConfigurationを拡張せずに構成を最初から使用することもできます。

@Configuration
public class SimpleMongoConfig {

    @Bean
    public MongoClient mongo() {
        return new MongoClient("localhost");
    }

    @Bean
    public MongoTemplate mongoTemplate() throws Exception {
        return new MongoTemplate(mongo(), "test");
    }
}

4. MongoRepositoryの構成

4.1. XML構成

カスタムリポジトリを利用するには(MongoRepositoryを拡張する)–セクション3.1から構成を続行し、リポジトリを設定する必要があります。

4.2. Java設定

同様に、セクション3.2ですでに作成した構成に基づいて構築し、新しいアノテーションをミックスに追加します。

@EnableMongoRepositories(basePackages = "org.example.repository")

4.3. リポジトリを作成する

ここで、構成後、リポジトリを作成する必要があります–既存のMongoRepositoryインターフェースを拡張します。

public interface UserRepository extends MongoRepository {
    //
}

これで、このUserRepositoryを自動配線して、MongoRepositoryからの操作を使用したり、カスタム操作を追加したりできます。

5. MongoTemplateの使用

5.1. Insert

挿入操作から始めましょう。空のデータベースから始めましょう。

{
}

次に、新しいユーザーを挿入した場合:

User user = new User();
user.setName("Jon");
mongoTemplate.insert(user, "user");

データベースは次のようになります。

{
    "_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
    "_class" : "org.example.model.User",
    "name" : "Jon"
}

5.2. Save – Insert

save操作には、保存または更新のセマンティクスがあります。IDが存在する場合は更新を実行し、存在しない場合は挿入を実行します。

最初のセマンティクスである挿入を見てみましょう。これがデータベースの初期状態です:

{
}

新しいユーザーをsaveすると、次のようになります。

User user = new User();
user.setName("Albert");
mongoTemplate.save(user, "user");

エンティティがデータベースに挿入されます:

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.model.User",
    "name" : "Albert"
}

次に、更新セマンティクスを使用した同じ操作(save)について説明します。

5.3. Save – Update

次に、既存のエンティティで動作する、更新セマンティクスを使用したsaveを見てみましょう。

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.model.User",
    "name" : "Jack"
}

ここで、既存のユーザーをsaveすると、更新します。

user = mongoTemplate.findOne(
  Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
mongoTemplate.save(user, "user");

データベースは次のようになります。

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.model.User",
    "name" : "Jim"
}

ご覧のとおり、この特定の例では、_idが指定されたオブジェクトを使用しているため、saveupdateのセマンティクスを使用しています。

5.4. UpdateFirst

updateFirstは、クエリに一致する最初のドキュメントを更新します。

データベースの初期状態から始めましょう。

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Alex"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.example.model.User",
        "name" : "Alex"
    }
]

updateFirstを実行すると:

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Alex"));
Update update = new Update();
update.set("name", "James");
mongoTemplate.updateFirst(query, update, User.class);

最初のエントリのみが更新されます。

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "James"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.example.model.User",
        "name" : "Alex"
    }
]

5.5. UpdateMulti

UpdateMultiupdates all document that matches the given query

まず、updateMultiを実行する前のデータベースの状態は次のとおりです。

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Eugen"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.example.model.User",
        "name" : "Eugen"
    }
]

それでは、updateMulti操作を実行してみましょう。

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Eugen"));
Update update = new Update();
update.set("name", "Victor");
mongoTemplate.updateMulti(query, update, User.class);

データベース内の既存のオブジェクトは両方とも更新されます。

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Victor"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614c"),
        "_class" : "org.example.model.User",
        "name" : "Victor"
    }
]

5.6. FindAndModify

この操作はupdateMultiのように機能しますが、returns the object before it was modifiedです。

最初–findAndModifyを呼び出す前のデータベースの状態:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Markus"
}

実際の操作コードを見てみましょう。

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Markus"));
Update update = new Update();
update.set("name", "Nick");
User user = mongoTemplate.findAndModify(query, update, User.class);

返されるuser objectは、データベースの初期状態と同じ値です。

ただし、データベースの新しい状態は次のとおりです。

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Nick"
}

5.7. Upsert

upsertは、find and modify else create semanticsで動作します。ドキュメントが一致する場合は更新し、そうでない場合はクエリと更新オブジェクトを組み合わせて新しいドキュメントを作成します。

データベースの初期状態から始めましょう。

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Markus"
}

では、upsertを実行してみましょう。

Query query = new Query();
query.addCriteria(Criteria.where("name").is("Markus"));
Update update = new Update();
update.set("name", "Nick");
mongoTemplate.upsert(query, update, User.class);

操作後のデータベースの状態は次のとおりです。

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Nick"
}

5.8. Remove

removeを呼び出す前のデータベースの状態:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Benn"
}

removeを実行してみましょう:

mongoTemplate.remove(user, "user");

結果は予想どおりになります。

{
}

6. MongoRepositoryの使用

6.1. Insert

最初–insert:を実行する前のデータベースの状態

{
}

さて、新しいユーザーを挿入すると:

User user = new User();
user.setName("Jon");
userRepository.insert(user);

データベースの最終状態は次のとおりです。

{
    "_id" : ObjectId("55b4fda5830b550a8c2ca25a"),
    "_class" : "org.example.model.User",
    "name" : "Jon"
}

操作がMongoTemplate APIのinsertと同じように機能することに注意してください。

6.2. SaveInsert

同様に–saveは、MongoTemplate APIのsave操作と同じように機能します。

操作のthe insert semanticsを確認することから始めましょう。データベースの初期状態は次のとおりです。

{
}

ここで、save操作を実行します。

User user = new User();
user.setName("Aaron");
userRepository.save(user);

これにより、データベースにユーザーが追加されます。

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.model.User",
    "name" : "Aaron"
}

この例では、新しいオブジェクトを挿入しているため、saveinsertセマンティクスとどのように連携するかに再度注意してください。

6.3. SaveUpdate

同じ操作をupdate semanticsで見てみましょう。

まず、新しいsave:を実行する前のデータベースの状態を次に示します。

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.model.User",
    "name" : "Jack"81*6
}

次に、操作を実行します。

user = mongoTemplate.findOne(
  Query.query(Criteria.where("name").is("Jack")), User.class);
user.setName("Jim");
userRepository.save(user);

最後に、データベースの状態は次のとおりです。

{
    "_id" : ObjectId("55b52bb7830b8c9b544b6ad5"),
    "_class" : "org.example.model.User",
    "name" : "Jim"
}

この例では、既存のオブジェクトを使用しているため、saveupdateセマンティクスとどのように連携するかに再度注意してください。

6.4. Delete

deleteを呼び出す前のデータベースの状態:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Benn"
}

deleteを実行してみましょう:

userRepository.delete(user);

結果は次のようになります。

{
}

6.5. FindOne

findOneが呼び出されたときのデータベースの状態:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Chris"
}

findOneを実行してみましょう:

userRepository.findOne(user.getId())

既存のデータを返す結果:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Chris"
}

6.6. Exists

existsを呼び出す前のデータベースの状態:

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Harris"
}

それでは、existsを実行してみましょう。

boolean isExists = userRepository.exists(user.getId());

もちろん、どちらがtrueを返します。

6.7. FindAll #with[.pl-en] Sort#

findAllを呼び出す前のデータベースの状態:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Brendan"
    },
    {
       "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
       "_class" : "org.example.model.User",
       "name" : "Adam"
    }
]

Sortを使用してfindAllを実行してみましょう。

List users = userRepository.findAll(new Sort(Sort.Direction.ASC, "name"));

結果はsorted by name in ascending orderになります:

[
    {
        "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Adam"
    },
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Brendan"
    }
]

6.8. FindAll #with[.pl-en] Pageable #

findAllを呼び出す前のデータベースの状態:

[
    {
        "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Brendan"
    },
    {
        "_id" : ObjectId("67b5ffa5511fee0e45ed614b"),
        "_class" : "org.example.model.User",
        "name" : "Adam"
    }
]

次に、ページネーション要求を使用してfindAllを実行しましょう。

Pageable pageableRequest = PageRequest.of(0, 1);
Page page = userRepository.findAll(pageableRequest);
List users = pages.getContent();

結果のusersリストは1人のユーザーのみになります:__

{
    "_id" : ObjectId("55b5ffa5511fee0e45ed614b"),
    "_class" : "org.example.model.User",
    "name" : "Brendan"
}

7. アノテーション

最後に、SpringDataがこれらのAPI操作を駆動するために使用する簡単なアノテーションについても見ていきましょう。

@Id
private String id;

フィールドレベルの@Id注釈は、longstringを含む任意のタイプを装飾できます。

@Idフィールドの値がnullでない場合は、そのままデータベースに保存されます。それ以外の場合、コンバーターは、データベースにObjectIdを格納することを想定します(ObjectId, StringまたはBigIntegerのいずれかが機能します)。

次へ–@Document

@Document
public class User {
    //
}

この注釈は、使用するコレクションの名前を選択できるようにするとともに、データベースに永続化する必要がある単純なmarks a class as being a domain objectです。

8. 結論

この記事は、MongoTemplate APIを介して、およびMongoRepositoryを使用して、SpringDataでMongoDBを使用するための迅速で包括的な紹介でした。

これらすべての例とコードスニペットcan be foundover on Githubの実装–これはMavenベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。