14. díl - Diář s databází v Javě (dokončení)

Java Objektově orientované programování Diář s databází v Javě (dokončení)

V minulém dílu našeho seriálu tutoriálů o Javě jsme rozpracovali jednoduchý diář s databází pomocí ArrayListu. Dnes aplikaci dokončíme.

Do třídy Diar přidejme pomocnou metodu zjistiCalendar(), která vyzve uživatele k zadání data a času a vrátí instanci Calendar nastavenou na tuto hodnotu. Nejprve si metodu ukažme, záhy si ji popíšeme:

private Calendar zjistiCalendar(DateFormat formatData)
{
        Calendar datumCas = Calendar.getInstance();
        try
        {
                datumCas.setTime(formatData.parse(sc.nextLine()));
                // Používá se k vyvolání výjimky při nesprávném formátu
                datumCas.setLenient(false);
                datumCas.getTime();
        }
        catch (Exception e)
        {
                System.out.println("Nesprávně zadáno, zadejte prosím znovu");
                return zjistiCalendar(formatData);
        }
        return datumCas;
}

Metoda vrací instanci Calendar a v parametru bere formatter. Nejprve si získáme instanci kalendáře. V bloku try se ji pokusíme nastavit na hodnotu zadanou do konzole. SetLenient() se volá k tomu, aby se projevila případná chyba v zadání (např. 30. únor a podobně). Pokud něco takového uživatel zadal, chyba nenastane při parsování, ale až při čtení hodnoty, které vyvoláme zavoláním getTime(). Pokud šlo vše hladce, program nepřejde do bloku catch a vrátí daný datum a čas. Pokud se pokazilo parsování nebo následná kontrola správnosti, uživatele na to upozorníme a zadání provedeme znovu. Všimněte si, že metoda volá sebe sama pro nové zadání. Je to běžná programátorská praktika, které se říká rekurze. Tuto metodu si shovejte, bude se vám jistě hodit i do budoucích konzolových aplikací :)

Do třídy si přidejme 2 veřejné, statické proměnné. Budou to formattery data a času. Statické proto, aby byly použitelné i pro další třídy v naší aplikaci. Každá třída může používat tyto formattery, které máme definované na jednom místě.

public static DateFormat formatData = new SimpleDateFormat("d.MM.yyyy H:mm");
public static DateFormat formatDataBezCasu = new SimpleDateFormat("d.MM.yyyy");

Jeden formatter obsahuje datum i čas, jeden pouze datum bez času. Přejděme do třídy Zaznam.java a metodu toString() pozměňme takto:

@Override
public String toString()
{
        return Diar.formatData.format(datumCas.getTime()) + " " + text;
}

Kdybychom si dělali instanci formatteru znovu v každém záznamu, bylo by to nepraktické. Takto máme formattery na jednom místě a když se rozhodneme formát změnit, změníme ho jen ve třídě Diar. Se statikou ale opatrně, ne vždy ji je vhodné použít.

Vraťme se do třídy Diar. Přidáme 2 metody pro zjištění data a času:

private Calendar zjistiDatumCas()
{
        System.out.println("Zadejte datum a čas ve tvaru [1.1.2013 14:00]:");
        return zjistiCalendar(formatData);
}

private Calendar zjistiDatum()
{
        System.out.println("Zadejte datum ve tvaru [1.1.2013]:");
        return zjistiCalendar(formatDataBezCasu);
}

Obě využívají naši metodu zjistiCalendar(), ale dávají ji jiný formatter. Pomocí zjistiDatumCas() budeme zadávat datum a čas, pomocí zjistiDatum() budeme zadávat pouze datum. Druhá metoda bude sloužit k vyhledávání záznamů v určitý den, jelikož určitě nebudeme chtít vypsat záznam v danou hodinu a minutu, ale záznamy v daný den bez určení času.

Přidejme metodu vypisZaznamy(), která najde záznamy v daný den a vypíše je:

public void vypisZaznamy(Calendar den)
{
        ArrayList<Zaznam> zaznamy = databaze.najdiZaznamy(den, false);
        for (Zaznam z : zaznamy)
                System.out.println(z);
}

Metoda pro vyzvání uživatele k vložení parametrů nového záznamu a jeho přidání do databáze bude následující:

public void pridejZaznam()
{
        Calendar datumCas = zjistiDatumCas();
        System.out.println("Zadejte text záznamu:");
        String text = sc.nextLine();
        databaze.pridejZaznam(datumCas, text);
}

Zbývá záznamy vyhledávat a mazat. Metoda k vyhledání vrátí ArrayList s nalezenými záznamy (jen podle data, přesný čas nebude hrát roli). Vyzveme uživatele k zadání data a to předáme databázi. Výsledek zobrazíme.

public void vyhledejZaznamy()
{
        // Zadání data uživatelem
        Calendar datumCas = zjistiDatum();
        // Vyhledání záznamů
        ArrayList<Zaznam> zaznamy = databaze.najdiZaznamy(datumCas, false);
        // Výpis záznamů
        if (zaznamy.size() > 0)
        {
                System.out.println("Nalezeny tyto záznamy: ");
                for (Zaznam z : zaznamy)
                        System.out.println(z);
        }
        else
                // Nenalezeno
                System.out.println("Nebyly nalezeny žádné záznamy.");
}

Mazání záznamů je triviální:

public void vymazZaznamy()
{
        System.out.println("Budou vymazány záznamy v daný den a hodinu");
        Calendar datumCas = zjistiDatumCas();
        databaze.vymazZaznamy(datumCas);
}

Jako poslední přidejme metodu pro vypsání úvodní obrazovky programu s aktuálním datem a časem a událostmi na dnešek a zítřek.

public void vypisUvodniObrazovku()
{
        System.out.println();
        System.out.println();
        System.out.println("Vítejte v diáři!");
        Calendar dnes = Calendar.getInstance();
        System.out.printf("Dnes je: %s\n", formatData.format(dnes.getTime()));
        System.out.println();
        // výpis hlavní obrazovky
        System.out.println("Dnes:\n-----");
        vypisZaznamy(dnes);
        System.out.println();
        System.out.println("Zítra:\n------");
        Calendar zitra = Calendar.getInstance();
        zitra.add(Calendar.DAY_OF_MONTH, 1);
        //zitra.add
        vypisZaznamy(zitra);
        System.out.println();
}

Můžeme vítězoslavně přejít do Poznamkovac.java a vytvořit instanci diáře. Zde umístíme také hlavní cyklus programu s menu programu a reakcí na volbu uživatele. Je to ta nejvyšší vrstva programu:

public static void main(String[] args) {
        Scanner sc = new Scanner(System.in, "Windows-1250");
        Diar diar = new Diar();
        String volba = "";
        // hlavní cyklus
        while (!volba.equals("4"))
        {
                diar.vypisUvodniObrazovku();
                System.out.println();
                System.out.println("Vyberte si akci:");
                System.out.println("1 - Přidat záznam");
                System.out.println("2 - Vyhledat záznamy");
                System.out.println("3 - Vymazat záznam");
                System.out.println("4 - Konec");
                volba = sc.nextLine();
                System.out.println();
                // reakce na volbu
                switch (volba)
                {
                        case "1":
                                        diar.pridejZaznam();
                                        break;
                        case "2":
                                        diar.vyhledejZaznamy();
                                        break;
                        case "3":
                                        diar.vymazZaznamy();
                                        break;
                        case "4":
                                        System.out.println("Libovolnou klávesou ukončíte program...");
                                        break;
                        default:
                                        System.out.println("Neplatná volba, stiskněte libovolnou klávesu a opakujte volbu.");
                                        break;
                }
        }
}

Kód výše není složitý a již jsme tu podobný měli mockrát. Výslednou aplikaci jsem na vyzkoušení půjčil přítelkyni, zde vidíte výsledek :) :

