Vodič za Apache Commons DbUtils

1. Pregled

Apache Commons DbUtils je mala knjižnica koja puno olakšava rad s JDBC-om.

U ovom ćemo članku implementirati primjere kako bismo prikazali njegove značajke i mogućnosti.

2. Postavljanje

2.1. Ovisnosti Mavena

Prvo, moramo dodati commons-dbutils i h2 ovisnosti o našim pom.xml:

 commons-dbutils commons-dbutils 1.6 com.h2database h2 1.4.196 

Najnoviju verziju commons-dbutils i h2 možete pronaći na Maven Central.

2.2. Baza podataka ispitivanja

S našim ovisnostima, stvorimo skriptu za izradu tablica i zapisa koje ćemo koristiti:

IZRADI TABELU zaposlenika (id int NIJE NULL PRIMARNI KLJUČ auto_increment, ime varchar (255), prezime varchar (255), plaća dvostruka, datum unajmljivanja,); IZRADI TABELU e-pošte (id int NIJE NULL PRIMARNI KLJUČ auto_increment, workerid int, adresa varchar (255)); INSERT INTO zaposlenika (ime, prezime, plaća, datum zaposlenja) VRIJEDNOSTI ('John', 'Doe', 10000.10, to_date ('01 -01-2001 ',' dd-mm-yyyy ')); // ... UMETNITE U E-mail (zaposlenik, adresa) VRIJEDNOSTI (1, '[e-mail zaštićen]'); // ...

Svi primjeri testnih slučajeva u ovom članku koristit će novostvorenu vezu s H2 bazom podataka u memoriji:

