Entitätsprüfung, optimistische Sperrung und Abfragekonsistenz in Spring Data Couchbase

Entitätsvalidierung, optimistische Sperre und Abfragekonsistenz in Spring Data Couchbase

1. Einführung

Nach unserenintroduction to Spring Data Couchbase konzentrieren wir uns in diesem zweiten Lernprogramm auf die Unterstützung der Entitätsvalidierung (JSR-303), das optimistische Sperren und verschiedene Ebenen der Abfragekonsistenz für eine Couchbase-Dokumentendatenbank.

2. Entitätsvalidierung

Spring Data Couchbase bietet Unterstützung für JSR-303-Entitätsvalidierungsanmerkungen. Um diese Funktion nutzen zu können, fügen wir zunächst die JSR-303-Bibliothek zum Abschnitt "Abhängigkeiten" unseres Maven-Projekts hinzu:


    javax.validation
    validation-api
    1.1.0.Final

Dann fügen wir eine Implementierung von JSR-303 hinzu. Wir werden die Hibernate-Implementierung verwenden:


    org.hibernate
    hibernate-validator
    5.2.4.Final

Schließlich fügen wir unserer Couchbase-Konfiguration eine Validator-Factory-Bean und einen entsprechenden Couchbase-Ereignis-Listener hinzu:

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

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

Die entsprechende XML-Konfiguration sieht folgendermaßen aus:



Jetzt fügen wir unseren Entitätsklassen JSR-303-Annotationen hinzu. Wenn während einer Persistenzoperation eine Einschränkungsverletzung auftritt, schlägt die Operation fehl und wirftConstraintViolationException aus.

Hier ist ein Beispiel für die Einschränkungen, die wir für unsereStudent-Entitäten erzwingen können:

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

...
@Field
@Past
private DateTime dateOfBirth;

3. Optimistisches Sperren

Spring Data Couchbase unterstützt keine Transaktionen mit mehreren Dokumenten, die denen ähneln, die Sie in anderen Spring Data-Modulen wie Spring Data JPA (über die Annotation@Transactional) erzielen können, und bietet auch keine Rollback-Funktion.

Durch die Verwendung der Annotation@Versionwird jedoch das optimistische Sperren ähnlich wie bei anderen Spring Data-Modulen unterstützt:

@Version
private long version;

Im Hintergrund verwendet Couchbase einen sogenannten CAS-Mechanismus (Compare and Swap), um eine optimistische Sperrung auf Datenspeicherebene zu erzielen.

Jedem Dokument in Couchbase ist ein CAS-Wert zugeordnet, der automatisch geändert wird, wenn die Metadaten oder Inhalte des Dokuments geändert werden. Die Verwendung der Annotation@Version in einem Feld bewirkt, dass dieses Feld mit dem aktuellen CAS-Wert gefüllt wird, wenn ein Dokument aus Couchbase abgerufen wird.

Wenn Sie versuchen, das Dokument wieder in Couchbase zu speichern, wird dieses Feld mit dem aktuellen CAS-Wert in Couchbase verglichen. Wenn die Werte nicht übereinstimmen, schlägt die Persistenzoperation mitOptimisticLockingException fehl.

Es istextremely important zu beachten, dass Sie niemals versuchen sollten, auf dieses Feld in Ihrem Code zuzugreifen oder es zu ändern.

4. Abfragekonsistenz

Wenn Sie eine Persistenzschicht über Couchbase implementieren, müssen Sie die Möglichkeit veralteter Lese- und Schreibvorgänge berücksichtigen. Dies liegt daran, dass es beim Einfügen, Aktualisieren oder Löschen von Dokumenten einige Zeit dauern kann, bis die Sicherungsansichten und -indizes aktualisiert werden, um diese Änderungen widerzuspiegeln.

Und wenn Sie einen großen Datensatz haben, der von einem Cluster von Couchbase-Knoten unterstützt wird, kann dies zu einem erheblichen Problem werden, insbesondere für ein OLTP-System.

Spring Data bietet eine solide Konsistenz für einige Repository- und Vorlagenvorgänge sowie einige Optionen, mit denen Sie die für Ihre Anwendung akzeptable Lese- und Schreibkonsistenz bestimmen können.

4.1. Konsistenzstufen

Mit Spring Data können Sie verschiedene Ebenen der Abfragekonsistenz und -qualität für Ihre Anwendung über die im Paketorg.springframework.data.couchbase.core.queryenthaltene AufzählungConsistencyangeben.

Diese Aufzählung definiert die folgenden Stufen der Abfragekonsistenz und -festigkeit, von der niedrigsten bis zur strengsten:

  • EVENTUALLY_CONSISTENT

    • veraltete Lesevorgänge sind zulässig

    • Indizes werden gemäß dem Couchbase-Standardalgorithmus aktualisiert

  • UPDATE_AFTER

    • veraltete Lesevorgänge sind zulässig

    • Indizes werden nach jeder Anforderung aktualisiert

  • DEFAULT_CONSISTENCY (wieREAD_YOUR_OWN_WRITES)

  • READ_YOUR_OWN_WRITES

    • Veraltete Lesevorgänge sind nicht zulässig

    • Indizes werden nach jeder Anforderung aktualisiert

  • STRONGLY_CONSISTENT

    • Veraltete Lesevorgänge sind nicht zulässig

    • Indizes werden nach jeder Anweisung aktualisiert

4.2. Standardverhalten

Stellen Sie sich vor, Sie haben Dokumente, die aus Couchbase gelöscht wurden, und die Hintergrundansichten und -indizes wurden nicht vollständig aktualisiert.

