En guide til Jdbi

1. Introduksjon

I denne artikkelen skal vi se på hvordan du kan spørre en relasjonsdatabase med jdbi.

Jdbi er et open source Java-bibliotek (Apache-lisens) som bruker lambdauttrykk og refleksjon for å gi et vennligere grensesnitt på høyere nivå enn JDBC for å få tilgang til databasen.

Jdbi er imidlertid ikke en ORM; Selv om den har en valgfri SQL Object-kartleggingsmodul, har den ikke en økt med tilknyttede objekter, et databaseuavhengighetslag og andre bjeller og fløyter av en typisk ORM.

2. Jdbi-oppsett

Jdbi er organisert i en kjerne og flere valgfrie moduler.

For å komme i gang, må vi bare inkludere kjernemodulen i våre avhengigheter:

  org.jdbi jdbi3-core 3.1.0 

I løpet av denne artikkelen viser vi eksempler ved bruk av HSQL-databasen:

 org.hsqldb hsqldb 2.4.0 test 

Vi finner den nyeste versjonen av jdbi3-kjerne, HSQLDB og de andre Jdbi-modulene på Maven Central.

3. Koble til databasen

Først må vi koble til databasen. For å gjøre det, må vi spesifisere tilkoblingsparametrene.

Utgangspunktet er Jdbi klasse:

Jdbi jdbi = Jdbi.create ("jdbc: hsqldb: mem: testDB", "sa", "");

Her spesifiserer vi tilkoblings-URL, et brukernavn og selvfølgelig et passord.

3.1. Tilleggsparametere

Hvis vi trenger å oppgi andre parametere, bruker vi en overbelastet metode som godtar a Eiendommer gjenstand:

Egenskaper egenskaper = nye egenskaper (); properties.setProperty ("brukernavn", "sa"); properties.setProperty ("passord", ""); Jdbi jdbi = Jdbi.create ("jdbc: hsqldb: mem: testDB", egenskaper);

I disse eksemplene har vi lagret Jdbi forekomst i en lokal variabel. Det er fordi vi bruker den til å sende uttalelser og spørsmål til databasen.

Faktisk bare å ringe skape oppretter ingen forbindelse til DB. Det lagrer bare tilkoblingsparametrene for senere.

3.2. Bruker en Datakilde

Hvis vi kobler til databasen ved hjelp av en Datakilde, som det vanligvis er tilfelle, kan vi bruke det aktuelle skape overbelastning:

Jdbi jdbi = Jdbi.create (datakilde);

3.3. Arbeide med håndtak

Faktiske tilkoblinger til databasen er representert av forekomster av Håndtak klasse.

Den enkleste måten å jobbe med håndtakene, og få dem automatisk lukket, er å bruke lambdauttrykk:

jdbi.useHandle (håndtak -> {doStuffWith (håndtak);});

Vi ringer useHandle når vi ikke trenger å returnere en verdi.

Ellers bruker vi medHåndtak:

jdbi.withHandle (håndtak -> {return computeValue (håndtak);});

Det er også mulig, men ikke anbefalt, å åpne et tilkoblingshåndtak manuelt; i så fall må vi lukke det når vi er ferdige:

Jdbi jdbi = Jdbi.create ("jdbc: hsqldb: mem: testDB", "sa", ""); prøv (Håndtak = jdbi.open ()) {doStuffWith (håndtak); }

Heldigvis, som vi kan se, Håndtak redskaper Lukkbar, slik at den kan brukes med prøve-med-ressurser.

4. Enkle uttalelser

Nå som vi vet hvordan vi skal få en forbindelse, la oss se hvordan vi bruker den.

I denne delen lager vi en enkel tabell som vi vil bruke gjennom hele artikkelen.

Å sende uttalelser som lage bord til databasen bruker vi henrette metode:

handle.execute ("create table project" + "(id integer identity, name varchar (50), url varchar (100))");

henrette returnerer antall rader som ble berørt av utsagnet:

int updateCount = handle.execute ("sett inn i prosjektverdier" + "(1, 'tutorials', 'github.com/eugenp/tutorials')"); assertEquals (1, updateCount);

Egentlig er utførelse bare en praktisk metode.

Vi vil se på mer komplekse brukssaker i senere seksjoner, men før vi gjør det, må vi lære å hente ut resultater fra databasen.

