1. 序章

Spring Dataに関するこのチュートリアルでは、Spring Dataリポジトリとテンプレートの抽象化の両方を使用してCouchbaseドキュメントの永続性レイヤーを設定する方法と、ビューや/を使用してこれらの抽象化をサポートするようにCouchbaseを準備するために必要な手順について説明します。またはインデックス。

2. Mavenの依存関係

まず、次のMaven依存関係をpom.xmlファイルに追加します。

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-couchbase</artifactId>
    <version>2.0.0.RELEASE</version>
</dependency>

この依存関係を含めることで、互換性のあるバージョンのネイティブCouchbase SDKが自動的に取得されるため、明示的に含める必要がないことに注意してください。

JSR-303 Bean検証のサポートを追加するために、次の依存関係も含まれています。

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>5.2.4.Final</version>
</dependency>

Spring Data Couchbaseは、従来のDateクラスとCalendarクラス、およびJodaTimeライブラリを介して日付と時刻の永続性をサポートします。これには次のものが含まれます。

<dependency>
    <groupId>joda-time</groupId>
    <artifactId>joda-time</artifactId>
    <version>2.9.2</version>
</dependency>

3. 構成

次に、Couchbaseクラスターの1つ以上のノードと、ドキュメントを保存するバケットの名前とパスワードを指定して、Couchbase環境を構成する必要があります。

3.1. Java構成

Javaクラス構成の場合、AbstractCouchbaseConfigurationクラスを拡張するだけです。

@Configuration
@EnableCouchbaseRepositories(basePackages={"com.baeldung.spring.data.couchbase"})
public class MyCouchbaseConfig extends AbstractCouchbaseConfiguration {

    @Override
    protected List<String> getBootstrapHosts() {
        return Arrays.asList("localhost");
    }

    @Override
    protected String getBucketName() {
        return "baeldung";
    }

    @Override
    protected String getBucketPassword() {
        return "";
    }
}

プロジェクトでCouchbase環境をさらにカスタマイズする必要がある場合は、 getEnvironment()メソッドをオーバーライドして提供できます。

@Override
protected CouchbaseEnvironment getEnvironment() {
   ...
}

3.2. XML構成

XMLでの同等の構成は次のとおりです。

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:beans="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="http://www.springframework.org/schema/data/couchbase
  xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans.xsd
    http://www.springframework.org/schema/data/couchbase
    http://www.springframework.org/schema/data/couchbase/spring-couchbase.xsd">

    <couchbase:cluster>
        <couchbase:node>localhost</couchbase:node>
    </couchbase:cluster>

    <couchbase:clusterInfo login="baeldung" password="" />

    <couchbase:bucket bucketName="baeldung" bucketPassword=""/>

    <couchbase:repositories base-package="com.baeldung.spring.data.couchbase"/>
</beans:beans>

注:「 clusterInfo 」ノードはクラスタークレデンシャルまたはバケットクレデンシャルのいずれかを受け入れ、必須であるため、ライブラリはCouchbaseクラスターがN1QL(SQL for NoSQLのスーパーセット)をサポートしているかどうかを判断できます。データベース、Couchbase 4.0以降で利用可能)。

プロジェクトでカスタムCouchbase環境が必要な場合は、 鬼ごっこ。

4. データ・モデル

永続化するJSONドキュメントを表すエンティティクラスを作成しましょう。 最初にクラスに@Document、で注釈を付け、次にStringフィールドに@Idで注釈を付けてCouchbaseドキュメントキーを表します。

SpringDataの@Idアノテーション、またはネイティブのCouchbaseSDKのアノテーションのいずれかを使用できます。 同じクラスで2つの異なるフィールドで両方の@Idアノテーションを使用する場合、Spring Data @Id アノテーションが付けられたフィールドが優先され、次のように使用されることに注意してください。ドキュメントキー。

JSONドキュメントの属性を表すために、@Fieldでアノテーションが付けられたプライベートメンバー変数を追加します。 @NotNull アノテーションを使用して、特定のフィールドを必要に応じてマークします。

@Document
public class Person {
    @Id
    private String id;
    
    @Field
    @NotNull
    private String firstName;
    
    @Field
    @NotNull
    private String lastName;
    
    @Field
    @NotNull
    private DateTime created;
    