Die inCouchbaseRepositoryintegrierte MethodedeleteAll()ignoriert Dokumente, die in der Hintergrundansicht gefunden wurden, deren Löschung jedoch noch nicht in der Ansicht angezeigt wird.

Ebenso bieten die inCouchbaseTemplateintegrierten MethodenfindByView undfindBySpatialView ein ähnliches Maß an Konsistenz, da keine Dokumente zurückgegeben werden, die ursprünglich in der Hintergrundansicht gefunden wurden, aber inzwischen gelöscht wurden.

Für alle anderen Vorlagenmethoden, integrierten Repository-Methoden und abgeleiteten Repository-Abfragemethoden verwendet Spring Data gemäß der offiziellen Dokumentation zu Spring Data Couchbase 2.1.x zum jetzigen Zeitpunkt eine Standardkonsistenzstufe vonConsistency.READ_YOUR_OWN_WRITES.

Es ist erwähnenswert, dass frühere Versionen der Bibliothek einen Standardwert vonConsistency.UPDATE_AFTER verwendeten.

Unabhängig von der verwendeten Version bietet Spring zwei Methoden an, mit denen Sie die verwendete (n) Konsistenzstufe (n) deklarativ steuern können, wenn Sie Bedenken haben, die angegebene Standardkonsistenzstufe blind zu akzeptieren, wie in den folgenden Unterabschnitten beschrieben wird.

4.3. Globale Konsistenzeinstellung

Wenn Sie Couchbase-Repositorys verwenden und Ihre Anwendung eine stärkere Konsistenz erfordert oder eine schwächere Ebene tolerieren kann, können Sie die Standardkonsistenzeinstellung für alle Repositorys überschreiben, indem Sie die MethodegetDefaultConsistency()in Ihrer Couchbase-Konfiguration überschreiben .

So können Sie die globale Konsistenzstufe in Ihrer Couchbase-Konfigurationsklasse überschreiben:

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

Hier ist die entsprechende XML-Konfiguration:

Beachten Sie, dass der Preis für strengere Konsistenzstufen die Latenz zum Zeitpunkt der Abfrage erhöht. Passen Sie diese Einstellung daher unbedingt an die Anforderungen Ihrer Anwendung an.

Beispielsweise wäre ein Data Warehouse oder eine Berichtsanwendung, in der Daten häufig nur in einem Stapel angehängt oder aktualisiert werden, ein guter Kandidat fürEVENTUALLY_CONSISTENT, während eine OLTP-Anwendung wahrscheinlich zu strengeren Ebenen wieREAD_YOUR_OWN_WRITEStendieren sollte ) s oderSTRONGLY_CONSISTENT.

4.4. Implementierung einer benutzerdefinierten Konsistenz

Wenn Sie genauere Konsistenzeinstellungen benötigen, können Sie die Standardkonsistenzstufe abfrageweise überschreiben, indem Sie Ihre eigene Repository-Implementierung für alle Abfragen bereitstellen, deren Konsistenzstufe Sie unabhängig steuern möchten, undqueryViewverwenden. s und / oderqueryN1QL Methoden, die vonCouchbaseTemplate bereitgestellt werden.

Implementieren wir eine benutzerdefinierte Repository-Methode namensfindByFirstNameStartsWith für unsereStudent-Entität, für die wir keine veralteten Lesevorgänge zulassen möchten.

Erstellen Sie zunächst eine Schnittstelle mit der benutzerdefinierten Methodendeklaration:

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

Implementieren Sie als Nächstes die Schnittstelle und setzen Sie die EinstellungStaleaus dem zugrunde liegenden Couchbase Java SDK auf die gewünschte Ebene:

public class CustomStudentRepositoryImpl implements CustomStudentRepository {

    @Autowired
    private CouchbaseTemplate template;

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

Wenn Ihre Standard-Repository-Schnittstelle sowohl die generischeCrudRepository-Schnittstelle als auch Ihre benutzerdefinierte Repository-Schnittstelle erweitert, haben Clients Zugriff auf alle integrierten und abgeleiteten Methoden Ihrer Standard-Repository-Schnittstelle sowie auf alle benutzerdefinierten Methoden, die Sie implementiert haben Ihre benutzerdefinierte Repository-Klasse:

public interface StudentRepository extends CrudRepository,
  CustomStudentRepository {
    ...
}

5. Fazit

In diesem Lernprogramm wurde gezeigt, wie Sie die JSR-303-Entitätsvalidierung implementieren und eine optimistische Sperrfunktion erzielen, wenn Sie das Community-Projekt Spring Data Couchbase verwenden.

Wir haben auch die Notwendigkeit des Verständnisses der Abfragekonsistenz in Couchbase erörtert und die verschiedenen Konsistenzstufen eingeführt, die Spring Data Couchbase bietet.

Schließlich haben wir die von Spring Data Couchbase global und für einige bestimmte Methoden verwendeten Standardkonsistenzstufen erläutert und Möglichkeiten aufgezeigt, wie die globale Standardkonsistenzeinstellung außer Kraft gesetzt werden kann und wie Konsistenzeinstellungen abfrageweise durch Bereitstellung außer Kraft gesetzt werden können Ihre eigenen benutzerdefinierten Repository-Implementierungen.

Sie können den vollständigen Quellcode für dieses Lernprogramm inthe GitHub project anzeigen.

Um mehr über Spring Data Couchbase zu erfahren, besuchen Sie die offizielleSpring Data Couchbase-Projektseite.