5. Spørring av databasen

Det mest enkle uttrykket som gir resultater fra DB er et SQL-spørsmål.

For å sende et spørsmål med et Jdbi-håndtak, må vi i det minste:

  1. opprette spørringen
  2. velg hvordan du skal representere hver rad
  3. iterere over resultatene

Vi ser nå på hvert av punktene ovenfor.

5.1. Opprette en spørring

Ikke overraskende, Jdbi representerer spørsmål som forekomster av Spørsmål klasse.

Vi kan skaffe en fra et håndtak:

Query query = handle.createQuery ("velg * fra prosjekt");

5.2. Kartlegge resultatene

Jdbi trekker seg fra JDBC ResultatSett, som har et ganske tungvint API.

Derfor gir det flere muligheter for å få tilgang til kolonnene som skyldes et spørsmål eller en annen uttalelse som returnerer et resultat. Vi får nå se de enkleste.

Vi kan representere hver rad som et kart:

query.mapToMap ();

Tastene på kartet vil være de valgte kolonnenavnene.

Eller når et spørsmål returnerer en enkelt kolonne, kan vi kartlegge den til ønsket Java-type:

handle.createQuery ("velg navn fra prosjekt"). mapTo (String.class);

Jdbi har innebygde kartleggere for mange vanlige klasser. De som er spesifikke for noe bibliotek eller databasesystem, er gitt i separate moduler.

Selvfølgelig kan vi også definere og registrere kartleggere våre. Vi vil snakke om det i en senere del.

Til slutt kan vi kartlegge rader til en bønne eller en annen tilpasset klasse. Igjen vil vi se de mer avanserte alternativene i en dedikert seksjon.

5.3. Iterere over resultatene

Når vi har bestemt oss for hvordan vi skal kartlegge resultatene ved å kalle den riktige metoden, vi mottar en ResultatIterabelt gjenstand.

Vi kan deretter bruke den til å gjenta resultatene, en rad om gangen.

Her ser vi på de vanligste alternativene.

Vi kan bare samle resultatene i en liste:

Liste resultater = query.mapToMap (). liste ();

Eller til en annen Samling type:

Listeresultater = query.mapTo (String.class) .collect (Collectors.toSet ());

Eller vi kan gjenta resultatene som en strøm:

query.mapTo (String.class) .useStream ((Stream stream) -> {doStuffWith (stream)});

Her skrev vi eksplisitt strøm variabel for klarhet, men det er ikke nødvendig å gjøre det.

5.4. Få et enkelt resultat

Som et spesielt tilfelle, når vi forventer eller er interessert i bare en rad, har vi et par dedikerte metoder tilgjengelig.

Hvis vi vil høyst ett resultat, Vi kan bruke findFirst:

Valgfri først = query.mapToMap (). findFirst ();

Som vi kan se, returnerer den en Valgfri verdi, som bare er til stede hvis spørringen returnerer minst ett resultat.

Hvis spørringen returnerer mer enn én rad, returneres bare den første.

Hvis vi i stedet ønsker det ett og bare ett resultat, vi bruker finnBare:

Date onlyResult = query.mapTo (Date.class) .findOnly ();

Til slutt, hvis det er null resultater eller mer enn ett, finnBare kaster en IllegalStateException.

6. Bindende parametere

Ofte, spørringer har en fast del og en parameterisert del. Dette har flere fordeler, inkludert:

  • sikkerhet: ved å unngå sammenkobling av strenger, forhindrer vi SQL-injeksjon
  • letthet: vi trenger ikke å huske den eksakte syntaksen til komplekse datatyper som tidsstempler
  • ytelse: den statiske delen av spørringen kan analyseres en gang og bufres

Jdbi støtter både posisjonelle og navngitte parametere.

Vi setter inn posisjonsparametere som spørsmålstegn i et spørsmål eller utsagn:

Query positionalParamsQuery = handle.createQuery ("velg * fra prosjekt hvor navn =?");

Navngitte parametere starter i stedet med et kolon:

Query namedParamsQuery = handle.createQuery ("select * from project where url like: pattern");

I begge tilfeller bruker vi en av variantene til å angi verdien til en parameter binde metode:

positionalParamsQuery.bind (0, "tutorials"); heterParamsQuery.bind ("mønster", "% github.com / eugenp /%");

Merk at, i motsetning til JDBC, starter indekser på 0.