javna klasa DbUtilsUnitTest {veza privatne veze; @Prije javne void setupDB () baca iznimku {Class.forName ("org.h2.Driver"); Niz db = "jdbc: h2: mem:; INIT = runcript iz 'classpath: /employees.sql'"; veza = DriverManager.getConnection (db); } @Nakon javne praznine closeBD () {DbUtils.closeQuietly (veza); } // ...}

2.3. POJO

Napokon, trebat će nam dva jednostavna razreda:

zaposlenik u javnoj klasi {private Integer id; private String firstName; private String lastName; privatna Dvostruka plaća; privatno Datum najmaDatum; // standardni konstruktori, getteri i postavljači} e-pošta javne klase {private Integer id; privatni Integer zaposlenikId; privatna string adresa; // standardni konstruktori, getteri i postavljači}

3. Uvod

DbUtils knjižnica pruža the QueryRunner klasa kao glavna ulazna točka za većinu dostupnih funkcionalnosti.

Ova klasa djeluje tako što prima vezu s bazom podataka, SQL izraz koji treba izvršiti i neobavezni popis parametara koji daju vrijednosti za rezervirana mjesta upita.

Kao što ćemo vidjeti kasnije, nekoliko metoda također prima a ResultSetHandler implementacija - koja je odgovorna za preobrazbu Postavi rezultat instanci u objekte koje očekuje naša aplikacija.

Naravno, knjižnica već nudi nekoliko implementacija koje obrađuju najčešće transformacije, poput popisa, karata i JavaBeansa.

4. Upitivanje podataka

Sad kad znamo osnove, spremni smo postaviti upit našoj bazi podataka.

Počnimo s brzim primjerom dobivanja svih zapisa u bazi podataka kao popisa karata pomoću a MapListHandler:

@Test public void givenResultHandler_whenExecutingQuery_thenExpectedList () baca SQLException {MapListHandler beanListHandler = new MapListHandler (); Pokretač QueryRunner = novi QueryRunner (); Popis list = runner.query (veza, "SELECT * FROM zaposlenik", beanListHandler); assertEquals (list.size (), 5); assertEquals (list.get (0) .get ("firstname"), "John"); assertEquals (list.get (4) .get ("firstname"), "Christian"); }

Dalje, evo primjera korištenja a BeanListHandler za pretvaranje rezultata u Zaposlenik primjerci:

@Test javna praznina givenResultHandler_whenExecutingQuery_thenEfficieeList () baca SQLException {BeanListHandler beanListHandler = novi BeanListHandler (Employee.class); Pokretač QueryRunner = novi QueryRunner (); Popis workerList = runner.query (veza, "SELECT * FROM zaposlenik", beanListHandler); assertEquals (workerList.size (), 5); assertEquals (workerList.get (0) .getFirstName (), "John"); assertEquals (workerList.get (4) .getFirstName (), "Christian"); }

Za upite koji vraćaju jednu vrijednost možemo koristiti a ScalarHandler:

@Test javna praznina givenResultHandler_whenExecutingQuery_thenExpectedScalar () baca SQLException {ScalarHandler scalarHandler = novi ScalarHandler (); Pokretač QueryRunner = novi QueryRunner (); String query = "SELECT COUNT (*) FROM zaposlenika"; dugo brojanje = runner.query (veza, upit, skalarHandler); assertEquals (count, 5); }

Da naučim sve ResultSerHandler implementacije, možete se pozvati na ResultSetHandler dokumentacija.

4.1. Prilagođeni rukovatelji

Također možemo stvoriti prilagođeni rukovatelj kojem ćemo proslijediti QueryRunner'Metode kada trebamo veću kontrolu nad načinom na koji će se rezultati pretvoriti u objekte.

To se može učiniti primjenom ResultSetHandler sučelje ili proširenje jedne od postojećih implementacija koje pruža knjižnica.

Pogledajmo kako izgleda drugi pristup. Prvo, dodajmo još jedno polje u naš Zaposlenik razred:

zaposlenik u javnoj klasi {e-adrese s privatnog popisa; // ...}

Sada, kreirajmo klasu koja proširuje BeanListHandler upišite i postavite popis e-adresa za svakog zaposlenika:

javna klasa EmployeeHandler proširuje BeanListHandler {veza privatne veze; javni EmployeeHandler (Connection con) {super (Employee.class); this.connection = con; } @Override javni popis popisa (ResultSet rs) baca SQLException {Popis zaposlenika = super.handle (rs); Pokretač QueryRunner = novi QueryRunner (); Rukovatelj BeanListHandler = novi BeanListHandler (Email.class); String query = "SELECT * FROM email WHERE zaposlenik =?"; za (Zaposleni zaposlenik: zaposlenici) {Popis e-adresa = runner.query (veza, upit, rukovatelj, worker.getId ()); worker.setEmails (e-mailovi); } vratiti zaposlenike; }}

Obavijest da očekujemo Veza objekt u konstruktoru tako da možemo izvršiti upite za dobivanje e-pošte.

Na kraju, testirajmo naš kod da vidimo radi li sve prema očekivanjima:

@Test javna praznina givenResultHandler_whenExecutingQuery_thenEmailsSetted () baca SQLException {EmployeeHandler workerHandler = novi EmployeeHandler (veza); Pokretač QueryRunner = novi QueryRunner (); Popis zaposlenika = runner.query (veza, "SELECT * FROM zaposlenik", workerHandler); assertEquals (zaposlenici.get (0) .getEmails (). size (), 2); assertEquals (zaposlenici.get (2) .getEmails (). size (), 3); }

4.2. Prilagođeni procesori redaka

U našim primjerima nazivi stupaca zaposlenik Tablica odgovara nazivima polja našeg Zaposlenik klasa (podudaranje ne razlikuje velika i mala slova). Međutim, to nije uvijek slučaj - na primjer kada nazivi stupaca koriste podvlake za odvajanje složenih riječi.

U tim situacijama možemo iskoristiti Procesor redaka sučelje i njegove implementacije za mapiranje imena stupaca u odgovarajuća polja u našim razredima.

Da vidimo kako ovo izgleda. Prvo stvorimo drugu tablicu i u nju ubacimo neke zapise:

IZRADI TABELU_zastupništvo_zaposlenika (id int NIJE NULTA PRIMARNI KLJUČ auto_increment, first_name varchar (255), last_name varchar (255), plaća dvostruka, datum unajmljenog datuma,); INSERT INTO worker_legacy (ime, prezime, plaća, datum najma) VRIJEDNOSTI ('John', 'Doe', 10000.10, to_date ('01 -01-2001 ',' dd-mm-yyyy ')); // ...

Sada, izmijenimo naš Rukovodilac zaposlenika razred:

javna klasa EmployeeHandler proširuje BeanListHandler {// ... public EmployeeHandler (Connection con) {super (Employee.class, novi BasicRowProcessor (novi BeanProcessor (getColumnsToFieldsMap ()))); // ...} javna statička karta getColumnsToFieldsMap () {Stupci mapeToFieldsMap = novi HashMap (); columnsToFieldsMap.put ("FIRST_NAME", "firstName"); columnsToFieldsMap.put ("LAST_NAME", "lastName"); columnsToFieldsMap.put ("HIRED_DATE", "hiredDate"); vrati stupceToFieldsMap; } // ...}

Obavijest da koristimo a BeanProcessor izvršiti stvarno mapiranje stupaca u polja i samo za ona kojima treba obratiti pažnju.

Napokon, testirajmo da je sve u redu:

@Test javna praznina givenResultHandler_whenExecutingQuery_thenAllPropertiesSetted () baca SQLException {EmployeeHandler workerHandler = novi EmployeeHandler (veza); Pokretač QueryRunner = novi QueryRunner (); String query = "SELECT * FROM worker_legacy"; Popis zaposlenika = runner.query (veza, upit, workerHandler); assertEquals ((int) zaposlenici.get (0) .getId (), 1); assertEquals (zaposlenici.get (0) .getFirstName (), "John"); }

5. Umetanje zapisa

The QueryRunner klasa pruža dva pristupa stvaranju zapisa u bazi podataka.

Prva je uporaba ažuriranje() metodu i proslijedite SQL izraz i neobavezni popis zamjenskih parametara. Metoda vraća broj umetnutih zapisa:

@Test public void whenInserting_thenInserted () baca SQLException {QueryRunner runner = new QueryRunner (); String insertSQL = "INSERT INTO zaposlenika (ime, prezime, plaća, unajmljeni datum)" + "VRIJEDNOSTI (?,?,?,?)"; int numRowsInserted = runner.update (veza, insertSQL, "Leia", "Kane", 60000.60, novi datum ()); assertEquals (numRowsInserted, 1); }

Drugi je korištenje umetnuti() metoda koja, uz SQL izraz i zamjenske parametre, treba i ResultSetHandler za transformiranje rezultirajućih automatski generiranih ključeva. Povratna vrijednost bit će ono što rukovatelj vraća:

@Test javna praznina givenHandler_whenInserting_thenExpectedId () baca SQLException {ScalarHandler scalarHandler = novi ScalarHandler (); Pokretač QueryRunner = novi QueryRunner (); String insertSQL = "INSERT INTO zaposlenika (ime, prezime, plaća, unajmljeni datum)" + "VRIJEDNOSTI (?,?,?,?)"; int newId = runner.insert (veza, insertSQL, skalarHandler, "Jenny", "Medici", 60000.60, novi datum ()); assertEquals (newId, 6); }

6. Ažuriranje i brisanje

The ažuriranje() metoda QueryRunner klasa se također može koristiti za izmjenu i brisanje zapisa iz naše baze podataka.

Njegova je upotreba trivijalna. Evo primjera kako ažurirati plaću zaposlenika:

@Test javna praznina givenSalary_whenUpdating_thenUpdated () baca SQLException {dvostruka plaća = 35000; Pokretač QueryRunner = novi QueryRunner (); String updateSQL = "AŽURIRANJE SET zaposlenika SET plaća = plaća * 1.1 WHERE plaća <=?"; int numRowsUpdated = runner.update (veza, updateSQL, plaća); assertEquals (numRowsUpdated, 3); }

I evo još jednog za brisanje zaposlenika s danim ID-om:

@Test public void whenDeletingRecord_thenDeleted () baca SQLException {QueryRunner runner = new QueryRunner (); String deleteSQL = "IZBRIŠI OD zaposlenika GDJE id =?"; int numRowsDeleted = runner.update (veza, deleteSQL, 3); assertEquals (numRowsDeleted, 1); }

7. Asinkrone operacije

DbUtils nudi AsyncQueryRunner klasa za izvršavanje operacija asinkrono. Metode u ovoj klasi podudaraju se s metodama iz QueryRunner razreda, osim što vraćaju a Budućnost primjer.

Evo primjera za dobivanje svih zaposlenika u bazi podataka, koji čekaju i do 10 sekundi da bi dobili rezultate:

@Test javna praznina givenAsyncRunner_whenExecutingQuery_thenExpectedList () baca izuzetak {AsyncQueryRunner runner = new AsyncQueryRunner (Executors.newCachedThreadPool ()); EmployeeHandler workerHandler = novi EmployeeHandler (veza); String query = "SELECT * FROM zaposlenik"; Budućnost budućnost = runner.query (veza, upit, workerHandler); Popis workerList = future.get (10, TimeUnit.SECONDS); assertEquals (workerList.size (), 5); }

8. Zaključak

U ovom uputstvu istražili smo najznačajnije značajke biblioteke Apache Commons DbUtils.

Upitivali smo podatke i transformirali ih u različite tipove objekata, ubacivali zapise koji su dobivali generirane primarne ključeve i ažurirali i brisali podatke na temelju zadanih kriterija. Također smo iskoristili AsyncQueryRunner klase za asinkrono izvršavanje operacije upita.

I kao i uvijek do sada, cjeloviti izvorni kod za ovaj članak nalazi se na Githubu.


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