Tímto jsme si ArrayList osvojili a bude nám poměrně dlouho stačit. Na závěr bych dodal, že takto si můžete udělat databázi čehokoli. Můžete použít např. třídu Uzivatel z lekce Gettery a settery v Javě nebo kteroukoli jinou třídu. Můžete ukládat články, úlohy, slony, cokoli, co chcete v databázi spravovat. A co dál? Příště to bude o rozhraní. V OOP nás toho čeká ještě dost :)


 

Stáhnout

Staženo 481x (24.25 kB)
Aplikace je včetně zdrojových kódů v jazyce java

 

  Aktivity (1)

Článek pro vás napsal David Čápka
Avatar
Autor pracuje jako softwarový architekt a pedagog na projektu ITnetwork.cz (a jeho zahraničních verzích). Velmi si váží svobody podnikání v naší zemi a věří, že když se člověk neštítí práce, tak dokáže úplně cokoli.
Unicorn College Autor se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.

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


 


Miniatura
Předchozí článek
Diář s databází v Javě
Miniatura
Následující článek
Rozhraní (interface) v Javě

 

 

Komentáře

Avatar
Kit
Redaktor
Avatar
Kit:

Pokud by se místo číslic 1-4 využila písmena, dalo by se to celé udělat do enum a switch by se stal zbytečným.

Odpovědět 30.4.2013 11:41
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
robineki
Člen
Avatar
robineki:

Když tam zadáte starý datum tak vám napíše: "Zadej text záznamu"
Ale to je spíše takový upomínač takže staré datum to v pohodě uloží.
Jen tak pro info. :D

Odpovědět 23.12.2013 11:42
Díky, Robineki
Avatar
Martin.mak
Člen
Avatar
Odpovídá na Kit
Martin.mak:

Jsem začátečník, Javu znám jen z devbooku ( :P )
Co to v enum znamená? :)
K placeným tutoriálům se nedostanu, nemám účet a než to lámat přes rodiče, to bude jednoduší si najít jiný zdroj informací. Možná že i levnější v případě knihy. :)

 
Odpovědět 27.8.2014 21:23
Avatar
Matěj Kripner
Redaktor
Avatar
Odpovídá na Martin.mak
Matěj Kripner:

Enumerátor je tzv. výčtový typ. Zadal jsem do googlu výčtový typ java a první dva odkazy celkem ujdou :)
http://www.algoritmy.net/…0320/Enum-19
http://java.vse.cz/…pta-enum.pdf

Odpovědět  +1 28.8.2014 9:07
"We reject kings, presidents and voting. We believe in rough consensus and running code" David Clark
Avatar
Marcel Smolik:

Pro mě to byl trochu zmatek ale to je asi normální, přece jenom nejsem tvůrce.

 
Odpovědět 12.7.2015 13:54
Avatar
Roman Duchoň:

Uf, u tohohle jsem se dost zapotil... ještě s novým DateTime API... nejdřív, že prej NullPointerEx­ception. Tak jsem upravoval, lovil na internetu a celkem mě to odradilo

Zažil to asi každý Java programátor. V aplikaci běžící na produkčním prostředí dojde k vyvolání NullPointerEx­ception. Obvyklou reakcí je zvolání „K...a!“ s razancí adekvátní vzniklému průšvihu.

viz. Java: Jak se bezpečně vyhnout NullPointerEx­ception.

Dal jsem si chvíli oraz, program celý smazal a pustil se do toho odznova. Přidal jsem novou třídu - pro datum a čas. Vadí?

Pak bych ještě zmínil problém s java.util.Con­currentModifi­cationExcepti­on. Kde mi pomohlo užití CopyOnWriteArra­yList namísto ArrayList.

Nakonec vše bylo úplně v pořádku, ač jsem se nedržel návodu. :)
Jen mně vrtá hlavou ještě jedna věc... a to sort databáze. Není ani v originálním zdrojáku... Jako třeba pro vypsání záznamu daného data. Zadám 22:00, pak 12:00... a v tomto pořadí se to vypíše.

Odpovědět 10. října 20:53
RD
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 6 zpráv z 6.