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.
