Проверка сущности, оптимистическая блокировка и согласованность запросов в Spring Couchbase

Данные]

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

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

После нашей ссылки:/spring-data-couchbase[введение в Spring Data Couchbase]во втором уроке мы сосредоточимся на поддержке проверки сущностей (JSR-303), оптимистической блокировке и разных уровнях согласованности запросов для базы данных документов Couchbase ,

2. Проверка сущности

Spring Data Couchbase поддерживает аннотации проверки сущностей JSR-303. Чтобы воспользоваться этой возможностью, сначала добавим библиотеку JSR-303 в раздел зависимостей нашего проекта Maven:

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>1.1.0.Final</version>
</dependency>

Затем мы добавляем реализацию JSR-303. Мы будем использовать реализацию Hibernate:

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

Наконец, мы добавляем фабричный компонент-валидатор и соответствующий слушатель события Couchbase в нашу конфигурацию Couchbase:

@Bean
public LocalValidatorFactoryBean localValidatorFactoryBean() {
    return new LocalValidatorFactoryBean();
}

@Bean
public ValidatingCouchbaseEventListener validatingCouchbaseEventListener() {
    return new ValidatingCouchbaseEventListener(localValidatorFactoryBean());
}

Эквивалентная конфигурация XML выглядит так:

<bean id="validator"
  class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean"/>

<bean id="validatingEventListener"
  class="org.springframework.data.couchbase.core.mapping.event.ValidatingCouchbaseEventListener"/>

Теперь мы добавляем аннотации JSR-303 к нашим классам сущностей. При обнаружении нарушения ограничения во время операции персистентности операция завершится с ошибкой, выдав исключение ConstraintViolationException .

Вот пример ограничений, которые мы можем применить с участием наших Student сущностей:

@Field
@NotNull
@Size(min=1, max=20)
@Pattern(regexp="^[a-zA-Z .'-]+$")
private String firstName;

...
@Field
@Past
private DateTime dateOfBirth;

3. Оптимистическая блокировка

Spring Data Couchbase не поддерживает транзакции с несколькими документами, аналогичные тем, которые вы можете выполнять в других модулях Spring Data, таких как Spring Data JPA (с помощью аннотации @ Transactional ), и не предоставляет функцию отката.

Однако он поддерживает оптимистическую блокировку во многом так же, как и другие модули Spring Data, с помощью аннотации @ Version :

@Version
private long version;

Под прикрытием Couchbase использует так называемый механизм сравнения и обмена (CAS) для достижения оптимистичной блокировки на уровне хранилища данных.

Каждый документ в Couchbase имеет соответствующее значение CAS, которое изменяется автоматически каждый раз, когда изменяются метаданные или содержимое документа.

Использование аннотации @ Version для поля приводит к тому, что это поле заполняется текущим значением CAS при получении документа из Couchbase.

Когда вы пытаетесь сохранить документ обратно в Couchbase, это поле сверяется с текущим значением CAS в Couchbase. Если значения не совпадают, операция сохранения завершится с ошибкой OptimisticLockingException .

  • Очень важно ** отметить, что вы никогда не должны пытаться получить доступ или изменить это поле в вашем коде.

4. Согласованность запроса

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

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

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

4.1. Уровни согласованности

Spring Data позволяет вам задавать различные уровни согласованности и целостности запросов для вашего приложения с помощью перечисления Consistency , найденного в пакете org.springframework.data.couchbase.core.query .

Это перечисление определяет следующие уровни согласованности и целостности запросов, от наименее до самых строгих:

  • EVENTUALLY CONSISTENT__

  • ** устаревшие чтения разрешены

  • ** индексы обновляются по стандартному алгоритму Couchbase

  • UPDATE AFTER__

  • ** устаревшие чтения разрешены

  • ** индексы обновляются после каждого запроса

  • DEFAULT CONSISTENCY (аналогично READ YOUR OWN WRITES )

  • READ YOUR OWN WRITES__

  • ** устаревшие чтения не допускаются

  • ** индексы обновляются после каждого запроса

  • STRONGLY CONSISTENT__

  • ** устаревшие чтения не допускаются

  • ** индексы обновляются после каждого утверждения

4.2. Поведение по умолчанию

Рассмотрим случай, когда у вас есть документы, которые были удалены из Couchbase, а вспомогательные представления и индексы не были полностью обновлены.

