Geek tričko zdarma Geek tričko zdarma
Hledáme grafika na pohodovou brigádu v Blenderu nebo programátora na hry v PyGame. Máš zájem? Napiš nám na redakce [zavináč] itnetwork.cz!
Tričko zdarma! Stačí před dobitím bodů použít kód TRIKO15. Více informací zde

Lekce 16 - Diář s databází v Javě (dokončení)

Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem.
Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V minulé lekci, Diář s databází v Javě, jsme rozpracovali jednoduchý diář s databází pomocí ArrayListu. V dnešním tutoriálu aplikaci dokončíme.

Do třídy Diar přidejme dvě pomocné metody zjistiDatumCas() a zjistiDatum(), které vyzvou uživatele k zadání data (a případně času) a vrátí instanci LocalDateTime nastavenou na tuto hodnotu. Nejprve si metody ukažme, záhy si je popíšeme:

private LocalDateTime zjistiDatumCas() {
    System.out.println("Zadejte datum a čas ve tvaru [1.1.2013 14:00]:");
    while (true) {
        try {
            return LocalDateTime.parse(sc.nextLine(), FORMAT_DATA);
        } catch (Exception ex) {
            System.out.println("Nesprávně zadáno, zadejte prosím znovu");
        }
    }
}

private LocalDateTime zjistiDatum() {
    System.out.println("Zadejte datum ve tvaru [1.1.2013]:");
    while (true) {
        try {
            return LocalDate.parse(sc.nextLine(), FORMAT_DATA_BEZ_CASU).atStartOfDay();
        } catch (Exception ex) {
            System.out.println("Nesprávně zadáno, zadejte prosím znovu");
        }
    }
}

Metody fungují téměř identicky. Jediný rozdíl je v třídě, která volá metodu parse(). V případě načtení data a času použijeme třídu LocalDateTime a formát FORMAT_DATA. V případě načtení pouze datumu musíme použít třídu LocalDate a formát FORMAT_DATA_BET_CA­SU. To nám ale vrátí instanci třídy LocalDate. Musíme tedy ještě zavolat metodu atStartOfDay(), abychom vrátili instanci třídy LocalDateTime. Celé čtení je zabaleno do nekonečné smyčky (viz while (true)). Tím docílíme, že budeme načítat vstup od uživatele do té doby, než zadá validní vstup. Parsování vstupu je ještě zabaleno do try-catch bloku. V případě nevalidního vstupu informujeme uživatele, že musí vstup zadat znovu.

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.

Do třídy si přidejme 2 veřejné, statické konstanty. 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 final DateTimeFormatter FORMAT_DATA = DateTimeFormatter.ofPattern("d'.'M'.'y H:mm");
public static final DateTimeFormatter FORMAT_DATA_BEZ_CASU = DateTimeFormatter.ofPattern("d'.'M'.'y");
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

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.FORMAT_DATA.format(datumCas) + " " + 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.

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

public void vypisZaznamy(LocalDateTime 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() {
    LocalDateTime 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
    LocalDateTime 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");
    LocalDateTime 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!");
    LocalDateTime dnes = LocalDateTime.now();
    System.out.printf("Dnes je: %s\n", FORMAT_DATA.format(dnes));
    System.out.println();
    // výpis hlavní obrazovky
    System.out.println("Dnes:\n-----");
    vypisZaznamy(dnes);
    System.out.println();
    System.out.println("Zítra:\n------");
    LocalDateTime zitra = LocalDateTime.now().plusDays(1);
    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 :) :

Konzolová aplikace
Vítejte v diáři!
Dnes je: 13.6.2016 20:22

Dnes:
-----
13.6.2016 10:00 Shopping - Arkády Pankrác
13.6.2016 19:30 Vyvenčit mého yorkšírka Dennyho

Zítra:
------
14.6.2016 14:00 Power plate

Vyberte si akci:
1 - Přidat záznam
2 - Vyhledat záznamy
3 - Vymazat záznam
4 - Konec
2
Zadejte datum ve tvaru [1.1.2012]:
15.6.2016
Nalezeny tyto záznamy:
15.6.2016 9:30 Zkouška - Ekonomika cestovního ruchu

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? V příští lekci, Rozhraní (interface) v Javě, to bude o rozhraní. V OOP nás toho čeká ještě dost :)


 

