Bruke Couchbase i en vårapplikasjon

1. Introduksjon

I denne oppfølgingen til vår introduksjon til Couchbase oppretter vi et sett med Spring-tjenester som kan brukes sammen for å lage et grunnleggende utholdenhetslag for en Spring-applikasjon uten bruk av Spring Data.

2. Klyngetjeneste

For å tilfredsstille begrensningen at bare en enkelt CouchbaseEnvironment kan være aktiv i JVM, begynner vi med å skrive en tjeneste som kobles til en Couchbase-klynge og gir tilgang til datasett uten direkte å utsette Klynge eller CouchbaseEnvironment tilfeller.

2.1. Grensesnitt

Her er vår ClusterService grensesnitt:

offentlig grensesnitt ClusterService {Bucket openBucket (strengnavn, strengpassord); }

2.2. Gjennomføring

Vår implementeringsklasse instantierer en DefaultCouchbaseEnvironment og kobles til en klynge under @PostConstruct fase under vårkontekstinitialisering.

Dette sikrer at klyngen ikke er null, og at den er koblet til når klassen injiseres i andre tjenesteklasser, slik at de kan åpne en eller flere datasett:

@Service offentlig klasse ClusterServiceImpl implementerer ClusterService {privat klyngeklynge; @PostConstruct private void init () {CouchbaseEnvironment env = DefaultCouchbaseEnvironment.create (); klynge = CouchbaseCluster.create (env, "localhost"); } ...}

Deretter gir vi en ConcurrentHashMap å inneholde de åpne skuffene og implementere openBucket metode:

private Map bøtter = nye ConcurrentHashMap (); @ Override synkronisert offentlig Bucket openBucket (strengnavn, strengpassord) {if (! Buckets.containsKey (name)) {Bucket bucket = cluster.openBucket (navn, passord); buckets.put (navn, bøtte); } returner bøtter. få (navn); }

3. Skuffeservice

Avhengig av hvordan du arkitekterer søknaden din, kan det hende du må gi tilgang til den samme databøtta i flere Spring-tjenester.

Hvis vi bare forsøkte å åpne den samme bøtta i to eller flere tjenester under oppstart av applikasjonen, er det sannsynlig at den andre tjenesten som prøver dette vil støte på en ConcurrentTimeoutException.

For å unngå dette scenariet definerer vi a BucketService grensesnitt og en implementeringsklasse per bøtte. Hver implementeringsklasse fungerer som en bro mellom ClusterService og klassene som trenger direkte tilgang til et bestemt Bøtte.

3.1. Grensesnitt

Her er vår BucketService grensesnitt:

offentlig grensesnitt BucketService {Bucket getBucket (); }

3.2. Gjennomføring

Følgende klasse gir tilgang til “baeldung-tutorial”Bøtte:

@Service @Qualifier ("TutorialBucketService") offentlig klasse TutorialBucketService implementerer BucketService {@Autowired private ClusterService couchbase; privat bøtte bøtte; @ PostConstruct privat ugyldig init () {bucket = couchbase.openBucket ("baeldung-tutorial", ""); } @ Override public Bucket getBucket () {return bucket; }}

Ved å injisere ClusterService i vår TutorialBucketService implementeringsklasse og åpne bøtta i en metode kommentert med @PostConstruct, Vi har sørget for at skuffen vil være klar til bruk når TutorialBucketService blir deretter injisert i andre tjenester.

4. Persistenslag

Nå som vi har en tjeneste på plass for å få en Bøtte For eksempel vil vi lage et lagringslignende utholdenhetslag som gir CRUD-operasjoner for enhetsklasser til andre tjenester uten å eksponere Bøtte eksempel til dem.

4.1. Personenheten

Her er Person enhetsklasse som vi ønsker å vedvare:

