15. diel - Diár s databázou v Jave - Záznam, databáza a diár
V predchádzajúcom cvičení, Riešené úlohy k 12. lekcii OOP v Jave, sme si precvičili získané skúsenosti z predchádzajúcich lekcií.
V dnešnom tutoriále si do ArrayListu skúsime uložiť objekty.
Najprv som chcel urobiť databázu používateľov, ale používateľa sme tu
už niekoľkokrát mali. Keďže sme nedávno preberali dátum a čas,
naprogramujeme si diár. Do databázy budeme ukladať jednotlivé záznamy a
vždy vypíšeme ten dnešný a zajtrajší. Nebude to databáza v tom pravom
slova zmysle (na to ešte nemáme skúsenosti), ale bude sa jednať práve o
ArrayList
v operačnej pamäti počítača. Bude umožňovať
záznamy pridávať, hľadať ich podľa dátumu a mazať podľa dátumu a
času. Založme si nový projekt, ktorý nepomenujeme Diary
(budeme
toto meno potrebovať pre triedu) ale napr. Journal
, to bude názov
našej výslednej aplikácie.
Hlavnú triedu Main.java
premenujeme na
Journal.java
. Môžeme to urobiť cez kontextovú ponuku (pravým
kliknutím na súbor Main.java
-> Refactor ->
Rename) prípadne ručne premenujeme súbor a potom aj názov triedy
(samozrejme bez prípony) vo vnútri kódu.
Záznam
Najprv si urobme triedu, ktorej inštancie budeme ukladať. Nazvime ju
Entry
. Záznam v diári sa bude viazať k nejakému dátumu a
času. Tiež bude obsahovať nejaký text. Záznam teda bude niečo ako
January 12, 2013 - Walk the dog
. To je asi všetko, trieda môže
vyzerať takto:
import java.time.LocalDateTime; public class Entry { private LocalDateTime dateTime; private String text; public Entry(LocalDateTime dateTime, String text) { this.dateTime = dateTime; this.text = text; } public LocalDateTime getDateTime() { return dateTime; } public void setDateTime(LocalDateTime dateTime) { this.dateTime = dateTime; } public String getText() { return text; } public void setText(String text) { this.text = text; } @Override public String toString() { return dateTime + " " + text; } }
Trieda v podstate slúži len na záznam dát a nemá žiadne metódy (až na
konštruktor a metódu toString()
a nejaké tie gettery/settery).
Funkcionalitu ako takú ale neponúka. Bystrejší si určite všimli, že
metóda toString()
nijako neformátuje dátum a čas. K tomu sa
neskôr ešte vrátime. Komentovať v lekcii nebudem, v prípade potreby si
potom môžete stiahnuť celý hotový projekt aj s komentármi.
Databáza
Pretože program bude o niečo zložitejší, rozdelíme ho na viaceré
objekty (vrstvy). Záznam máme, teraz si vytvoríme objekt
Database
, v ktorom budú záznamy uložené. Opäť bude mať
privátnu kolekciu ArrayList
, ako mala trieda Lottery
.
Kolekcia bude teraz typu Entry
. Diár bude umožňovať záznamy
pridávať, mazať a vyhľadávať podľa dátumu. K projektu teda pridáme
triedu Database
. Bude veľmi podobná minulej triede
Lottery
:
import java.util.ArrayList; public class Database { private ArrayList<Entry> entries; public Database() { entries = new ArrayList<>(); } }
Všimnite si použitie "diamond operátora" pri vytváraní novej inštancie
ArrayList
. Od Javy 7 nemusíme generický typ uvádzať 2x, ale
stačí ho uviesť iba pri deklarácii premennej a špicaté zátvorky môžeme
druhýkrát už ponechať prázdne. Tiež si povedzme, že keby sme špicaté
zátvorky nenapísali vôbec a ArrayList
deklarovali aj
inicializovali bez uvedenia generického typu, položky by sa ukladali ako typ
Object
. Museli by sme ich vždy na naše entries
ručne prevádzať. Ďalej v seriáli si ukážeme, ako by sa to robilo a listy
ešte potom stretnete pri kolekciách.
Trieda Database
teda slúži iba na manipuláciu s dátami.
Obsahuje vnútornú kolekciu entries
, tá sa inicializuje v
konštruktore. Mohli by sme použiť aj inicializáciu bez konštruktora priamo
pri deklarácii vo forme:
private ArrayList<Entry> entries = new ArrayList<>();
Dodajme triede metódy na pridanie, vymazanie a vyhľadanie záznamu.
Pridanie záznamu by malo byť jasné:
public void addEntry(LocalDateTime dateTime, String text) { entries.add(new Entry(dateTime, text)); }
Budeme si musieť pridať aj import:
import java.time.LocalDateTime;
Ako druhú metódu pridajme nájdenie záznamov v daný deň. Metóda bude
vracať kolekciu ArrayList
nájdených záznamov, pretože ich pre
ten deň môže byť v databáze viac. Záznamy budeme môcť vyhľadávať
podľa dátumu i času alebo len podľa dátumu. Môžeme tak nájsť záznamy v
konkrétny deň bez ohľadu na to, v akú sú hodinu. To, podľa čoho budeme
chcieť vyhľadávať, bude udávať parameter byTime
typu
boolean
. Ak bude mať hodnotu false
, hľadáme len
podľa dátumu bez ohľadu na čas. Kolekciu ArrayList
si najskôr
vytvoríme a potom do nej pridávame záznamy, ktoré zodpovedajú hľadanému
dátumu. Zodpovedať musí buď celý dátum a čas (ak hľadáme aj podľa
času) alebo len dátum (ak hľadáme len podľa dátumu). Naplnený
ArrayList
s nájdenými záznamami vrátime:
public ArrayList<Entry> findEntries(LocalDateTime dateTime, boolean byTime) { ArrayList<Entry> found = new ArrayList<>(); for (Entry entry : entries) { if ((byTime && (entry.getDateTime().equals(dateTime))) || ((!byTime) && (entry.getDateTime().toLocalDate().equals(dateTime.toLocalDate())))) { found.add(entry); } } return found; }
Nakoniec pridáme vymazanie záznamov v určitú dobu. To urobíme pomocou
metódy findEntries()
a nájdené záznamy jednoducho preiterujeme
a z kolekcie ArrayList
odstránime. Budeme mazať podľa presného
dátumu aj času, 2. parameter pri metóde findEntries()
bude teda
na hodnote true
:
public void deleteEntries(LocalDateTime dateTime) { ArrayList<Entry> found = findEntries(dateTime, true); for (Entry entry : found) { entries.remove(entry); } }
Diár
Teraz si pridáme k projektu poslednú triedu a bude ňou samotný diár.
Nazvime ju Diary
. Tá už bude obsahovať metódy na komunikáciu s
používateľom. Všimnite si, ako aplikáciu rozdeľujeme a jej jednotlivé
časti zapuzdrujeme. Kolekcia ArrayList
je zapuzdrená v databáze,
ktorá nad ňou postavila ďalšie metódy pre bezpečnú manipuláciu s jej
obsahom. Samotnú databázu teraz vložíme do diára. Tým oddelíme logiku a
prácu s dátami od komunikácie s používateľom a ďalšími
vstupmi/výstupmi programu. Trieda Diary
teda bude komunikovať s
používateľom a dáta od neho odovzdá databáze.
Pridajme si privátnu inštanciu databázy, ktorú si vytvoríme v
konštruktore. Podobne pridajme aj inštanciu triedy Scanner
,
ktorú budeme v triede potrebovať:
import java.util.Scanner; public class Diary { private Database database; private Scanner scanner = new Scanner(System.in); public Diary() { database = new Database(); } }
V ďalšej lekcii, Diár s databázou v Jave - Metódy diára, výnimky a final, sa pozrieme na metódy triedy Diary
,
v krátkosti si predstavíme výnimky a kľúčové slovo
final
.