Při tvorbě aplikací, které pracují s většími objemy dat, vždy dříve či později narazíme na problém, jakým způsobem a kam data ukládat. Standardem pro ukládání dat jsou v dnešní době relační databáze, které daný úkol plní velmi efektivně, přičemž můžeme volit z široké nabídky jak volně šířených, tak komerčních implementací. Programujeme-li v Javě, máme hned několik možností, jak relační databáze využít.

Jak ukládat data v Javě

V první řadě můžeme použít standardní rozhraní JDBC, které umožňuje přímo přistupovat k prakticky libovolné relační databázi pomocí jazyka SQL. Toto řešení je implementačně nenáročné, nevyžaduje žádné nadstavbové balíky, takže výsledná aplikace může být velmi malá a efektivní. Na druhou stranu se musíme smířit s tím, že si budeme muset sami navrhnout strukturu databáze a implementovat zvlášť ukládání, změnu a zpětné získávání každého kousku dat. V okamžiku, kdy je zapotřebí strukturu dat lehce změnit, je zapotřebí upravit strukturu příslušné tabulky a všechny SQL příkazy s ní pracující, což může snadno přerůst v noční můru každého programátora.

Java je ovšem jazyk objektově orientovaný a vnitřně jsou proto obvykle všechna data, se kterými pracujeme, reprezentována jako objekty. Z tohoto pohledu tedy vypadá rozumně neukládat jednotlivé datové položky (tedy jednotlivé vlastnosti daných objektů), ale donutit objekty, aby se ukládaly celé. Mějme například třídu Osoba definovanou takto:

public class Osoba
{
    protected String jmeno;
    protected String prijmeni;
    protected int vek;
    public Osoba(String jmeno, String prijmeni, int vek)
    {
        …
    }
}

Každá osoba, o které uchováváme informace, je tedy reprezentována jako objekt třídy Osoba. Místo toho, abychom konstruovali SQL příkaz, který uloží jméno, příjmení a věk osoby do relační tabulky (INSERT) a následně obdobné příkazy pro změnu (UPDATE) a zpětné načtení (SELECT) těchto údajů, nabízí se myšlenka uchovat každý vytvořený objekt jako celek. Takové objekty, jejichž existence přetrvá vlastní běh aplikace, se nazývají persistentní objekty.

Toto řešení má mnoho výhod oproti prostému použití relační databáze. Předně objekty, na rozdíl od relací, mají vlastní identitu, odpadají proto starosti s volbou primárního klíče, který by v předchozím příkladě nejspíše musel být generován uměle. A dále, pokud během vývoje aplikace změníme strukturu objektu (například přidáme osobě rodinný stav), nemusíme revidovat všechny SQL příkazy.

Nejelegantnější řešení představuje přímo použití objektové databáze, která obsahuje Javovské aplikační rozhraní, jako například Caché. Naneštěstí objektové databáze dosud zdaleka nedosáhly tak masového rozšíření jako databáze relační a zatímco například velmi kvalitní relační MySQL je běžnou součástí linuxových distribucí a běží na kdejakém (i freehostingovém) serveru, objektovou databázi si obvykle můžeme dopřát pouze pokud máme kam si ji sami nainstalovat, nehledě k tomu, že se v naprosté většině jedná o nákladné komerční řešení. Mnohem reálnější řešení proto představuje použití některého nástroje pro persistenci objektů s využitím relační databáze.

V případě Javy je v tomto směru opět z čeho vybírat. Standardním řešením je použití J2EE a Entity beans, což ovšem vyžaduje podřídit styl psaní celé aplikace tomuto modelu a pro většinu použití představuje příslovečný kanón na vrabce. Mnohem jednodušší řešení poskytují nestandardní nástroje pro persistenci objektů jako Hibernate nebo TopLink, které zajišťují persistenci běžných objektů v Javě. Každý z těchto nástrojů má ovšem své vlastní aplikační rozhraní, takže případný přechod k jiné implementaci znamená přepsání větší části aplikace. Zbytek článku proto věnujeme popisu standardního rozhraní pro persistenci objektů v Javě s názvem Java Data Objects (JDO).