6.1. Binding av flere navngitte parametere samtidig

Vi kan også binde flere navngitte parametere sammen ved hjelp av et objekt.

La oss si at vi har dette enkle spørsmålet:

Query query = handle.createQuery ("velg id fra prosjekt hvor navn =: navn og url =: url"); Kartparametere = nye HashMap (); params.put ("name", "REST with Spring"); params.put ("url", "github.com/eugenp/REST-With-Spring");

Så kan vi for eksempel bruke et kart:

query.bindMap (params);

Eller vi kan bruke et objekt på forskjellige måter. Her, for eksempel, binder vi et objekt som følger JavaBean-konvensjonen:

query.bindBean (paramsBean);

Men vi kunne også binde et objekts felt eller metoder; for alle støttede alternativer, se Jdbi-dokumentasjonen.

7. Utstede mer komplekse uttalelser

Nå som vi har sett spørsmål, verdier og parametere, kan vi gå tilbake til utsagn og bruke samme kunnskap.

Husk at henrette metoden vi så tidligere er bare en praktisk snarvei.

Faktisk, på samme måte som spørsmål, DDL og DML uttalelser er representert som forekomster av klassen Oppdater.

Vi kan få en ved å ringe metoden createUpdate på et håndtak:

Oppdater oppdatering = handle.createUpdate ("INSERT IN PROJECT (NAME, URL) VALUES (: name,: url)");

Så, på en Oppdater vi har alle bindingsmetodene som vi har i a Spørsmål, så avsnitt 6. gjelder også for oppdateringer. url

Uttalelser utføres når vi ringer, overrasker, henrette:

int-rader = update.execute ();

Som vi allerede har sett, returnerer det antallet berørte rader.

7.1. Henter ut automatisk økning av kolonneverdier

Som et spesielt tilfelle, når vi har en innsettingsuttalelse med automatisk genererte kolonner (vanligvis automatisk økning eller sekvenser), vil vi kanskje hente de genererte verdiene.

Da ringer vi ikke henrette, men executeAndReturnGeneratedKeys:

Oppdater oppdatering = handle.createUpdate ("INSERT IN PROJECT (NAME, URL)" + "VALUES ('tutorials', 'github.com/eugenp/tutorials')"); ResultBearing generatedKeys = update.executeAndReturnGeneratedKeys ();

ResultatBærende er det samme grensesnittet implementert av Spørsmål klasse som vi har sett tidligere, så vi vet allerede hvordan vi bruker det:

generatedKeys.mapToMap () .findOnly (). get ("id");

8. Transaksjoner

Vi trenger en transaksjon når vi må utføre flere utsagn som en enkelt atomoperasjon.

Som med tilkoblingshåndtak introduserer vi en transaksjon ved å ringe en metode med lukking:

handle.useTransaction ((Håndtak h) -> {haveFunWith (h);});

Og som med håndtak, lukkes transaksjonen automatisk når stengingen kommer tilbake.

Vi må imidlertid begå eller tilbakebetale transaksjonen før retur:

handle.useTransaction ((Handle h) -> {h.execute ("..."); h.commit ();});

Hvis imidlertid et unntak blir kastet fra nedleggelsen, ruller Jdbi automatisk transaksjonen tilbake.

Som med håndtak, har vi en dedikert metode, iTransaksjon, hvis vi vil returnere noe fra nedleggelsen:

handle.inTransaction ((Handle h) -> {h.execute ("..."); h.commit (); return true;});

8.1. Manuell transaksjonsstyring

Selv om det generelt ikke anbefales, kan vi også begynne og Lukk en transaksjon manuelt:

handle.begin (); // ... handle.commit (); handle.close ();

9. Konklusjoner og videre lesing

I denne opplæringen har vi introdusert kjernen til Jdbi: spørsmål, uttalelser og transaksjoner.

Vi har utelatt noen avanserte funksjoner, som tilpasset rad- og kolonnekartlegging og batchbehandling.

Vi har heller ikke diskutert noen av de valgfrie modulene, særlig SQL Object-utvidelsen.

Alt er presentert i detalj i Jdbi-dokumentasjonen.

Implementeringen av alle disse eksemplene og kodebitene finnes i GitHub-prosjektet - dette er et Maven-prosjekt, så det skal være enkelt å importere og kjøre som det er.


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