Sprievodca Apache Commons DbUtils

1. Prehľad

Apache Commons DbUtils je malá knižnica, ktorá výrazne uľahčuje prácu s JDBC.

V tomto článku implementujeme príklady na predstavenie jeho funkcií a schopností.

2. Inštalácia

2.1. Maven závislosti

Najprv musíme pridať Commons-dbutils a h2 závislosti na naše pom.xml:

 commons-dbutils commons-dbutils 1,6 com.h2database h2 1.4.196 

Najnovšiu verziu commons-dbutils a h2 nájdete na serveri Maven Central.

2.2. Testovacia databáza

Po vytvorení závislostí vytvorme skript na vytvorenie tabuliek a záznamov, ktoré použijeme:

CREATE TABLE employee (id int NOT NULL PRIMARY KEY auto_increment, meno varchar (255), priezvisko varchar (255), plat dvojnásobok, hireddate dátum,); CREATE TABLE email (id int NIE NULL PRIMARY KEY auto_increment, id zamestnanca int, adresa varchar (255)); INSERT INTO employee (meno, priezvisko, plat, hireddate) HODNOTY ('John', 'Doe', 10000.10, to_date ('01 -01-2001 ',' dd-mm-rrrr ')); // ... INSERT INTO email (employeeid, address) VALUES (1, '[email protected]'); // ...

Všetky príklady testovacích prípadov v tomto článku budú používať novovytvorené pripojenie k databáze H2 v pamäti:

public class DbUtilsUnitTest {súkromné ​​pripojenie; @ Pred public void setupDB () vyvolá výnimku {Class.forName ("org.h2.Driver"); Reťazec db = "jdbc: h2: mem:; INIT = spustený skript z 'classpath: /employees.sql'"; connection = DriverManager.getConnection (db); } @After public void closeBD () {DbUtils.closeQuietly (pripojenie); } // ...}

2.3. POJO

Nakoniec budeme potrebovať dve jednoduché triedy:

public class Employee {private Integer id; private String meno; private String priezvisko; dvojitý súkromný plat; súkromné ​​Dátum najatéhoDátum; // štandardné konštruktory, getre a setre} verejná trieda Email {private Integer id; private Integer employeeId; súkromná adresa reťazca; // štandardné konštruktory, getre a setre}

3. Úvod

Knižnica DbUtils poskytuje the QueryRunner triedy ako hlavný vstupný bod pre väčšinu dostupných funkcií.

Táto trieda funguje tak, že prijíma pripojenie k databáze, má byť vykonaný príkaz SQL a voliteľný zoznam parametrov na dodanie hodnôt pre zástupné symboly dotazu.

Ako uvidíme neskôr, niekoľko metód tiež získa a ResultSetHandler implementácia - ktorá je zodpovedná za transformáciu Sada výsledkov inštancie do objektov, ktoré naša aplikácia očakáva.

Knižnica samozrejme už poskytuje niekoľko implementácií, ktoré zvládajú najbežnejšie transformácie, ako sú zoznamy, mapy a JavaBeans.

4. Dotazovanie údajov

Teraz, keď poznáme základné informácie, sme pripravení vyhľadávať v našej databáze.

Začnime rýchlym príkladom získania všetkých záznamov v databáze ako zoznamu máp pomocou a MapListHandler:

@Test public void givenResultHandler_whenExecutingQuery_thenExectedList () hodí SQLException {MapListHandler beanListHandler = nový MapListHandler (); Bežec QueryRunner = nový QueryRunner (); Zoznam list = runner.query (pripojenie, "SELECT * OD zamestnanca", beanListHandler); assertEquals (list.size (), 5); assertEquals (list.get (0) .get ("meno"), "John"); assertEquals (list.get (4) .get ("meno"), "Christian"); }

Ďalej je uvedený príklad použitia a BeanListHandler transformovať výsledky do Zamestnanec prípady:

@Test public void givenResultHandler_whenExecutingQuery_thenEmployeeList () hodí SQLException {BeanListHandler beanListHandler = nový BeanListHandler (Employee.class); Bežec QueryRunner = nový QueryRunner (); Zoznam employeeList = runner.query (pripojenie, "SELECT * FROM employee", beanListHandler); assertEquals (employeeList.size (), 5); assertEquals (employeeList.get (0) .getFirstName (), "John"); assertEquals (employeeList.get (4) .getFirstName (), "Christian"); }

Pre dotazy, ktoré vracajú jednu hodnotu, môžeme použiť a ScalarHandler:

@Test public void givenResultHandler_whenExecutingQuery_thenExpectedScalar () hodí SQLException {ScalarHandler scalarHandler = nový ScalarHandler (); Bežec QueryRunner = nový QueryRunner (); Reťazcový dotaz = "VYBERTE POČET (*) OD zamestnanca"; long count = runner.query (connection, query, scalarHandler); assertEquals (count, 5); }

Naučiť sa všetko ResultSerHandler implementácie, môžete sa obrátiť na ResultSetHandler dokumentácia.

4.1. Vlastné manipulátory

Môžeme tiež vytvoriť vlastný obslužný program, ktorý sa má odovzdať QueryRunnerMetódy, keď potrebujeme väčšiu kontrolu nad tým, ako sa výsledky transformujú do objektov.

To je možné vykonať implementáciou ResultSetHandler rozhranie alebo rozšírenie jednej z existujúcich implementácií poskytovaných knižnicou.

Pozrime sa, ako vyzerá druhý prístup. Najskôr do nášho poľa pridáme ďalšie Zamestnanec trieda:

public class Employee {private List emails; // ...}

Poďme teraz vytvoriť triedu, ktorá rozširuje BeanListHandler zadajte a nastavíte zoznam e-mailov pre každého zamestnanca:

verejná trieda EmployeeHandler rozširuje BeanListHandler {súkromné ​​pripojenie; public EmployeeHandler (Connection con) {super (Employee.class); this.connection = con; } @Override obsluha verejného zoznamu (ResultSet rs) hodí SQLException {Zoznam zamestnancov = super.handle (rs); Bežec QueryRunner = nový QueryRunner (); BeanListHandler handler = nový BeanListHandler (Email.class); Reťazec query = "SELECT * FROM email WHERE employeeid =?"; pre (Zamestnanec zamestnanec: zamestnanci) {Zoznam e-mailov = runner.query (pripojenie, dopyt, obsluha, employee.getId ()); employee.setEmails (e-maily); } vrátiť zamestnancov; }}

Všimnite si, že očakávame a Pripojenie objekt v konštruktore, aby sme mohli vykonať dotazy na získanie e-mailov.

Nakoniec otestujme náš kód a zistíme, či všetko funguje podľa očakávaní:

@Test public void givenResultHandler_whenExecutingQuery_thenEmailsSetted () hodí SQLException {EmployeeHandler employeeHandler = nový EmployeeHandler (pripojenie); Bežec QueryRunner = nový QueryRunner (); Zoznam zamestnancov = runner.query (pripojenie, "VYBERTE * OD zamestnanca", employeeHandler); assertEquals (zamestnanci.get (0) .getEmails (). veľkosť (), 2); assertEquals (zamestnanci.get (2) .getEmails (). veľkosť (), 3); }

4.2. Vlastné riadkové procesory

V našich príkladoch sú názvy stĺpcov zamestnanec tabuľka sa zhoduje s názvami polí nášho Zamestnanec trieda (pri párovaní sa nerozlišujú malé a veľké písmená). To však neplatí vždy - napríklad keď názvy stĺpcov používajú na oddelenie zložených slov znaky podčiarknutia.

V týchto situáciách môžeme využiť výhody RowProcessor rozhranie a jeho implementácie na mapovanie názvov stĺpcov do príslušných polí v našich triedach.

Pozrime sa, ako to vyzerá. Najskôr vytvoríme ďalšiu tabuľku a vložíme do nej niekoľko záznamov:

CREATE TABLE employee_legacy (id int NOT NULL PRIMARY KEY auto_increment, first_name varchar (255), last_name varchar (255), plat double, hired_date date,); INSERT INTO employee_legacy (first_name, last_name, plate, hired_date) VALUES ('John', 'Doe', 10 000.10, to_date ('01 -01-2001 ',' dd-mm-rrrr ')); // ...

Teraz poďme upraviť naše EmployeeHandler trieda:

public class EmployeeHandler extends BeanListHandler {// ... public EmployeeHandler (Connection con) {super (Employee.class, new BasicRowProcessor (new BeanProcessor (getColumnsToFieldsMap ()))); // ...} public static Map getColumnsToFieldsMap () {Map columnsToFieldsMap = new HashMap (); columnsToFieldsMap.put ("FIRST_NAME", "meno"); columnsToFieldsMap.put ("LAST_NAME", "priezvisko"); columnsToFieldsMap.put ("HIRED_DATE", "hiredDate"); vrátiť stĺpceToFieldsMap; } // ...}

Všimnite si, že používame a BeanProcessor skutočné mapovanie stĺpcov do polí a to iba pre tie, ktoré je potrebné adresovať.

Nakoniec otestujme, že je všetko v poriadku:

@Test public void givenResultHandler_whenExecutingQuery_thenAllPropertiesSetted () hodí SQLException {EmployeeHandler employeeHandler = nový EmployeeHandler (pripojenie); Bežec QueryRunner = nový QueryRunner (); Reťazcový dopyt = "ZVOLIŤ * ZO zamestnanca_legacy"; Zoznam zamestnancov = runner.query (pripojenie, dotaz, employeeHandler); assertEquals ((int) zamestnanci.get (0) .getId (), 1); assertEquals (zamestnanci.get (0) .getFirstName (), "John"); }

5. Vkladanie záznamov

The QueryRunner trieda poskytuje dva prístupy k vytváraniu záznamov v databáze.

Prvým z nich je použitie aktualizácia () metóda a odovzdať príkaz SQL a voliteľný zoznam náhradných parametrov. Metóda vráti počet vložených záznamov:

@ Test public void whenInserting_thenInserted () hodí SQLException {QueryRunner runner = new QueryRunner (); Reťazec insertSQL = "VLOŽTE DO ZAMESTNANCA (meno, priezvisko, plat, dátum nájmu)" + "HODNOTY (?,?,?,?)"; int numRowsInserted = runner.update (pripojenie, insertSQL, "Leia", "Kane", 60000,60, nový dátum ()); assertEquals (numRowsInserted, 1); }

Druhým z nich je použitie vložiť () metóda, ktorá okrem príkazu SQL a náhradných parametrov potrebuje a ResultSetHandler transformovať výsledné automaticky generované kľúče. Návratová hodnota bude taká, akú vráti obslužná rutina:

@Test public void givenHandler_whenInserting_thenExectedId () hodí SQLException {ScalarHandler scalarHandler = nový ScalarHandler (); Bežec QueryRunner = nový QueryRunner (); Reťazec insertSQL = "INSERT INTO employee (meno, priezvisko, plat, hireddate)" + "HODNOTY (?,?,?,?)"; int newId = runner.insert (pripojenie, insertSQL, scalarHandler, "Jenny", "Medici", 60000,60, nový dátum ()); assertEquals (newId, 6); }

6. Aktualizácia a odstránenie

The aktualizácia () metóda QueryRunner triedy je možné použiť aj na úpravy a mazanie záznamov z našej databázy.

Jeho použitie je triviálne. Tu je príklad toho, ako aktualizovať plat zamestnanca:

@Test public void givenSalary_whenUpdating_thenUpdated () hodí SQLException {dvojnásobný plat = 35000; Bežec QueryRunner = nový QueryRunner (); Reťazec updateSQL = "AKTUALIZOVAŤ zamestnanca SET plat = plat * 1,1 KDE plat <=?"; int numRowsUpdated = runner.update (pripojenie, updateSQL, plat); assertEquals (numRowsUpdated, 3); }

A tu je ďalší na odstránenie zamestnanca s daným ID:

@ Test public void whenDeletingRecord_thenDeleted () hodí SQLException {QueryRunner runner = nový QueryRunner (); Reťazec deleteSQL = "ODSTRÁNIŤ OD zamestnanca WHERE id =?"; int numRowsDeleted = runner.update (pripojenie, deleteSQL, 3); assertEquals (numRowsDeleted, 1); }

7. Asynchrónne operácie

DbUtils poskytuje AsyncQueryRunner triedy na vykonávanie operácií asynchrónne. Metódy v tejto triede zodpovedajú metódam v QueryRunner triedy, ibaže sa vracajú a Budúcnosť inštancia.

Tu je príklad na získanie všetkých zamestnancov v databáze čakajúcich na získanie výsledkov až 10 sekúnd:

@Test public void givenAsyncRunner_whenExecutingQuery_thenExectedList () vyvolá výnimku {AsyncQueryRunner runner = nový AsyncQueryRunner (Executors.newCachedThreadPool ()); EmployeeHandler employeeHandler = nový EmployeeHandler (pripojenie); Reťazcový dotaz = "ZVOLIŤ * OD zamestnanca"; Budúcnosť future = runner.query (pripojenie, dotaz, employeeHandler); Zoznam zamestnancaList = future.get (10, TimeUnit.SECONDS); assertEquals (employeeList.size (), 5); }

8. Záver

V tomto tutoriáli sme preskúmali najvýznamnejšie funkcie knižnice Apache Commons DbUtils.

Dotazovali sme sa na údaje a transformovali ich na rôzne typy objektov, vložili sme záznamy získavajúce vygenerované primárne kľúče a aktualizované a vymazané údaje na základe daných kritérií. Využili sme tiež výhody AsyncQueryRunner triedy na asynchrónne vykonanie operácie dotazu.

Kompletný zdrojový kód tohto článku nájdete ako vždy na serveri Github.


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