offentlig klasse person {privat streng-id; privat streng type; privat strengnavn; privat String hjemby; // standard getters og setters}

4.2. Konvertering av enhetsklasser til og fra JSON

Å konvertere enhetsklasser til og fra JsonDocument objekter som Couchbase bruker i sin utholdenhetsoperasjon, definerer vi JsonDocumentConverter grensesnitt:

offentlig grensesnitt JsonDocumentConverter {JsonDocument toDocument (T t); T fromDocument (JsonDocument doc); }

4.3. Implementering av JSON Converter

Deretter må vi implementere en JsonConverter til Person enheter.

@Service offentlig klasse PersonDocumentConverter implementerer JsonDocumentConverter {...}

Vi kunne bruke Jackson bibliotek i forbindelse med JsonObject klasse toJson og fraJson metoder for å serieisere og deserialisereenheter, men det er ekstra overhead å gjøre det.

I stedet for å dokumentere metoden, bruker vi flytende metoder for JsonObject klasse for å opprette og fylle ut en JsonObject før du pakker den inn a JsonDocument:

@Override public JsonDocument toDocument (Person p) {JsonObject content = JsonObject.empty () .put ("type", "Person") .put ("name", p.getName ()) .put ("homeTown", p .getHomeTown ()); returner JsonDocument.create (p.getId (), innhold); }

Og for fra Dokument metoden, bruker viJsonObject klasse getString metoden sammen med setterne i Person klasse i vår fra Dokument metode:

@Override public Person fromDocument (JsonDocument doc) {JsonObject content = doc.content (); Person p = ny person (); p.setId (doc.id ()); p.setType ("Person"); p.setName (content.getString ("navn")); p.setHomeTown (content.getString ("hjemby")); retur p; }

4.4. CRUD-grensesnitt

Vi lager nå en generikk CrudService grensesnitt som definerer utholdenhetsoperasjoner for enhetsklasser:

offentlig grensesnitt CrudService {void create (T t); T read (String id); T readFromReplica (streng-id); ugyldig oppdatering (T t); ugyldig sletting (streng-id); boolsk eksisterer (streng-id); }

4.5. Implementering av CRUD-tjenesten

Med enhet- og omformerklassene på plass implementerer vi nå CrudService for Person enhet, injiserer skuffetjenesten og dokumentomformeren vist ovenfor og henter skuffen under initialiseringen:

@Service offentlig klasse PersonCrudService implementerer CrudService {@Autowired private TutorialBucketService bucketService; @Autowired privat PersonDocumentConverter-omformer; privat bøtte bøtte; @PostConstruct privat ugyldig init () {bucket = bucketService.getBucket (); } @Override public void create (Person person) {if (person.getId () == null) {person.setId (UUID.randomUUID (). ToString ()); } JsonDocument-dokument = converter.toDocument (person); bucket.insert (dokument); } @ Override offentlig person lest (String id) {JsonDocument doc = bucket.get (id); retur (doc! = null? converter.fromDocument (doc): null); } @ Override offentlig person readFromReplica (streng-id) {List docs = bucket.getFromReplica (id, ReplicaMode.FIRST); return (docs.isEmpty ()? null: converter.fromDocument (docs.get (0))); } @Override offentlig ugyldig oppdatering (personperson) {JsonDocument document = converter.toDocument (person); bucket.upsert (dokument); } @ Overstyr offentlig ugyldig sletting (streng-id) {bucket.remove (id); } @Override offentlig boolsk eksisterer (streng-id) {return bucket.exists (id); }}

5. Sette det hele sammen

Nå som vi har alle delene av utholdenhetslaget på plass, er det et enkelt eksempel på en registreringstjeneste som bruker PersonCrudService for å vedvare og hente registranter:

@Service offentlig klasse RegistrationService {@Autowired privat PersonCrudService crud; public void registerNewPerson (String name, String homeTown) {Person person = new Person (); person.setName (navn); person.setHomeTown (hjemby); crud.create (person); } public Person findRegistrant (String id) {try {return crud.read (id); } fange (CouchbaseException e) {return crud.readFromReplica (id); }}}

6. Konklusjon

Vi har vist at det med noen få grunnleggende Spring-tjenester er ganske trivielt å innlemme Couchbase i en Spring-applikasjon og implementere et grunnleggende utholdenhetslag uten å bruke Spring Data.

Kildekoden som vises i denne opplæringen, er tilgjengelig i GitHub-prosjektet.

Du kan lære mer om Couchbase Java SDK på det offisielle dokumentasjonssiden for Couchbase-utvikler.


$config[zx-auto] not found$config[zx-overlay] not found