Vodič za sql2o JDBC omot

1. Uvod

U ovom uputstvu ćemo pogledati Sql2o, malu i brzu knjižnicu za pristup relacijskim bazama podataka u idiomatskoj Javi.

Vrijedno je spomenuti da, iako Sql2o radi mapiranjem rezultata upita u POJO-ove (obični stari Java objekti), nije cjelovito ORM rješenje kao što je Hibernate.

2. Postavljanje Sql2o

Sql2o je jedna jar datoteka koju možemo lako dodati u ovisnosti našeg projekta:

 org.sql2o sql2o 1.6.0 

U našim ćemo primjerima koristiti i ugrađenu bazu podataka HSQL; kako bismo nastavili dalje, možemo ga uključiti i:

 org.hsqldb hsqldb 2.4.0 test 

Maven Central domaćin je najnovijoj verziji sql2o i HSQLDB.

3. Povezivanje s bazom podataka

Da bismo uspostavili vezu, polazimo od instance Sql2o razred:

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

Ovdje navodimo URL veze, korisničko ime i lozinku kao parametre konstruktora.

The Sql2o objekt je zaštićen niti i možemo ga podijeliti u aplikaciji.

3.1. Korištenje a Izvor podataka

U većini aplikacija željet ćemo koristiti a Izvor podatakaumjesto sirovog DriverManager veze, možda da se iskoristi spremište veza ili da se navedu dodatni parametri veze. Ne brinite, Sql2o nas je pokrio:

Sql2o sql2o = novi Sql2o (izvor podataka);

3.2. Rad s vezama

Samo instanciranje a Sql2o objekt ne uspostavlja nikakvu vezu s bazom podataka.

Umjesto toga, koristimo otvorena metoda za dobivanje a Veza objekt (imajte na umu da to nije JDBC Veza). Od Veza je Automatski se zatvara, možemo ga umotati u blok try-with-resources:

probajte (Veza veze = sql2o.open ()) {// koristi vezu}

4. Umetanje i ažuriranje izjava

Ajmo sada stvoriti bazu podataka i u nju staviti neke podatke. Kroz tutorial koristit ćemo jednostavnu tablicu koja se zove projekt:

connection.createQuery ("izradi projekt tablice" + "(identitet cjelobrojnog ID-a, ime varchar (50), url varchar (100))"). executeUpdate ();

executeUpdate vraća Veza objekt tako da možemo povezati više poziva. Zatim, ako želimo znati broj zahvaćenih redaka, koristimo getResult:

assertEquals (0, connection.getResult ());

Primijenit ćemo uzorak koji smo upravo vidjeli - createQuery i executeUpdate -za sve DDL, INSERT i UPDATE izjave.

4.1. Dobivanje generiranih ključnih vrijednosti

U nekim slučajevima, možda bismo htjeli vratiti generirane vrijednosti ključeva. To su vrijednosti stupaca ključeva koji se automatski izračunavaju (kao kada se koristi automatsko povećanje u određenim bazama podataka).

To radimo u dva koraka. Prvo, s dodatnim parametrom za createQuery:

Upit upita = connection.createQuery ("umetni u projekt (ime, url)" + "vrijednosti ('tutoriali', 'github.com/eugenp/tutorials')", true);

Zatim, prizivanje getKey na vezi:

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

Ako je tipki više od jedne, koristimo getKeys umjesto toga, koji vraća niz:

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

5. Izdvajanje podataka iz baze podataka

Krenimo sada u srž stvari: ODABERI upite i mapiranje skupova rezultata na Java objekte.

Prvo, moramo definirati POJO klasu sa getterima i setterima koji će predstavljati tablicu naših projekata:

projekt javne klase {long id; privatni naziv niza; private String url; // Standardni getteri i postavljači}

Zatim ćemo, kao i prije, napisati svoj upit:

Upit upita = connection.createQuery ("odaberi * iz redoslijeda projekta prema id-u");

Međutim, ovaj put koristit ćemo novu metodu, executeAndFetch:

Lista popisa = query.executeAndFetch (Project.class);

Kao što vidimo, metoda uzima klasu rezultata kao parametar, na koji će Sql2o preslikati retke sirovog skupa rezultata koji dolaze iz baze podataka.

5.1. Mapiranje stupaca

Sql2o preslikava stupce u JavaBean svojstva po imenu, bez velikih i malih slova.

Međutim, konvencije imenovanja razlikuju se između Java i relacijskih baza podataka. Pretpostavimo da našim projektima dodamo svojstvo datuma izrade:

projekt javne klase {long id; privatni naziv niza; private String url; privatni Datum kreiranjaDat; // Standardni getteri i postavljači}

U shemi baze podataka, najvjerojatnije ćemo nazvati isto svojstvo Datum stvaranja.

Naravno, možemo ga nadimati u našim upitima:

Upit upita = connection.createQuery ("odaberi ime, url, datum_kretanja kao Datum stvaranja iz projekta");

Međutim, zamorno je i gubimo mogućnost korištenja Odaberi *.

Druga je mogućnost uputiti Sql2o na mapiranje Datum stvaranja do Datum stvaranja. Odnosno, upitu o mapiranju možemo reći:

connection.createQuery ("select * from project") .addColumnMapping ("datum_stvaranja", "Datum kreiranja");

Ovo je lijepo ako koristimo Datum stvaranja štedljivo, u pregršt upita; međutim, kada se intenzivno koristi u većem projektu, postaje dosadno i podložno pogreškama ponavljati istu činjenicu uvijek iznova.

Srećom, možemo i mi navedite preslikavanja globalno:

Mapiranja karte = novi HashMap (); mappings.put ("CREATION_DATE", "createDate"); sql2o.setDefaultColumnMappings (preslikavanja);

Naravno, to će uzrokovati svaki slučaj Datum stvaranja biti mapiran Datum stvaranja, pa je to još jedan razlog za nastojanje da imena budu konzistentna u svim definicijama naših podataka.

5.2. Skalarni rezultati

Ponekad iz upita želimo izdvojiti jedan skalarni rezultat. Na primjer, kada trebamo prebrojati broj zapisa.

U tim je slučajevima definiranje klase i ponavljanje popisa za koji znamo da sadrži jedan element pretjerano. Tako, Sql2o uključuje executeScalar metoda:

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

Ovdje određujemo vrstu povrata Cijeli broj. Međutim, to nije obavezno i ​​možemo dopustiti osnovnom upravljačkom programu JDBC da odluči.

5.3. Složeni rezultati

Umjesto toga, složeni upiti (na primjer za izvještavanje) možda se neće lako preslikati na Java objekt. Mogli bismo također odlučiti da ne želimo kodirati Java klasu koja će se koristiti samo u jednom upitu.

Tako, Sql2o također omogućuje dinamičko mapiranje niže razine u tablične strukture podataka. Pristupamo tome koristeći executeAndFetchTable metoda:

Upit upita = connection.createQuery ("odaberi * iz redoslijeda projekta prema id-u"); Tablica tablice = query.executeAndFetchTable ();

Zatim možemo izvući popis karata:

Popis list = table.asList (); assertEquals ("tutoriali", list.get (0) .get ("name"));

Alternativno, možemo mapirati podatke na popis Red objekti, koji su preslikavanja imena stupaca u vrijednosti, slično Postavi rezultats:

Redovi popisa = table.rows (); assertEquals ("tutoriali", redovi.get (0) .getString ("name"));

6. Vezani parametri upita

Mnogi SQL upiti imaju fiksnu strukturu s nekoliko parametriziranih dijelova. Mogli bismo naivno pisati one djelomično dinamične upite s spajanjem nizova.

Međutim, Sql2o dopušta parametrizirane upite, tako da:

  • Izbjegavamo napade SQL ubrizgavanja
  • Dopuštamo bazi podataka da predmemorira često korištene upite i poboljšava performanse
  • Napokon, pošteđeni smo potrebe kodiranja složenih vrsta poput datuma i vremena

Dakle, možemo koristiti imenovane parametre sa Sql2o kako bismo postigli sve gore navedeno. Parametre uvodimo s dvotačkom i vežemo ih s addParameter metoda:

Query query = connection.createQuery ("umetni u vrijednosti projekta (ime, url) ((ime,: url)") .addParameter ("name", "REST with Spring") .addParameter ("url", "github.com / eugenp / REST-With-Spring "); assertEquals (1, query.executeUpdate (). getResult ());

6.1. Vezanje iz POJO-a

Sql2o nudi alternativni način vezivanja parametara: to jest, korištenjem POJO-a kao izvor. Ova je tehnika posebno prikladna kada upit ima mnogo parametara i svi se odnose na isti entitet. Pa, predstavimo the vezati metoda:

Projektni projekt = novi projekt (); project.setName ("ODMOR s proljećem"); project.setUrl ("github.com/eugenp/REST-With-Spring"); connection.createQuery ("umetanje u vrijednosti projekta (ime, url) (: ime,: url)") .bind (projekt) .executeUpdate (); assertEquals (1, connection.getResult ());

7. Transakcije i skupni upiti

Transakcijom možemo izdati više SQL izraza kao jednu operaciju koja je atomska. Odnosno, ili uspije ili ne uspije u velikom broju, bez posrednih rezultata. Zapravo, transakcije su jedno od ključnih obilježja relacijskih baza podataka.

Da bismo otvorili transakciju, koristimo startTransaction metoda umjesto otvorena metoda koju smo do sada koristili:

try (Connection connection = sql2o.beginTransaction ()) {// ovdje je transakcija aktivna}

Kada izvršenje napusti blok, Sql2o automatski vraća transakciju ako je još uvijek aktivan.

7.1. Ručno predavanje i vraćanje

Međutim, možemo izričito izvršiti ili vratiti transakciju odgovarajućim metodama:

try (Connection connection = sql2o.beginTransaction ()) {booleanactionSuccessful = false; // izvršiti neke operacije if (transactionSuccessful) {connection.commit (); } else {connection.rollback (); }}

Imajte na umu da oba počiniti i vraćanje završiti transakciju. Naredni izvodi izvršavat će se bez transakcije, pa se neće automatski vraćati natrag na kraju bloka.

Međutim, transakciju možemo izvršiti ili vratiti, a da je ne završimo:

probajte (Connection connection = sql2o.beginTransaction ()) {List list = connection.createQuery ("select * from project") .executeAndFetchTable () .asList (); assertEquals (0, list.size ()); // umetanje ili ažuriranje neke podatkovne veze.rollback (false); // izvodimo neke druge upite za umetanje ili ažuriranje} // implicitni pokušaj vraćanja (Connection connection = sql2o.beginTransaction ()) {List list = connection.createQuery ("select * from project") .executeAndFetchTable () .asList (); assertEquals (0, list.size ()); }

7.2. Serijski rad

Kad trebamo izdati istu izjavu više puta s različitim parametrima, njihovo pokretanje u paketu pruža veliku prednost performansi.

Srećom, kombinirajući dvije tehnike koje smo do sada opisali - parametrizirane upite i transakcije - dovoljno je jednostavno pokrenuti ih u paketu:

  • Prvo, upit kreiramo samo jednom
  • Zatim, vežemo parametre i pozivamo addToBatch za svaku instancu upita
  • Napokon, zovemo executeBatch:
try (Connection connection = sql2o.beginTransaction ()) {Query query = connection.createQuery ("umetni u projekt (ime, url)" + "vrijednosti (: ime,: url)"); for (int i = 0; i <1000; i ++) {query.addParameter ("name", "tutorials" + i); query.addParameter ("url", "//github.com/eugenp/tutorials" + i); query.addToBatch (); } query.executeBatch (); veza.commit (); } isprobajte (Connection connection = sql2o.beginTransaction ()) {assertEquals (1000L, connection.createQuery ("select count (*) from project"). executeScalar ()); }

7.3. Lijeni dohvat

Obrnuto, kada jedan upit vrati velik broj rezultata, pretvaranje svih i spremanje na popis otežano pamti.

Dakle, Sql2o podržava lijeni način rada, gdje se retci vraćaju i mapiraju jedan po jedan:

Upit upita = connection.createQuery ("odaberi * iz projekta"); probajte (ResultSetIterable projects = query.executeAndFetchLazy (Project.class)) {for (Project p: projects) {// napravite nešto s projektom}}

Imajte na umu da RezultatSetIterable je AutoCloseable i namijenjen je korištenju s pokušajte s resursima zatvoriti temeljnu Postavi rezultat kad završi.

8. Zaključci

U ovom smo priručniku predstavili pregled knjižnice Sql2o i najčešće uzorake korištenja. Daljnje informacije mogu se naći u wiki Sql20 na GitHubu.

Također, implementacija svih ovih primjera i isječaka koda može se naći u projektu GitHub, a to je Maven projekt, pa bi ga trebalo lako uvesti i pokrenuti kakav jest.