Lekce 6 - Databázový wrapper v Javě - Tvorba třídy Query
V minulém dílu, Programování databázového Wrapperu v Javě - Příprava, jsme započali tvorbu databázového wrapperu, který nám zjednoduší práci s databází.
Dnešní tutoriál bude hlavně o programování. Ještě než začneme
programovat samotnou třídu Database
, tak si připravíme kód
třídy Query
, která bude znázorňovat samotný SQL dotaz.
Třída Query
V balíčku DB
máme z dřívějška připravené prázdné
třídy Database
a Query
. Ve třídě
Query
budeme nyní pomocí metod postupně sestavovat SQL dotazy.
Celá struktura našeho projektu vypadá takto:

Metody pro vyhledávání a mazání
Ve třídě Query
si vytvoříme metodu delete()
a
metodu where()
, kterou budeme používat velmi často:
public class Query { private StringBuilder query; /** * @param table (Db table) * @return SQL query DELETE */ public Query delete(String table) { query = new StringBuilder(); query.append("DELETE FROM "); query.append(table); return this; } /** * Adds condition forSQL query * * @param requirement condition * @return SQL query WHERE */ public Query where(String requirement) { query.append(" WHERE "); query.append(requirement); return this; } /** * @param table (Db table) * @return SQL query FROM */ public Query from(String table) { query.append(" FROM "); query.append(table); return this; } }
Díky třídě StringBuilder
můžeme snadněji poskládat naše
SQL dotazy a uložit je do instanční proměnné query
. Metoda
append()
k ní jednoduše přidá část textu, znak, nebo
proměnou. Proměnná může být jakéhokoli datového typu
(Object
, String
, char
,
boolean
, double
, int
, float
,
atd.).
Instanci třídy StringBuilder
můžeme poté přeměnit na
textový řetězec pomocí metody toString()
.
Důležitá pro nás je metoda where()
, protože tu využijeme
nejčastěji.
Metody update()
a
set()
Podobně přidáme i metody update()
a set()
:
public class Query { // ... /** * @param table (Db table) * @return SQL query UPDATE */ public Query update(String table) { query = new StringBuilder(); query.append("UPDATE "); query.append(table); query.append(" SET "); return this; } /** * Fills Db columns into the query * * @param columns (array of Db columns) */ public Query set(String[] columns) { int count = columns.length; if (count == 0) { throw new IllegalArgumentException("Neplatný počet parametrů."); } for (String column : columns) { query.append(column); query.append(" = "); query.append("?"); query.append(","); } query.deleteCharAt(query.lastIndexOf(",")); return this; } }
Teď si řekneme, proč máme na konci každé metody
return this;
. Je to jednoduché. Každá metoda ve třídě
Query
je datového typu Query
. To znamená, že
vrací instancí dané třídy. Má to tu výhodu, že můžeme
zefektivnít kód. A místo takového kódu:
query.update(table); query.set(columns); query.where(requirement);
Můžeme efektivně napsat toto:
query.update(table).set(columns).where(requirement);
Takovému zápisu se říká plynulé rozhraní (Fluent Interface). Pomáhá nám to vytvářet aplikační rozhraní, které je velmi čitelné a pochopitelné. Plynulé rozhraní vytvořil Martin Fowler a je to technika objektové orientovaného programování, kde jak jsme si již výše ukázali, řetězíme po sobě jdoucí volání metod téhož objektu.
Dále stojí za povšimnutí, že v metodě set()
testujeme, zda
neposíláme prázdný parametr. V případě, že pošleme neplatný parametr,
tak se vyvolá výjimka IllegalArgumentException
. Nakonec jen
zmíníme, že metoda deleteCharAt()
nám odebere poslední
nežádoucí čárku, ale vnitřní logiku metod si i s příklady probereme v
jiné části tohoto tutoriálu.
Metody insert()
a
values()
Přidejme metody insert()
a values()
:
public class Query { // ... /** * @param table (Db table) * @return SQL query INSERT */ public Query insert(String table) { query = new StringBuilder(); query.append("INSERT INTO "); query.append(table); return this; } /** * @param params (array of VALUES) * @return VALUES for INSERT */ public Query values(Object[] params) { query.append(" VALUES("); int count = params.length; if (count == 0) { throw new IllegalArgumentException("Neplatný počet parametrů."); } for (int i = 0; i < count; i++) { query.append("?,"); } query.deleteCharAt(query.lastIndexOf(",")); query.append(");"); return this; } }
V metodě insert()
není nic nového. Metoda
values()
bere jako parametr pole objektů a za každý prvek
dosadí do SQL dotazu ?
. Nakonec se odstraní poslední čárka a
vrátí instance třídy Query
. Pokud bude počet parametrů roven
nule, vyvolá se výjimka IllegalArgumentException
.
Metoda select()
Do třídy doplníme také metodu select()
s tímto kódem:
public class Query { // ... /** * @param columns (array of Db columns) * @return SQL query SELECT */ public Query select(Object[] columns) { query = new StringBuilder(); query.append("SELECT "); if (columns != null) { for (Object column : columns) { query.append(column); query.append(","); } query.deleteCharAt(query.lastIndexOf(",")); } else { query.append("*"); } return this; } }
Metoda select()
bere jako parametr pole objektů, které
reprezentují jednotlivé sloupce. Pokud dáme metodě select()
jako parametr hodnotu null
, dosadí do SQL dotazu znak
*
, který vrací všechny sloupce z databázové tabulky.
Metoda getQuery()
Nakonec doplníme metodu, která nám vrátí daný SQL dotaz:
public class Query { // ... /** * * @return complete sql query */ public String getQuery() { return query.toString(); } }
V metodě getQuery()
jsme zavolali metodu
toString()
na instanci query
a vrátili předtím
sestavený dotaz jako textový řetězec. Pokračovat budeme příště
V dalším díle, Programování databázového Wrapperu v Javě - Třída Database, si třídu Query
otestujeme a
vytvoříme si třídu Database
.