    @Field
    private DateTime updated;
    
    // standard getters and setters
}

@Id で注釈が付けられたプロパティは、単にドキュメントキーを表すだけであり、次のように @Field でも注釈が付けられていない限り、必ずしも保存されたJSONドキュメントの一部ではないことに注意してください。

@Id
@Field
private String id;

エンティティクラスのフィールドにJSONドキュメントに格納されるものとは異なる名前を付ける場合は、次の例のように、その@Fieldアノテーションを修飾するだけです。

@Field("fname")
private String firstName;

永続化されたPersonドキュメントがどのように見えるかを示す例を次に示します。

{
    "firstName": "John",
    "lastName": "Smith",
    "created": 1457193705667
    "_class": "com.baeldung.spring.data.couchbase.model.Person"
}

Spring Dataは、エンティティの完全なクラス名を含む属性を各ドキュメントに自動的に追加することに注意してください。 デフォルトでは、この属性の名前は“ _ class” ですが、 typeKey()メソッドをオーバーライドすることで、Couchbase構成クラスの属性をオーバーライドできます。

たとえば、「dataType」という名前のフィールドを指定してクラス名を保持する場合は、これをCouchbase構成クラスに追加します。

@Override
public String typeKey() {
    return "dataType";
}

typeKey()をオーバーライドするもう1つの一般的な理由は、アンダースコアが前に付いたフィールドをサポートしないバージョンのCouchbaseMobileを使用している場合です。 この場合、前の例のように独自の代替タイプフィールドを選択するか、Springが提供する代替タイプを使用できます。

@Override
public String typeKey() {
    // use "javaClass" instead of "_class"
    return MappingCouchbaseConverter.TYPEKEY_SYNCGATEWAY_COMPATIBLE;
}

5. Couchbaseリポジトリ

Spring Data Couchbaseは、JPAなどの他のSpringDataモジュールと同じ組み込みクエリと派生クエリメカニズムを提供します。

のリポジトリインターフェースを宣言します拡張によるクラス CrudRepository 派生可能なクエリメソッドを追加します。

public interface PersonRepository extends CrudRepository<Person, String> {
    List<Person> findByFirstName(String firstName);
}

6. インデックスによるN1QLサポート

Couchbase 4.0以降を使用している場合、デフォルトでは、カスタムクエリはN1QLエンジンを使用して処理されます(次のセクションで説明するように、対応するリポジトリメソッドに @View の注釈が付けられている場合を除く)。 。

N1QLのサポートを追加するには、バケットにプライマリインデックスを作成する必要があります。 cbq コマンドラインクエリプロセッサ(ご使用の環境で cbq ツールを起動する方法についてはCouchbaseのドキュメントを参照)を使用し、次のコマンドを発行して、インデックスを作成できます。

CREATE PRIMARY INDEX ON baeldung USING GSI;

上記のコマンドで、 GSI グローバルセカンダリインデックスを表します。これは、OLTPシステムをサポートするアドホックN1QLクエリの最適化に特に適したインデックスのタイプであり、デフォルトのインデックスタイプです。特に指定がない場合。

ビューベースのインデックスとは異なり、GSIインデックスはクラスター内のすべてのインデックスノードに自動的に複製されないため、クラスターに複数のインデックスノードが含まれている場合は、クラスター内の各ノードに各GSIインデックスを作成する必要があります。各ノードで異なるインデックス名。

1つ以上のセカンダリインデックスを作成することもできます。 その場合、Couchbaseはクエリ処理を最適化するために必要に応じてそれらを使用します。

たとえば、 firstName フィールドにインデックスを追加するには、cbqツールで次のコマンドを発行します。

CREATE INDEX idx_firstName ON baeldung(firstName) USING GSI;

7. バッキングビュー

リポジトリインターフェイスごとに、Couchbaseデザインドキュメントと1つ以上のビューをターゲットバケットに作成する必要があります。 設計ドキュメント名は、エンティティクラス名の lowerCamelCase バージョンである必要があります(例: 「人」)。

実行しているCouchbaseServerのバージョンに関係なく、組み込みの「 findAll」リポジトリメソッドをサポートするには、「all」という名前のバッキングビューを作成する必要があります。 Personクラスの「all」ビューのマップ関数は次のとおりです。

function (doc, meta) {
    if(doc._class == "com.baeldung.spring.data.couchbase.model.Person") {
        emit(meta.id, null);
    }
}

4.0より前のバージョンのCouchbaseを使用する場合、カスタムリポジトリメソッドにはそれぞれバッキングビューが必要です(4.0以降ではバッキングビューの使用はオプションです)。

次の例のように、ビューに裏打ちされたカスタムメソッドに@Viewの注釈を付ける必要があります。

@View
List<Person> findByFirstName(String firstName);

バッキングビューのデフォルトの命名規則では、「find」キーワードに続くメソッド名のその部分のlowerCamelCase バージョンを使用します(例: 「byFirstName」)。

「byFirstName」ビューのマップ関数を作成する方法は次のとおりです。

function (doc, meta) {
    if(doc._class == "com.baeldung.spring.data.couchbase.model.Person"
      && doc.firstName) {
        emit(doc.firstName, null);
    }
}

@Viewアノテーションを対応するバッキングビューの名前で修飾することにより、この命名規則をオーバーライドして、独自のビュー名を使用できます。 例えば:

@View("myCustomView")
List<Person> findByFirstName(String lastName);

8. サービスレイヤー

サービスレイヤーでは、インターフェイスと2つの実装を定義します。1つはSpring Dataリポジトリの抽象化を使用し、もう1つはSpringDataテンプレートの抽象化を使用します。 PersonServiceインターフェイスは次のとおりです。

public interface PersonService {
    Person findOne(String id);
    List<Person> findAll();
    List<Person> findByFirstName(String firstName);
    
    void create(Person person);
    void update(Person person);
    void delete(Person person);
}

8.1. リポジトリサービス

上記で定義したリポジトリを使用した実装は次のとおりです。

@Service
@Qualifier("PersonRepositoryService")
public class PersonRepositoryService implements PersonService {
    
    @Autowired
    private PersonRepository repo; 

    public Person findOne(String id) {
        return repo.findOne(id);
    }

    public List<Person> findAll() {
        List<Person> people = new ArrayList<Person>();
        Iterator<Person> it = repo.findAll().iterator();
        while(it.hasNext()) {
            people.add(it.next());
        }
        return people;
    }

    public List<Person> findByFirstName(String firstName) {
        return repo.findByFirstName(firstName);
    }

    public void create(Person person) {
        person.setCreated(DateTime.now());
        repo.save(person);
    }

    public void update(Person person) {
        person.setUpdated(DateTime.now());
        repo.save(person);
    }

    public void delete(Person person) {
        repo.delete(person);
    }
}

8.2. テンプレートサービス

テンプレートベースの実装では、上記のセクション7にリストされているバッキングビューを作成する必要があります。 CouchbaseTemplate オブジェクトは、Springコンテキストで使用可能であり、サービスクラスに挿入される場合があります。

テンプレート抽象化を使用した実装は次のとおりです。

@Service
@Qualifier("PersonTemplateService")
public class PersonTemplateService implements PersonService {
    private static final String DESIGN_DOC = "person";
    @Autowired
    private CouchbaseTemplate template;
    
    public Person findOne(String id) {
       return template.findById(id, Person.class);
    }

    public List<Person> findAll() {
        return template.findByView(ViewQuery.from(DESIGN_DOC, "all"), Person.class);
    }

    public List<Person> findByFirstName(String firstName) {
        return template.findByView(ViewQuery.from(DESIGN_DOC, "byFirstName"), Person.class);
    }

    public void create(Person person) {
        person.setCreated(DateTime.now());
        template.insert(person);
    }

    public void update(Person person) {
        person.setUpdated(DateTime.now());
        template.update(person);
    }

    public void delete(Person person) {
        template.remove(person);
    }
}

9. 結論

Spring Data Couchbaseモジュールを使用するようにプロジェクトを構成する方法と、単純なエンティティクラスとそのリポジトリインターフェイスを作成する方法を示しました。 シンプルなサービスインターフェイスを作成し、リポジトリを使用した1つの実装と、SpringDataテンプレートAPIを使用した別の実装を提供しました。

このチュートリアルの完全なソースコードは、GitHubプロジェクトで表示できます。

詳細については、 Spring DataCouchbaseプロジェクトサイトにアクセスしてください。