Lekce 16 - Diář s databází v Javě - Záznam, databáze a diář
V předešlém cvičení, Řešené úlohy k 13. lekci OOP v Javě, jsme si procvičili nabyté zkušenosti z předchozích lekcí.
V dnešním tutoriálu si do ArrayListu zkusíme uložit objekty.
Prvně jsem chtěl udělat databázi uživatelů, ale uživatele jsme tu již
několikrát měli. Jelikož jsme se nedávno naučili datum a čas,
naprogramujeme si diář. Do databáze budeme ukládat jednotlivé záznamy a
vždy vypíšeme ten dnešní a zítřejší. Databáze to nebude samozřejmě
ta v tom pravém slova smyslu (na to ještě nemáme zkušenosti), ale bude se
jednat právě o ArrayList
v operační paměti počítače. Bude
umožňovat záznamy přidávat, hledat je podle data a mazat podle data a
času. Založme si nový projekt, který nepojmenujeme Diar
(budeme
toto jméno potřebovat pro třídu) ale např. Poznamkovac
, to
bude název naší výsledné aplikace.
Hlavní třídu Main.java
pojmenujeme na
Poznamkovac.java
. Můžeme to udělat přes kontextovou nabídku
(pravým kliknutím na soubor Main.java
-> Refactor
-> Rename) případně ručně přejmenujeme soubor a poté i název
třídy (samozřejmě bez přípony) uvnitř kódu.
Záznam
Prvně si udělejme třídu, jejíž instance budeme ukládat. Nazvěme ji
Zaznam
. Záznam v diáři se bude vázat k nějakému datu a času.
Také bude obsahovat nějaký text. Záznam tedy bude něco jako
12. ledna 2013 - Vyvenčit psa
. To je asi vše, třída může
vypadat takto:
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 + " " + text; } }
Třída v podstatě slouží jen k záznamu dat a nemá žádné metody (až
na konstruktor a metodu toString()
a nějaké ty gettery/settery).
Funkcionalitu jako takovou ale nenabízí. Bystřejší si jistě všimli, že
metoda toString()
nijak neformátuje datum a čas. K tomu se
později ještě vrátíme. Okomentovávat v lekci nebudu, v případě potřeby
si pak můžete stáhnout celý hotový projekt i s komentáři.
Databáze
Protože program bude o něco složitější, rozdělíme ho do více
objektů (vrstev). Záznam máme, nyní si vytvoříme objekt
Databaze
, ve které budou záznamy uloženy. Opět bude mít
privátní kolekci ArrayList
, jako měl Losovac
. Ten
bude nyní typu Zaznam
. Diář bude umožňovat záznamy
přidávat, mazat a vyhledávat podle data. K projektu tedy přidáme třídu
Databaze
. Bude velmi podobná minulé třídě
Losovac
:
import java.util.ArrayList; public class Databaze { private ArrayList<Zaznam> zaznamy; public Databaze() { zaznamy = new ArrayList<>(); } }
Všimněte si použití "diamond operátoru" při vytváření nové instance
ArrayList
. Od Javy 7 nemusíme generický typ uvádět 2x, ale
stačí ho uvést pouze při deklaraci proměnné a špičaté závorky můžeme
podruhé již ponechat prázdné. Také si řekněme, že kdybychom špičaté
závorky nenapsali vůbec a ArrayList
deklarovali i inicializovali
bez uvedení generického typu, položky by se ukládaly jako typ
Object
. Museli bychom je vždy na naše zaznamy
ručně převádět. Dále v seriálu si ukážeme, jak by se to dělalo a listy
ještě potom potkáte u kolekcí.
Třída Databaze
tedy slouží pouze pro manipulaci s daty.
Obsahuje vnitřní kolekci zaznamy
, ta se inicializuje v
konstruktoru. Mohli bychom použít i inicializaci bez konstruktoru přímo u
deklarace ve formě:
private ArrayList<Zaznam> zaznamy = new ArrayList<>();
Dodejme třídě metody pro přidání, vymazání a vyhledání záznamu.
Přidání záznamu by mělo být jasné:
public void pridejZaznam(LocalDateTime datumCas, String text) { zaznamy.add(new Zaznam(datumCas, text)); }
Budeme si muset přidat i import:
import java.time.LocalDateTime;
Jako druhou metodu přidejme nalezení záznamů v daný den. Metoda bude
vracet kolekci ArrayList
nalezených záznamů, protože jich pro
ten den může být v databázi více. Záznamy budeme moci vyhledávat podle
data i času nebo jen podle data. Můžeme tak najít záznamy v konkrétní den
bez ohledu na to, v jakou jsou hodinu. Podle čeho budeme chtít vyhledávat
bude udávat parametr dleCasu
typu boolean
. Pokud bude
mít hodnotu false
, hledáme jen podle data bez ohledu na čas.
Kolekci ArrayList
si nejprve vytvoříme a poté do něj
přidáváme záznamy, které odpovídají hledanému datu. Odpovídat musí
buď celé datum a čas (pokud hledáme i podle času) nebo jen datum (pokud
hledáme jen podle data). Naplněný ArrayList
s nalezenými
záznamy vrátíme:
public ArrayList<Zaznam> najdiZaznamy(LocalDateTime datumCas, boolean dleCasu) { ArrayList<Zaznam> nalezene = new ArrayList<>(); for (Zaznam zaznam : zaznamy) { if ((dleCasu && zaznam.getDatumCas().equals(datumCas)) || (!dleCasu && zaznam.getDatumCas().toLocalDate().equals(datumCas.toLocalDate()))) { nalezene.add(zaznam); } } return nalezene; }
Nakonec přidáme vymazání záznamů v určitou dobu. To provedeme pomocí
metody najdiZaznamy()
a nalezené záznamy jednoduše proiterujeme
a z kolekce ArrayList
odstraníme. Budeme mazat podle přesného
data i času, 2. parametr u metody najdiZaznamy()
bude tedy na
hodnotě true
:
public void vymazZaznamy(LocalDateTime datum) { ArrayList<Zaznam> nalezeno = najdiZaznamy(datum, true); for (Zaznam zaznam : nalezeno) { zaznamy.remove(zaznam); } }
Diář
Nyní si přidáme k projektu poslední třídu, bude to samotný diář.
Nazvěme ji Diar
. Ten již bude obsahovat metody pro komunikaci s
uživatelem. Všimněte si, jak aplikaci rozdělujeme a jednotlivé její
části zapouzdřujeme. Kolekce ArrayList
je zapouzdřena v
databázi, která nad ním postavila další metody pro bezpečnou manipulaci s
jeho obsahem. Samotnou databázi nyní vložíme do diáře. Tím oddělíme
logiku a práci s daty od komunikace s uživatelem a dalšími vstupy/výstupy
programu. Třída Diar
tedy bude komunikovat s uživatelem a data
od něj předá databázi.
Přidejme si privátní instanci databáze, kterou si vytvoříme v
konstruktoru. Podobně přidejme i instanci třídy Scanner
, kterou
budeme ve třídě potřebovat:
import java.util.Scanner; public class Diar { private Databaze databaze; private Scanner scanner = new Scanner(System.in); public Diar() { databaze = new Databaze(); } }
V další lekci, Diář s databází v Javě - Metody diáře, výjimky a final, se podíváme na metody třídy Diar
,
krátce koukneme na výjimky a klíčové slovo final.