Java Data Objects

Takzvané JDO neboli Java Data Objects je standardizované aplikační rozhraní pro persistenci objektů v Javě, vyvinuté přímo firmou Sun Microsystems, která je i původcem Javy jako takové. JDO umožňuje implementovat libovolný způsob ukládání objektů – může sloužit jako aplikační rozhraní objektové databáze, ale stejně tak může provádět mapování objektů na relační tabulky a ukládat data do relační databáze. Podstatné ovšem je, že aplikační rozhraní je zcela nezávislé na vlastní implementaci persistence, a proto aplikace využívající JDO mohou bez větších změn ukládat data do různých relačních i objektových databází.

Vytváření persistentních objektů

Samotné aplikační rozhraní není nijak složité. V podstatě sestává z třídy PersistenceManagerFactory, která spravuje konfiguraci persistence, PersistenceManager, která implementuje metody pro persistenci objektů, a třídy Transaction pro správu transakcí. Všechny tyto třídy nalezneme v balíku javax.jdo.

Práci s persistentními objekty v JDO si nejlépe ukážeme na příkladu. Vytvořme si pokusný objekt třídy Osoba:

Osoba karel = new Osoba(„Karel“, „Novak“, 32);

Chceme-li uložit údaje o příslušné osobě, musíme z vytvořeného objektu udělat objekt persistentní. V JDO tak učiníme následujícím způsobem:

/* Inicializace persistence */
Properties properties = new Properties();
properties.setProperty(…, …);

PersistenceManagerFactory pmfactory =
    JDOHelper.getPersistenceManagerFactory(properties);
PersistenceManager pm = pmfactory.getPersistenceManager();
/* Začátek transakce */
Transaction tx = pm.currentTransaction();
tx.begin();
pm.makePersistent(karel);
/*
… další práce s persistentními objekty …
*/

/* Konec transakce */
tx.commit();

První fáze spočívá v konfiguraci objektu PersistenceManagerFactory podle toho, kam a jakým způsobem chceme ukládat data. Konfigurace spočívá ve vytvoření množiny vlastností (properties), které udávají způsob připojení k databázi a další parametry.

Dalším krokem je vytvoření objektu třídy PersistenceManager, který se bude starat o persistenci jednotlivých datových objektů. Tento objekt je vytvořen pomocí PersistenceManagerFactory na základě předchozí konfigurace.

Práce s persistentním objektem probíhá v rámci takzvané transakce. Transakce začíná voláním begin() a během jejího trvání je možno vytvářet persistentní objekty a měnit jejich vlastnosti. V okamžiku ukončení transakce voláním commit() se aktuální stav persistentních objektů uloží do databáze. V našem případě v rámci transakce pouze učiníme z objektu karel persistentní objekt pomocí volání metody makePersistent(), čímž zajistíme, že v okamžiku volání commit() se aktuální stav objektu uloží do databáze.

Přístup k persistentním objektům

Máme-li persistentní objekty uložené v databázi, bylo by vhodné, abychom se k nim při dalším spuštění aplikace opět dostali. JDO nabízí několik možností, jak v databázi najít požadovaný objekt a načíst jej tak, aby byl opět zpracovatelný v aplikaci.

Pro demonstraci základních možností JDO si prozatím ukážeme přístup k objektům přes takzvané extenty. V objektových databázích obecně extent představuje kolekci všech objektů dané třídy uložených v databázi. V případě JDO probíhá čtení objektů z databáze opět v rámci transakce a typicky vypadá následovně (předpokládáme již existující PersistenceManager z předchozího příkladu):

Transaction tx = pm.currentTransaction();
tx.begin();
Extent extent = pm.getExtent(Osoba.class, false);
for (Iterator i = extent.iterator(); i.hasNext(); ) {
    Osoba nekdo = (Osoba) i.next();
    /* … zpracuj informace o osobě … */
}
tx.comit();

Objekty načtené z databáze jsou samozřejmě persistentní, takže jakákoli změna v nich provedená během transakce se na konci automaticky uloží zpět do databáze.

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět