Введение в Spring Data Couchbase

Данные]** ссылка:/категория/постоянство/весеннее постоянство/[весеннее постоянство]

  • ссылка:/tag/couchbase/[Couchbase]

1. Вступление

В этом руководстве по Spring Data мы обсудим, как настроить постоянный слой для документов Couchbase с использованием репозитория Spring Data и абстракций шаблонов, а также шаги, необходимые для подготовки 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, поэтому нам не нужно явно включать ее.

Чтобы добавить поддержку проверки bean-компонента JSR-303, мы также включили следующую зависимость:

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

Spring Data Couchbase поддерживает постоянство даты и времени с помощью традиционных классов Date и Calendar, а также с помощью библиотеки Joda Time, которую мы включаем следующим образом:

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

3. Конфигурация

Далее нам необходимо настроить среду Couchbase, указав один или несколько узлов нашего кластера Couchbase, а также имя и пароль корзины, в которой мы будем хранить наши документы.

3.1. Конфигурация Java

Для настройки класса Java мы просто расширяем класс AbstractCouchbaseConfiguration :

@Configuration
@EnableCouchbaseRepositories(basePackages={"org.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="org.baeldung.spring.data.couchbase"/>
</beans:beans>

Примечание. Узел « clusterInfo » принимает учетные данные кластера или учетные данные корзины и является обязательным , чтобы библиотека могла определить, поддерживает ли ваш кластер Couchbase N1QL (расширенный набор SQL для баз данных NoSQL, доступный в Couchbase 4.0 и более поздних версиях).

Если для вашего проекта требуется пользовательская среда Couchbase, вы можете предоставить ее с помощью тега <couchbase: env/> .

4. Модель данных

Давайте создадим класс сущности, представляющий документ JSON для сохранения.

Сначала мы аннотируем класс с помощью @ Document, , а затем аннотируем поле String с помощью @ Id для представления ключа документа Couchbase.

Вы можете использовать либо аннотацию @ Id из Spring Data, либо аннотацию из собственного пакета Couchbase SDK. Имейте в виду, что если вы используете обе аннотации @ 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 , просто представляет ключ документа и не обязательно является частью хранимого документа JSON, если оно также не помечено @ Field , как в:

@Id
@Field
private String id;

Если вы хотите назвать поле в классе сущности не так, как в документе JSON, просто укажите его аннотацию @ Field , как в этом примере:

@Field("fname")
private String firstName;

Вот пример, показывающий, как будет выглядеть сохраненный документ Person :

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

Обратите внимание, что Spring Data автоматически добавляет к каждому документу атрибут, содержащий полное имя класса сущности. По умолчанию этот атрибут называется « class» , хотя вы можете переопределить его в классе конфигурации Couchbase, переопределив метод typeKey () __.

Например, если вы хотите назначить поле с именем «dataType» для хранения имен классов, вы должны добавить это в свой класс конфигурации Couchbase:

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

Другая популярная причина переопределения typeKey () - это использование версии Couchbase Mobile, которая не поддерживает поля с префиксом подчеркивания. В этом случае вы можете выбрать собственное поле альтернативного типа, как в предыдущем примере, или вы можете использовать альтернативу, предоставленную Spring:

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

5. Couchbase Repository

Spring Data Couchbase предоставляет те же встроенные запросы и механизмы производных запросов, что и другие модули Spring Data, такие как JPA.

Мы объявляем интерфейс репозитория для класса Person , расширяя CrudRepository <String, Person> и добавляя метод производного запроса:

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

6. Поддержка N1QL через индексы

Если используется Couchbase 4.0 или более поздняя версия, то по умолчанию пользовательские запросы обрабатываются с использованием механизма N1QL (если только их соответствующие методы хранилища не помечены @ View , чтобы указать использование вспомогательных видов, как описано в следующем разделе).

Чтобы добавить поддержку N1QL, вы должны создать первичный индекс в корзине.

Вы можете создать индекс с помощью обработчика запросов командной строки cbq (см. Документацию Couchbase о том, как запустить инструмент cbq для вашей среды) и выполнив следующую команду:

CREATE PRIMARY INDEX ON baeldung USING GSI;

В приведенной выше команде GSI обозначает вторичный индекс global , который представляет собой тип индекса, особенно подходящий для оптимизации специальных запросов N1QL для поддержки систем OLTP, и является типом индекса по умолчанию, если не указано иное.

В отличие от индексов на основе представлений, индексы GSI не реплицируются автоматически на все узлы индекса в кластере, поэтому, если ваш кластер содержит более одного узла индекса, вам нужно будет создать каждый индекс GSI для каждого узла в кластере, и вы должны другое имя индекса на каждом узле.

Вы также можете создать один или несколько вторичных индексов. Когда вы это сделаете, Couchbase будет использовать их по мере необходимости для оптимизации обработки запросов.

Например, чтобы добавить индекс в поле firstName , введите следующую команду в инструменте cbq :

CREATE INDEX idx__firstName ON baeldung(firstName) USING GSI;

7. Поддержка просмотров

Для каждого интерфейса репозитория вам нужно будет создать проектный документ Couchbase и одно или несколько представлений в целевой корзине. Имя проектного документа должно быть lowerCamelCase версией имени класса сущности (например, «персона» ).

Независимо от того, какую версию Couchbase Server вы используете, вы должны создать вспомогательное представление с именем «all» для поддержки встроенного метода « findAll» репозитория. Вот функция map для представления «all» для нашего класса Person :

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

Каждый из пользовательских методов репозитория должен иметь представление поддержки при использовании версии Couchbase до 4.0 (использование версий поддержки является необязательным в версии 4.0 или более поздней).

Пользовательские методы с поддержкой представлений должны быть помечены @ View , как в следующем примере:

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

Соглашение об именах по умолчанию для вспомогательных представлений заключается в использовании версии lowerCamelCase этой части имени метода после ключевого слова « find» (например, «byFirstName» __).

Вот как бы вы написали функцию карты для представления «byFirstName» :

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

Вы можете переопределить это соглашение об именах и использовать собственные имена представлений, указав в каждой аннотации @ View имя вашего соответствующего вспомогательного представления. Например:

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

8. Сервисный уровень

Для нашего сервисного уровня мы определяем интерфейс и две реализации:

один использует абстракцию хранилища Spring Data, а другой - абстракцию шаблона Spring Data. Вот наш интерфейс 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 и как написать простой класс сущностей и его интерфейс репозитория. Мы написали простой интерфейс службы и предоставили одну реализацию с использованием репозитория, а другую реализацию с использованием API-интерфейса шаблонов Spring Data.

Вы можете просмотреть полный исходный код этого руководства в ject GitHub

Для получения дополнительной информации посетите сайт проекта Spring Data Couchbase .