Stáhnout

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

 

 

Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
14 hlasů
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 sítě se informační technologie naučil na Unicorn College - prestižní soukromé vysoké škole IT a ekonomie.
Předchozí článek
Diář s databází v Javě
Všechny články v sekci
Objektově orientované programování v Javě
Miniatura
Následující článek
Rozhraní (interface) v Javě
Aktivity (11)

 

 

Komentáře
Zobrazit starší komentáře (8)

Avatar
Seyuki.Yamamoro:21.1.2018 20:51

Omlouvam se
Vnimal jsem vic kurz javy pri kterym jsem to datloval...
To byl nechtene muj log na co se podivat pred smazanim projektu a znovutvorbou.

Zitra na to kouknu s plnym soustredenim.
Muj osobni typ ted je, ze jsem ja i roman zapomenul naimportovat neco...
Asi toto do zaznamu
import java.util.Calendar

 
Odpovědět 21.1.2018 20:51
Avatar
Tonda Đình Hoàng:12.2.2018 17:50

Mám otázku, když přidám záznam tak se to uloží, ale když vypnu program tak se smaže i záznam.

Nevíte to někdo jak to uložit jakože na pořát ten záznam i když ten program vypnu?

Děkuju moc

 
Odpovědět  -1 12.2.2018 17:50
Avatar
Will Cooper
Člen
Avatar
Will Cooper:26.7.2018 15:55

Čau, přepsal jsem to tak, aby se místo třídy Calendar používala třída LocalDateTime. Tady je zdroják:

Třída Databaze

import java.time.LocalDateTime;
import java.util.ArrayList;

public class Databaze {

    private ArrayList<Zaznam> zaznamy;

    public Databaze() {
        zaznamy = new ArrayList<>();
    }

    public void pridejZaznam(LocalDateTime datumCas, String text) {
        zaznamy.add(new Zaznam(datumCas, text));
    }

    public ArrayList<Zaznam> najdiZaznamy(LocalDateTime datum, boolean dleCasu) {
        ArrayList<Zaznam> nalezene = new ArrayList<>();
        for(Zaznam z : zaznamy) {
            if((dleCasu && (z.getDatumCas().equals(datum))) // podle data a času
                ||
              ((!dleCasu) && (z.getDatumCas().toLocalDate().equals(datum.toLocalDate())))) { // podle data
                nalezene.add(z);
            }
        }
        return nalezene;
    }

    public void vymazZaznamy(LocalDateTime datum) {
        ArrayList<Zaznam> nalezeno = najdiZaznamy(datum, true);
        for(Zaznam z : nalezeno){
            zaznamy.remove(z);
        }
    }

}

Třída Zaznam

import java.time.LocalDateTime;

public class Zaznam {
    private LocalDateTime datumCas;
    private String text;

    public Zaznam (LocalDateTime datumCas, String text) {
        this.datumCas = datumCas;
        this.text = text;
    }

    public LocalDateTime getDatumCas() {
        return datumCas;
    }

    public void setDatumCas(LocalDateTime datumCas) {
        this.datumCas = datumCas;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }

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

}

Třída Diar

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.Scanner;

public class Diar {
    private Databaze databaze;
    private Scanner sc = new Scanner(System.in, "Windows-1250");
    public static DateTimeFormatter formatData = DateTimeFormatter.ofPattern("d.M.y HH:mm");
    public static DateTimeFormatter formatDataBezCasu = DateTimeFormatter.ofPattern("d.M.y");

    public Diar(){
        databaze = new Databaze();
    }

    private LocalDateTime zjistiDatumCas() {
        System.out.println("Zadejte datum a čas ve tvaru [1.1.2013 14:00]:");
        LocalDateTime datumCas;
        try {
            datumCas = LocalDateTime.parse(sc.nextLine(), formatData);
        }
        catch (DateTimeParseException e) {
            System.out.println("Nesprávně zadáno, zadejte prosím znovu");
            return zjistiDatumCas();
        }
        return datumCas;
    }

    private LocalDate zjistiDatum() {
        System.out.println("Zadejte datum ve tvaru [1.1.2013]:");
        LocalDate datum;
        try {
            datum = LocalDate.parse(sc.nextLine(), formatDataBezCasu);
        }
        catch (DateTimeParseException e) {
            System.out.println("Nesprávně zadáno, zadejte prosím znovu");
            return zjistiDatum();
        }
        return datum;
    }

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

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

    public void vyhledejZaznamy() {
        // Zadání data uživatelem
        LocalDateTime datumCas = zjistiDatum().atStartOfDay();
        // 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.");
        }
        sc.nextLine(); // počká na enter
    }

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

    public void vypisUvodniObrazovku() {
        System.out.println();
        System.out.println();
        System.out.println("Vítejte v diáři!");
        System.out.println("Dnes je: " + LocalDateTime.now().format(formatData));
        System.out.println();
        // výpis domácí obrazovky
        System.out.println("Dnes:\n------");
        vypisZaznamy(LocalDate.now());
        System.out.println();
        System.out.println("Zítra:\n---------");
        vypisZaznamy(LocalDate.now().plusDays(1));
        System.out.println();
    }

}
 
Odpovědět  +4 26.7.2018 15:55
Avatar
Jáchym Zosinčuk:31.10.2018 16:32

Ahoj, mám jeden malý problém se svým diářem. Dělal jsem ho s LocalDateTime, ale neinspiroval jsem se nikde, ani viz výše. Vše funguje jak má, ale nedaří se mi z něj vipsat údaje v pro člověka pochopotelném formátu. Když použiji System.out.prin­tln(z), jako v zdrojáku výše vyskočí mi na řádku toto: diar.vz.pkg2.Zaz­[email protected] Nějaký tip jak to správně zformátovat?

 
Odpovědět 31.10.2018 16:32
Avatar
Petr Štechmüller
Překladatel
Avatar
Odpovídá na Jáchym Zosinčuk
Petr Štechmüller:31.10.2018 17:01

Ahoj, musíš přepsat metodu toString ve třídě Zaznamnik. Pak už se to bude podle tvých pravidel.

Editováno 31.10.2018 17:01
Odpovědět 31.10.2018 17:01
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Odpovídá na Petr Štechmüller
Jáchym Zosinčuk:2.11.2018 15:53

Děkuju! Na to jsem úplně zapoměl. Program funguje jak má na 100%, díky. Už můžu v noci teď spát. :)

 
Odpovědět 2.11.2018 15:53
Avatar
David Čápka
Tým ITnetwork
Avatar
David Čápka:12. června 15:31

Aktualizováno na nové datetime API.

Odpovědět 12. června 15:31
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
ishei
Člen
Avatar
ishei:25. června 10:34

V clanku je omylem 2x kod metody vypisZaznamy(), podruhe namisto metody s vyzvou pro uzivatele k zadani zaznamu a jeho pridani do DB.

 
Odpovědět 25. června 10:34
Avatar
Petr Štechmüller
Překladatel
Avatar
Odpovídá na ishei
Petr Štechmüller:25. června 10:57

Pravda :-P Opravím to...

Odpovědět 25. června 10:57
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
ishei
Člen
Avatar
Odpovídá na Petr Štechmüller
ishei:25. června 11:51

To je rychlost. Jeste v mainu cast:

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;

lehce zavani C#..

 
Odpovědět 25. června 11:51
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 10 zpráv z 18. Zobrazit vše