En guide til sql2o JDBC Wrapper

1. Introduksjon

I denne opplæringen skal vi ta en titt på Sql2o, et lite og raskt bibliotek for relasjonell databasetilgang i idiomatisk Java.

Det er verdt å nevne at selv om Sql2o fungerer ved å kartlegge søkeresultater til POJOer (vanlige gamle Java-objekter), det er ikke en komplett ORM-løsning som Hibernate.

2. Sql2o-oppsett

SQL2O er en enkelt jar-fil som vi enkelt kan legge til i prosjektets avhengighet:

 org.sql2o sql2o 1.6.0 

Vi bruker også HSQL, den innebygde databasen, i eksemplene våre; For å følge med kan vi også inkludere det:

 org.hsqldb hsqldb 2.4.0 test 

Maven Central er vert for den siste versjonen av kvl2o og HSQLDB.

3. Koble til databasen

For å etablere en forbindelse, starter vi fra en forekomst av Sql2o klasse:

Sql2o sql2o = ny Sql2o ("jdbc: hsqldb: mem: testDB", "sa", "");

Her spesifiserer vi tilkoblings-URL, brukernavn og passord som konstruktørparametere.

De Sql2o objektet er trådsikkert, og vi kan dele det på tvers av applikasjonen.

3.1. Bruker en Datakilde

I de fleste applikasjoner vil vi bruke en Datakildei stedet for en rå DriverManager tilkobling, kanskje for å utnytte en tilkoblingsgruppe, eller for å spesifisere flere tilkoblingsparametere. Bekymre deg ikke, Sql2o har fått oss dekket:

Sql2o sql2o = ny Sql2o (datakilde);

3.2. Arbeide med tilkoblinger

Bare instantiating a Sql2o objektet oppretter ingen forbindelse til databasen.

I stedet, vi bruker åpen metode for å få en Forbindelse gjenstand (merk at det ikke er en JDBC Forbindelse). Siden Forbindelse er Kan lukkes automatisk, vi kan pakke den inn i en prøve-med-ressurs-blokk:

prøv (Tilkoblingstilkobling = sql2o.open ()) {// bruk tilkoblingen}

4. Sett inn og oppdater uttalelser

La oss nå opprette en database og legge inn noen data i den. Gjennom opplæringen bruker vi en enkel tabell som heter prosjekt:

connection.createQuery ("opprett tabellprosjekt" + "(id heltall identitet, navn varchar (50), url varchar (100))"). executeUpdate ();

executeUpdate returnerer Forbindelse objekt slik at vi kan kjede flere samtaler. Så hvis vi vil vite antall berørte rader, bruker vi getResult:

assertEquals (0, connection.getResult ());

Vi bruker mønsteret som vi nettopp har sett - createQuery og executeUpdate -for alle DDL, INSERT og UPDATE uttalelser.

4.1. Få genererte nøkkelverdier

I noen tilfeller, skjønt, kan det være lurt å få genererte nøkkelverdier tilbake. Dette er verdiene til nøkkelkolonner som automatisk beregnes (som når du bruker automatisk økning i bestemte databaser).

Vi gjør det i to trinn. Først med en ekstra parameter til createQuery:

Query query = connection.createQuery ("sett inn i prosjekt (navn, url)" + "verdier ('tutorials', 'github.com/eugenp/tutorials')", true);

Så påkaller getKey på forbindelsen:

assertEquals (0, query.executeUpdate (). getKey ());

Hvis tastene er mer enn én, bruker vi getKeys i stedet, som returnerer en matrise:

assertEquals (1, query.executeUpdate (). getKeys () [0]);

5. Hente ut data fra databasen

La oss nå komme til kjernen i saken: Å VELGE spørsmål og kartlegging av resultatsett til Java-objekter.

Først må vi definere en POJO-klasse med getters og settere for å representere prosjektbordet vårt:

offentlig klasse Prosjekt {lang id; privat strengnavn; privat String url; // Standard getters og setters}

Så, som før, skriver vi spørsmålet vårt:

Query query = connection.createQuery ("select * from project order by id");

Denne gangen bruker vi imidlertid en ny metode, executeAndFetch:

Listeliste = query.executeAndFetch (Project.class);

Som vi ser, tar metoden klassen av resultatene som en parameter, som Sql2o vil kartlegge radene til det rå resultatsettet som kommer fra databasen.

5.1. Kolonnekartlegging

SQL2o kartlegger kolonner til JavaBean-egenskaper etter navn, store og små bokstaver

Navnekonvensjoner er imidlertid forskjellige mellom Java og relasjonsdatabaser. Anta at vi legger til en egenskap for opprettelsesdato til prosjektene våre:

offentlig klasseprosjekt {lang id; privat strengnavn; privat String url; private Date creationDate; // Standard getters og setters}

I databaseskjemaet vil vi sannsynligvis kalle den samme egenskapen opprettelsesdato.

Selvfølgelig kan vi alias det i spørsmålene våre:

Query query = connection.createQuery ("velg navn, url, creation_date som creationDate fra prosjekt");

Imidlertid er det kjedelig og vi mister muligheten for å bruke å velge *.

Et annet alternativ er å instruere Sql2o om å kartlegge opprettelsesdato til opprettelsesdato. Det vil si at vi kan fortelle spørsmålet om kartleggingen:

connection.createQuery ("velg * fra prosjekt") .addColumnMapping ("creation_date", "creationDate");

Dette er hyggelig hvis vi bruker opprettelsesdato sparsomt, i en håndfull spørsmål; når det brukes mye i et større prosjekt, blir det imidlertid kjedelig og feilutsatt å fortelle det samme om og om igjen.

Heldigvis kan vi også spesifiser kartlegginger globalt:

Karttilordning = ny HashMap (); mappings.put ("CREATION_DATE", "creationDate"); sql2o.setDefaultColumnMappings (mappings);

Selvfølgelig vil dette føre til hver forekomst av opprettelsesdato som skal kartlegges til opprettelsesdato, så det er en annen grunn til å streve for å holde navnene konsistente på tvers av definisjonene av dataene våre.

5.2. Skalarresultater

Noen ganger ønsker vi å trekke ut et enkelt skalarresultat fra et spørsmål. For eksempel når vi trenger å telle antall poster.

I disse tilfellene er det for mye å definere en klasse og gjentatte over en liste som vi vet å inneholde et enkelt element. Og dermed, SQL2O inkluderer executeScalar metode:

Query query = connection.createQuery ("select count (*) from project"); assertEquals (2, query.executeScalar (Integer.class));

Her spesifiserer vi returtypen som skal være Heltall. Det er imidlertid valgfritt, og vi kan la den underliggende JDBC-driveren bestemme.

5.3. Komplekse resultater

Noen ganger kan komplekse spørsmål (for eksempel for rapportering) ikke enkelt kartlegges på et Java-objekt. Vi kan også bestemme at vi ikke vil kode en Java-klasse som bare skal brukes i ett spørsmål.

Og dermed, Sql2o tillater også en lavere nivå, dynamisk kartlegging av datastrukturer i tabeller. Vi får tilgang til det ved hjelp av executeAndFetchTable metode:

Query query = connection.createQuery ("select * from project order by id"); Tabell tabell = query.executeAndFetchTable ();

Deretter kan vi trekke ut en liste over kart:

Liste liste = table.asList (); assertEquals ("tutorials", list.get (0) .get ("name"));

Alternativt kan vi kartlegge dataene på en liste over Rad objekter, som er kartlegginger fra kolonnenavn til verdier, i likhet med ResultatSetts:

Liste rader = table.rows (); assertEquals ("tutorials", rows.get (0) .getString ("name"));

6. Bindende spørringsparametere

Mange SQL-spørsmål har en fast struktur med noen få parametrerte deler. Vi kan naivt skrive de delvis dynamiske spørringene med streng sammenkobling.

Imidlertid tillater Sql2o parametrerte spørsmål, slik at:

  • Vi unngår SQL-injeksjonsangrep
  • Vi lar databasen cache ofte brukte spørsmål og få ytelse
  • Til slutt er vi spart fra behovet for å kode komplekse typer som datoer og klokkeslett

Så vi kan bruke navngitte parametere med Sql2o for å oppnå alle de ovennevnte. Vi introduserer parametere med et kolon, og vi binder dem med addParameter metode:

Query query = connection.createQuery ("sett inn i prosjekt (navn, url) verdier (: navn,: url)") .addParameter ("navn", "REST med vår") .addParameter ("url", "github.com / eugenp / REST-With-Spring "); assertEquals (1, query.executeUpdate (). getResult ());

6.1. Binding fra en POJO

SQL2O tilbyr en alternativ måte å binde parametere: det vil si ved å bruke POJO som kilde. Denne teknikken er spesielt egnet når et spørsmål har mange parametere og de refererer til samme enhet. Så la oss introdusere de binde metode:

Prosjektprosjekt = nytt prosjekt (); project.setName ("HVIL med våren"); project.setUrl ("github.com/eugenp/REST-With-Spring"); connection.createQuery ("sett inn i prosjekt (navn, url) verdier (: navn,: url)") .bind (prosjekt) .executeUpdate (); assertEquals (1, connection.getResult ());

7. Transaksjoner og batch-spørsmål

Med en transaksjon kan vi utstede flere SQL-setninger som en enkelt atomoperasjon. Det vil si at enten det lykkes, eller at det mislykkes i bulk, uten mellomliggende resultater. Faktisk er transaksjoner en av nøkkelfunksjonene i relasjonsdatabaser.

For å åpne en transaksjon bruker vi begin Transaksjon metoden i stedet for åpen metoden som vi har brukt så langt:

prøv (Connection connection = sql2o.beginTransaction ()) {// her er transaksjonen aktiv}

Når henrettelse forlater blokken, SQL2o ruller automatisk tilbake transaksjonen hvis den fremdeles er aktiv.

7.1. Manuell forpliktelse og tilbakeføring

Derimot, Vi kan eksplisitt begå eller tilbakebetale transaksjonen med de riktige metodene:

prøv (Connection connection = sql2o.beginTransaction ()) {boolean transactionSuccessful = false; // utføre noen operasjoner hvis (transactionSuccessful) {connection.commit (); } annet {connection.rollback (); }}

Noter det både begå og tilbakeføring avslutte transaksjonen. Etterfølgende uttalelser vil kjøre uten en transaksjon, og dermed blir de ikke automatisk rullet tilbake på slutten av blokken.

Vi kan imidlertid begå eller tilbakebetale transaksjonen uten å avslutte den:

prøv (Connection connection = sql2o.beginTransaction ()) {List list = connection.createQuery ("select * from project") .executeAndFetchTable () .asList (); assertEquals (0, list.size ()); // sette inn eller oppdatere en datatilkobling. rollback (false); // utfør andre innsettings- eller oppdateringsspørsmål} ​​// implisitt tilbakestillingsforsøk (Connection connection = sql2o.beginTransaction ()) {List list = connection.createQuery ("select * from project") .executeAndFetchTable () .asList (); assertEquals (0, list.size ()); }

7.2. Batchoperasjoner

Når vi trenger det gi den samme uttalelsen mange ganger med forskjellige parametere, å kjøre dem i en serie gir en stor ytelsesfordel.

Heldigvis, ved å kombinere to av teknikkene vi har beskrevet så langt - parametrerte spørsmål og transaksjoner - er det enkelt å kjøre dem i batch:

  • Først oppretter vi spørringen bare en gang
  • Deretter binder vi parametrene og ringer addToBatch for hver forekomst av spørringen
  • Til slutt ringer vi executeBatch:
prøv (Connection connection = sql2o.beginTransaction ()) {Query query = connection.createQuery ("insert into project (name, url)" + "values ​​(: name,: url)"); for (int i = 0; i <1000; i ++) {query.addParameter ("name", "tutorials" + i); query.addParameter ("url", "//github.com/eugenp/tutorials" + i); query.addToBatch (); } spørring.executeBatch (); connection.commit (); } prøv (Connection connection = sql2o.beginTransaction ()) {assertEquals (1000L, connection.createQuery ("select count (*) from project"). executeScalar ()); }

7.3. Lazy Fetch

Omvendt, når et enkelt spørsmål returnerer et stort antall resultater, er det tungt for minne om å konvertere dem alle og lagre dem i en liste.

Så, Sql2o støtter en lat modus, der rader returneres og kartlegges en om gangen:

Query query = connection.createQuery ("velg * fra prosjekt"); prøv (ResultSetIterable projects = query.executeAndFetchLazy (Project.class)) {for (Project p: projects) {// gjør noe med prosjektet}}

Noter det ResultSetIterable er Kan lukkes automatisk og er ment å brukes med prøv-med-ressurser for å lukke det underliggende ResultatSett når ferdig.

8. Konklusjoner

I denne veiledningen har vi presentert en oversikt over Sql2o-biblioteket og dets vanligste bruksmønstre. Mer informasjon finner du i Sql20 wiki på GitHub.

Implementeringen av alle disse eksemplene og kodebitene finner du også i GitHub-prosjektet, som 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