6. díl - Databázový wrapper v Javě - Tvorba třídy Query

Java Databáze Databázový wrapper v Javě - Tvorba třídy Query

V minulém dílu seriálu tutoriálů o databázích v Javě jsme započali tvorbu databázového wrapperu, který nám zjednoduší práci s databází. Dnešní díl bude hlavně o programování. Ještě než začneme programovat samotnou třídu Database, tak si připravíme třídu Query, která bude znázorňovat samotný SQL dotaz.

Třída Query

V balíčku DB si vytvoříme novou třídu Query. V ní budeme pomocí metod postupně sestavovat SQL dotaz. Po tomto kroku bude náš projekt vypadat asi takto:

Diagram JDBC wrapperu v Javě

Ve třídě si vytvoříme metodu delete a metodu where, kterou budeme používat velmi často.

public class Query {
    private StringBuilder query;

    /**
     *
     * @param table
     * @return
     */
    public Query delete(String table){
        query = new StringBuilder();
        query.append("DELETE FROM ");
        query.append(table);
        return this;
    }

    /**
     * Přidá podmínku do sql dotazu
     * @param requirement
     * @return
     */
    public Query where(String requirement){
        query.append(" WHERE ");
        query.append(requirement);
        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 jednoduše přidá část textu, znak, nebo proměnou do pole. 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 přeměnit na textový řetězec za pomoci 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 {
        //proměnné třídy
        //metody třídy
    /**
     *
     * @param table
     * @return
     */
    public Query update(String table){
        query = new StringBuilder();
        query.append("UPDATE ");
        query.append(table);
        query.append(" SET ");
        return this;
    }

    /**
     * Doplní sloupce
     * @param 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;
    }
}

Tak a 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-li neposíláme prázdný parametr. V případě, že pošleme neplatný parametr, tak se vyvolá výjimka IllegalArgumen­tException. Nakonec jen zmíním, ž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 {
        //proměnné třídy
        //metody třídy
    /**
     *
     * @param table
     * @return
     */
    public Query insert(String table){
        query = new StringBuilder();
        query.append("INSERT INTO ");
        query.append(table);
        return this;
    }

    /**
     *
     * @param params
     * @return
     */
    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("?,");
        }
        //odstaníme poslední čárku
        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 IllegalArgumen­tException.

Metoda select a pomocné metody

public class Query {
        //proměnné třídy
        //metody třídy
    /**
     *
     * @param columns
     * @return
     */
    public Query select(Object[] columns){
        query = new StringBuilder();
        query.append("SELECT ");
        if(columns != null){
            for(Object column : columns){
                query.append(column);
                query.append(",");
            }
            //odstaníme poslední otazník
            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

public class Query {
        //proměnné třídy
        //metody třídy
     /**
     * Vrátí sestavený sql dotaz
     * @return query
     */
    public String getQuery(){
        return query.toString();
    }
}

Nakonec budeme potřebovat výsledný SQL dotaz nějak získat. K tomuto účelu nám poslouží metoda getQuery, která nám vrací dotaz jako textový řetězec za pomocí metody toString.

V dalším díle si třídu Query otestujeme a vytvoříme si třídu Database.


 

  Aktivity (1)

Článek pro vás napsal Milan Gallas
Avatar
Autor se věnuje programování, hardwaru a počítačovým sítím.

Jak se ti líbí článek?
Celkem (2 hlasů) :
55555


 



 

 

Komentáře

Avatar
Jan Vargovský
Redaktor
Avatar
Jan Vargovský:

Pěkný, ještě že my v .NETu už máme LINQ :P

 
Odpovědět 27.5.2014 19:23
Avatar
Matěj Kripner
Redaktor
Avatar
Odpovědět 3.6.2014 7:37
"We reject kings, presidents and voting. We believe in rough consensus and running code" David Clark
Avatar
Marek Šimon
Člen
Avatar
Marek Šimon:

Hoj, chcem sa spýtať, že prečo nie je vytvorený objekt StringBuilderu už priamo v deklaracií atributu query a miesto toho je vytváraný vždy v základe nejakého SQL dotazu (DELETE, INSERT, UPDATE,..)?

 
Odpovědět 19. července 12:54
Avatar
David Oczka
Redaktor
Avatar
Odpovídá na Marek Šimon
David Oczka:

No, jestli jsem se správně díval, tak StringBuilder v Javě nemá metodu Clear() (oproti C#), jen nějaké metody delete, kde je třeba zadávat indexy, takže asi autor vidí jako jednodušší vyčistit ho novou instancí...

Nicméně, přijde mi, že nekteré metody nejsou ošetřené vůči stavům, kdy je proměnná query ještě neinicializovaná... Např. metoda getQuery(), co bude navráceno ve chvíli, kdy programátor vytvoří pouze čistou instanci Query a zavolá metodu getQuery()? Ano, jsou to nepravděpodobné scénáře, ale asi by ošetřeny být měly...

Každopádně tazatel to podle mě vidí správně, asi bych taky inicializoval ten StringBuilder už při deklaraci a případně ho vyčistil metodou delete nebo nahradil novou instancí...

Pokud se ovšem pletu, tak mě prosím někdo opravte, děkuji...

 
Odpovědět 19. července 13:19
Avatar
Milan Gallas
Redaktor
Avatar
Odpovídá na David Oczka
Milan Gallas:

Ahoj zavolání samotné metody getQuery by sice nemělo nastat, ale je pravda, že by to mělo být zabezpečené. Od příštího týdne, budu mít více času, tak zkusím článek aktualizovat. Co se týče toho StringBuilderu, tak jsem našel, že se na to dá využít metoda setLength(0).

Takže by to mohlo vypadat takto:

query.setLength(0);

Nemám to ale testované.

 
Odpovědět 20. července 23:36
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 5 zpráv z 5.