Intro to Spring Data Couchbase

Les données]** lien:/catégorie/persistance/persistance de printemps/[persistance de printemps]

  • lien:/tag/couchbase/[Couchbase]

1. Introduction

Dans ce didacticiel sur les données Spring, nous expliquerons comment configurer une couche de persistance pour les documents Couchbase en utilisant à la fois le référentiel Spring Data et les abstractions de modèles, ainsi que les étapes nécessaires pour préparer Couchbase à la prise en charge de ces abstractions à l’aide de vues et/ou d’index .

2. Dépendances Maven

Premièrement, nous ajoutons la dépendance Maven suivante à notre fichier pom.xml :

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

Notez qu’en ajoutant cette dépendance, nous obtenons automatiquement une version compatible du SDK Couchbase natif. Il n’est donc pas nécessaire de l’inclure explicitement.

Pour ajouter la prise en charge de la validation de bean JSR-303, nous incluons également la dépendance suivante:

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

Spring Data Couchbase prend en charge la persistance de la date et de l’heure via les classes traditionnelles Date et Calendrier, ainsi que via la bibliothèque Joda Time, que nous incluons comme suit:

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

3. Configuration

Ensuite, nous devrons configurer l’environnement Couchbase en spécifiant un ou plusieurs nœuds de notre cluster Couchbase, ainsi que le nom et le mot de passe du compartiment dans lequel nous allons stocker nos documents.

3.1. Configuration Java

Pour la configuration de classe Java, nous étendons simplement la classe 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 "";
    }
}

Si votre projet nécessite davantage de personnalisation de l’environnement Couchbase, vous pouvez en fournir un en surchargeant la méthode getEnvironment () :

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

3.2. Configuration XML

Voici la configuration équivalente en 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>

Remarque: le nœud « clusterInfo » accepte les informations d’identification du cluster ou du compartiment. Il est obligatoire pour que la bibliothèque puisse déterminer si votre cluster Couchbase prend en charge N1QL (un sur-ensemble de bases de données NoSQL pour SQL, disponible dans Couchbase 4.0 et versions ultérieures).

Si votre projet requiert un environnement Couchbase personnalisé, vous pouvez en fournir un en utilisant la balise <couchbase: env/> .

4. Modèle de données

Créons une classe d’entité représentant le document JSON à conserver.

Nous annotons d’abord la classe avec @ Document, puis nous annotons un champ String avec @ Id pour représenter la clé de document Couchbase.

Vous pouvez utiliser l’annotation @ Id de Spring Data ou celle du kit de développement logiciel (SDK) Couchbase natif. Si vous utilisez les deux annotations @ Id de la même classe sur deux champs différents, le champ annoté avec l’annotation Spring Data @ Id aura priorité et sera utilisé comme clé de document.

Pour représenter les attributs des documents JSON, nous ajoutons des variables de membre privées annotées avec @ Field . Nous utilisons l’annotation @ NotNull pour marquer certains champs comme requis:

@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
}

Notez que la propriété annotée avec @ Id représente simplement la clé de document et ne fait pas nécessairement partie du document JSON stocké, sauf si elle est également annotée avec @ Field comme dans:

@Id
@Field
private String id;

Si vous souhaitez nommer un champ de la classe d’entité différemment de ce qui doit être stocké dans le document JSON, qualifiez simplement son annotation @ Field , comme dans cet exemple:

@Field("fname")
private String firstName;

Voici un exemple montrant à quoi ressemblerait un document persistant Person :

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

Notez que Spring Data ajoute automatiquement à chaque document un attribut contenant le nom complet de la classe de l’entité. Par défaut, cet attribut est nommé classe” , bien que vous puissiez le remplacer dans votre classe de configuration Couchbase en remplaçant la méthode typeKey () __.

Par exemple, si vous souhaitez désigner un champ nommé «dataType» pour contenir les noms de classe, vous devez l’ajouter à votre classe de configuration Couchbase:

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

Une autre raison courante de remplacer typeKey () est si vous utilisez une version de Couchbase Mobile qui ne prend pas en charge les champs précédés du trait de soulignement. Dans ce cas, vous pouvez choisir votre propre champ de type de remplacement, comme dans l’exemple précédent, ou vous pouvez utiliser un autre champ fourni par Spring:

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

5. Couchbase Repository

Spring Data Couchbase fournit les mêmes requêtes intégrées et les mêmes mécanismes de requête dérivés que d’autres modules Spring Data tels que JPA.

Nous déclarons une interface de référentiel pour la classe Person en étendant CrudRepository <String, Person> et en ajoutant une méthode de requête pouvant être dérivée:

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

6. Support N1QL via des index

Si vous utilisez Couchbase 4.0 ou version ultérieure, les requêtes personnalisées sont traitées par défaut à l’aide du moteur N1QL (sauf si les méthodes de référentiel correspondantes sont annotées avec @ View pour indiquer l’utilisation des vues de sauvegarde, comme décrit dans la section suivante).

Pour ajouter la prise en charge de N1QL, vous devez créer un index primaire sur le compartiment.

Vous pouvez créer l’index à l’aide du processeur de requête en ligne de commande cbq (voir la documentation de Couchbase sur le lancement de l’outil cbq pour votre environnement) et en exécutant la commande suivante:

CREATE PRIMARY INDEX ON baeldung USING GSI;

Dans la commande ci-dessus, GSI signifie global secondary index , qui est un type d’index particulièrement adapté à l’optimisation de requêtes ad hoc N1QL prenant en charge les systèmes OLTP. Il s’agit du type d’index par défaut, sauf indication contraire.

Contrairement aux index basés sur les vues, les index GSI ne sont pas automatiquement répliqués sur tous les noeuds d’index d’un cluster. Par conséquent, si votre cluster contient plusieurs noeuds d’index, vous devez créer chaque index GSI sur chaque noeud du cluster. un nom d’index différent sur chaque noeud.

Vous pouvez également créer un ou plusieurs index secondaires. Lorsque vous le ferez, Couchbase les utilisera au besoin afin d’optimiser son traitement des requêtes.

Par exemple, pour ajouter un index sur le champ firstName , exécutez la commande suivante dans l’outil cbq :

CREATE INDEX idx__firstName ON baeldung(firstName) USING GSI;

7. Sauvegardes de vues

Pour chaque interface de référentiel, vous devez créer un document de conception Couchbase et une ou plusieurs vues dans le compartiment cible. Le nom du document de conception doit être la version lowerCamelCase du nom de la classe d’entité (par exemple, «personne» ).

Quelle que soit la version de Couchbase Server que vous exécutez, vous devez créer une vue de sauvegarde nommée «all» pour prendre en charge la méthode de référentiel intégrée « findAll» . Voici la fonction map pour la vue «all» de notre classe Person :

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

Les méthodes de référentiel personnalisées doivent chacune avoir une vue de sauvegarde lors de l’utilisation d’une version de Couchbase antérieure à 4.0 (l’utilisation des vues de sauvegarde est facultative à partir de 4.0).

Les méthodes personnalisées basées sur une vue doivent être annotées avec @ View comme dans l’exemple suivant:

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

La convention de dénomination par défaut pour les vues de sauvegarde consiste à utiliser la version lowerCamelCase de cette partie du nom de la méthode après le mot clé " find" (par exemple, "byFirstName" ).

Voici comment vous écririez la fonction map pour la vue «byFirstName» :

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

Vous pouvez remplacer cette convention de dénomination et utiliser vos propres noms de vue en qualifiant chaque annotation @ View par le nom de votre vue de sauvegarde correspondante. Par exemple:

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

8. Couche de service

Pour notre couche de service, nous définissons une interface et deux implémentations:

une en utilisant l’abstraction du référentiel Spring Data et une autre en utilisant l’abstraction du modèle Spring Data. Voici notre interface 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 de référentiel

Voici une implémentation utilisant le référentiel défini ci-dessus:

@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. Service de template

Pour l’implémentation basée sur des modèles, nous devons créer les vues de sauvegarde répertoriées dans la section 7 ci-dessus. L’objet CouchbaseTemplate est disponible dans notre contexte Spring et peut être injecté dans la classe de service.

Voici l’implémentation utilisant l’abstraction du modèle:

@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. Conclusion

Nous avons montré comment configurer un projet pour utiliser le module Spring Data Couchbase et comment écrire une classe d’entité simple et son interface de référentiel. Nous avons écrit une interface de service simple et fourni une implémentation à l’aide du référentiel et une autre à l’aide de l’API de modèle Spring Data.

Vous pouvez visualiser le code source complet de ce didacticiel à l’adresse the GitHub .

Pour plus d’informations, visitez le site du projet Spring Data Couchbase .