Встроенный метод CouchbaseRepository deleteAll () безопасно игнорирует документы, которые были найдены вспомогательным видом, но удаление которых еще не отражено в представлении.

Аналогично, встроенные методы CouchbaseTemplate findByView и findBySpatialView обеспечивают аналогичный уровень согласованности, не возвращая документы, которые были первоначально найдены в режиме резервного копирования, но которые впоследствии были удалены.

Для всех других методов шаблонов, встроенных методов репозитория и методов производных запросов к репозиторию, согласно официальной документации Spring Data Couchbase 2.1.x на момент написания этой статьи, Spring Data использует уровень согласованности по умолчанию Consistency.READ YOUR OWN WRITES.__

Стоит отметить, что более ранние версии библиотеки использовали по умолчанию Consistency.UPDATE AFTER__

Какую бы версию вы не использовали, если у вас есть какие-либо сомнения относительно слепого принятия предоставляемого уровня согласованности по умолчанию, Spring предлагает два метода, с помощью которых вы можете декларативно контролировать используемые уровни согласованности, как описано в следующих подразделах.

4.3. Глобальная настройка согласованности

Если вы используете репозитории Couchbase и ваше приложение требует более высокого уровня согласованности или если оно может допускать более слабый уровень, вы можете переопределить настройку согласованности по умолчанию для всех репозиториев, переопределив метод getDefaultConsistency () в своей конфигурации Couchbase.

Вот как вы можете переопределить глобальный уровень согласованности в вашем классе конфигурации Couchbase:

@Override
public Consistency getDefaultConsistency() {
    return Consistency.STRONGLY__CONSISTENT;
}

Вот эквивалентная конфигурация XML:

<couchbase:template consistency="STRONGLY__CONSISTENT"/>

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

Например, хранилище данных или приложение для создания отчетов, в котором данные часто добавляются или обновляются только в пакете, будет хорошим кандидатом для EVENTUALLY CONSISTENT , тогда как приложение OLTP, вероятно, должно стремиться к более строгим уровням, таким как READ YOUR OWN WRITES или STRONGLY CONSISTENT__.

4.4. Индивидуальная реализация согласованности

Если вам нужны более точно настроенные параметры согласованности, вы можете переопределить уровень согласованности по умолчанию для каждого запроса, предоставив собственную реализацию хранилища для любых запросов, уровень согласованности которых вы хотите контролировать независимо, и используя queryView и/или queryN1QL методы, предоставляемые CouchbaseTemplate .

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

Сначала создайте интерфейс, содержащий объявление пользовательского метода:

public interface CustomStudentRepository {
    List<Student> findByFirstNameStartsWith(String s);
}

Затем реализуйте интерфейс, установив параметр Stale из базового Java-пакета Couchbase на желаемый уровень:

public class CustomStudentRepositoryImpl implements CustomStudentRepository {

    @Autowired
    private CouchbaseTemplate template;

    public List<Student> findByFirstNameStartsWith(String s) {
        return template.findByView(ViewQuery.from("student", "byFirstName")
          .startKey(s)
          .stale(Stale.FALSE),
          Student.class);
    }
}

Наконец, благодаря тому, что ваш стандартный интерфейс репозитория расширяет и общий интерфейс CrudRepository , и ваш пользовательский интерфейс репозитория, клиенты получат доступ ко всем встроенным и производным методам вашего стандартного интерфейса репозитория, а также к любым пользовательским методам, реализованным в вашем пользовательском классе репозитория. :

public interface StudentRepository extends CrudRepository<Student, String>,
  CustomStudentRepository {
    ...
}

5. Заключение

В этом руководстве мы показали, как реализовать проверку сущности JSR-303 и добиться возможности оптимистической блокировки при использовании проекта сообщества Spring Data Couchbase.

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

Наконец, мы объяснили уровни согласованности по умолчанию, используемые Spring Data Couchbase глобально и для нескольких конкретных методов, и продемонстрировали способы переопределения глобального параметра согласованности по умолчанию, а также способы переопределения параметров согласованности для каждого запроса путем предоставления ваши собственные реализации репозитория.

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

Чтобы узнать больше о Spring Data Couchbase, посетите официальный сайт проекта Spring Data Couchbase .