JDO – různé implementace a jejich použití

20. ledna 2005

Předtím, než se ponoříme hlouběji do samotného rozhraní JDO, musíme si objasnit, jak je to s vlastní implementací JDO a co všechno budeme potřebovat k tomu, abychom mohli vytvořit aplikaci v Javě založenou na JDO. Seznámíme se s některými dostupnými implementacemi a podíváme se, jak nakonfigurovat JDO implementaci, aby spolupracovala s naším databázovým serverem.

Implementace JDO

Standard JDO byl navržen za účasti mnoha stran v rámci Java Community Process (JCP). Na návrhu se podíleli mimo jiné výrobci objektových a relačních databází, aplikačních serverů, vývojových prostředí a další. Specifikace JDO se v současné době nachází ve verzi 1.0.1, verze 2.0 slibující mnohá rozšíření je zatím ve fázi návrhu.

Firma Sun vydala takzvanou referenční implementaci JDO, která je volně dostupná jak v binární podobě, tak ve zdrojových kódech. Nicméně její funkčnost je značně omezená. Implementuje kompletní aplikační rozhraní JDO, avšak ukládání persistentních objektů je omezeno pouze na lokální soubory (žádná podpora jakéhokoli databázového serveru) a z dalších důležitých vlastností chybí například vyhledávání objektů pomocí dotazů. Od počátku vývoje JDO se totiž předpokládalo, že implementace kompletního JDO bude zcela v rukou třetích stran – ať již výrobců existujících databázových systémů, či ostatních, zcela nezávislých výrobců.

V současnosti existuje velký výběr dostupných implementací JDO. Ve většině případů se jedná o komerční produkty. Výhodou komerčních implementací je široký výběr nadstavbových nástrojů, rozsálá dokumentace a integrace do běžně používaných vývojových prostředí. Za všechny můžeme jmenovat například produkt JCredo, který je v základní verzi volně dostupný, nebo Kodo, který je také k dispozici pro bezplatné vyzkoušení. Z pohledu seznámení se s JDO jsou mnohem zajímavější volně šířené open-source implementace, kterých začíná být poměrně slušný výběr. Uveďme alespoň stručný přehled (bez nároku na úplnost):

  • Triactive JDO – rychlá a kompaktní implementace sestávající z jednoho JAR balíčku. Drobnou nevýhodou je chybějící podpora některých pokročilých vlastností JDO, pro většinu aplikací je však zcela postačující.
  • Speedo – implementuje prakticky celý JDO standard včetně volitelných rozšíření. Na rozdíl od předchozí „odlehčené“ implementace se však jedná o rozsáhlý kolos postavený na celé řadě různých knihoven, což způsobuje jistou těžkopádnost.
  • JPOX – pravděpodobně nejkvalitnější open-source implementace, která je v současnosti k dispozici. Stabilní verze implementuje celý standard JDO 1.0.1, vývojové verze již implementují značnou část dosud neschváleného JDO 2.0. Vývoj je velice aktivní a vývojáři velmi rychle reagují na veškeré nalezené problémy.
  • Jakarta OJB – příspěvek Apache Software Foundation k implementaci JDO. V současnosti existuje ve formě přídavného modulu k referenční implementaci SUNu a nepodporuje JDO v plné šíři.
  • XORM – tato implementace poněkud vybočuje z řady. Aplikační rozhraní vychází z JDO, autoři ovšem zavádějí několik koncepčních změn, které způsobují určitou nekompatibilitu s původním JDO.

Prostřednictvím standardních JDBC konektorů umožňují všechny uvedené implementace používat k persistenci objektů všechny hlavní databázové servery jako Oracle, MySQL, MS SQL, PostgreSQL a další.

V dalším textu budu demonstrovat veškeré vlastnosti JDO na implementaci JPOX, protože dodržuje standard ve všech bodech a je snadno dostupná a použitelná. Části týkající se JDO jako takového platí i pro všechny ostatní implementace respektující standard, rozdíly jsou většinou v ovládání různých podpůrných nástrojů. Na tyto odchylky vždy upozorním.

Rozšiřování tříd

Všechny třídy, s jejichž objekty se bude v aplikaci pracovat jako s persistentními (budou ukládány do databáze), musí implementovat rozhraní PersistenceCapable. V referenční implementaci ani ve většině ostatních impelentací JDO není ovšem vyžadována specifikace ani implementace tohoto rozhraní přímo v kódu aplikace, nýbrž je dodána až následně pomocí externího nástroje zvaného class enhancer. Enhancer pracuje obvykle až s přeloženými třídami (soubory *.class) a přidá do již vytvořeného byte kódu specifikaci rozhraní PersistenceCapable a implementaci jeho metod, které jsou nezbytné k persistenci objektu. Tento nástroj je k dispozici již v referenční implementaci, většina výrobců ovšem dodává vlastní verzi, která je s původní verzí kompatibilní, ale obsahuje některá specifická rozšíření výrobce. Například v JPOX lze enhancer zavolat následujícím příkazem:

java org.jpox.enhancer.JPOXEnhancer <package.jdo>

Enhancer je nutno použít vždy po přeložení příslušných tříd. Používáme-li ant pro překlad projektu, můžeme rozšíření tříd s výhodou zařadit přímo do procesu překladu. Soubor package.jdo obsahuje takzvaná metadata určující, které třídy a jakým způsobem se budou rozšiřovat.

Metadata tříd

Pro třídy, jejichž objekty mají být persistentní, je třeba specifikovat dodatečné informace o způsobu jejich uložení v databázi, takzvaná metadata. Specifikace metadat se tvoří pro každý balík tříd, tedy pro každý adresář, ve kterém jsou uloženy třídy persistentních objektů, a je uložena v souboru package.jdo ve stejném adresáři. Pokud existují další podadresáře obsahující třídy, mohou být metadata pro tyto třídy specifikována ve stejném souboru nebo opět v souborech package.jdo v každém podadresáři zvlášť. Tyto přístupy lze i kombinovat. Standard JDO připouští i další varianty, které však využijeme pouze ve speciálních případech. Samotná specifikace je založena na formátu XML. Ukažme si vše na jednoduchém příkladě. Mějme opět jednoduchou třídu Osoba:

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

JDO vyžaduje, aby každá třída tvořící persistentní objekty měla definován implicitní konstruktor (konstruktor bez parametrů), i kdyby měl být prázdný. Metadata pro tuto třídu specifikujeme v souboru package.jdo umístěném ve stejném adresáři:

<?xml version=“1.0″ encoding=“UTF-8″?>
<!DOCTYPE jdo PUBLIC
    „-//Sun Microsystems, Inc.//DTD Java Data Objects Metadata 1.0//EN“
    „http://java.sun.com/dtd/jdo_1_0.dtd“>
<jdo>
<package name=“org.demo“>
    <class name=“Osoba“ identity-type=“datastore“>
        <field name=“jmeno“>
            <extension vendor-name=“jpox“ key=“length“ value=“max 100″/>
        </field>
        <field name=“prijmeni“>
            <extension vendor-name=“jpox“ key=“length“ value=“max 100″/>
        </field>
        <field name=“vek“/>
    </class>
</package>
</jdo>

Metadata pro každou třídu specifikujeme pomocí značky <class>. V našem případě definujeme pouze jméno třídy a skutečnost, že identitu objektů generuje úložiště, tedy vnitřní implementace JDO, což je implicitní hodnota. Další variantou je generování identity ve vlastní režii aplikace, o tom se však podrobněji zmíním někdy příště.

Dále je třeba zadat všechny vlastnosti třídy, které mají být ukládány do databáze, pomocí značky <field>. Datový typ každé vlastnosti vyplývá z deklarace třídy, proto není třeba jej zadávat v metadatech. U položek typu String je vhodné zadávat maximální délku, aby implementace JDO mohla správně vygenerovat databázové tabulky. Aktuální verze JDO 1.0.1 tuto možnost standardně neobsahuje, proto je tato vlastnost vyřešena pomocí specifického rozšíření výrobce (značka <extension>). Na příkladu vidíme specifikaci pro JPOX, většina ostatních implementací však používá stejnou syntaxi s tím, že hodnota atributu vendor-name se samozřejmě liší. Podrobnosti lze vždy nalézt v dokumentaci příslušné implementace. Budoucí standard JDO 2.0 by již měl tyto specifikace sjednotit. Pro vlastnosti typu int (v našem příkladě vlastnost vek) není nutné v běžných případech specifikovat žádné dodatečné informace.

Konfigurace JDO

Než začneme používat libovolnou implementaci JDO, je nutno ji nakonfigurovat, tedy přinejmenším specifikovat, který databázový server a která databáze se bude používat, a zadat příslušné uživatelské jméno a heslo, přes které se bude k serveru přistupovat. Jak bylo naznačeno v předchozím článku, toto nastavení se děje přes Javovské properties neboli vlastnosti. Pro správné nastavení JDO je třeba specifikovat hodnoty následujících vlastností:

javax.jdo.PersistenceManagerFactoryClass
Třída implementující JDO. Pro každou imlementace lze nalézt v dokumentaci. Pro JPOX zadáme org.jpox.PersistenceManagerFactoryImpl, pro Triactive JDO je to třída com.triactive.jdo.PersistenceManagerFactoryImpl.
javax.jdo.option.ConnectionDriverName
Třída implementující JDBC driver příslušného databázového serveru. Například pro MySQL zadáme com.mysql.jdbc.Driver.
javax.jdo.option.ConnectionURL
JDBC adresa databázového serveru. Zadáváme fyzický server a jméno databáze. Například pro MySQL na serveru muj.server.com a databázi mojedata zadáme jdbc:mysql://muj.server.com/mojedata.
javax.jdo.option.ConnectionUserName
Uživatelské jméno (login) pro přístup k příslušné databázi. Uživatel musí být předem vytvořen na databázovém serveru a musí mít právo přístupu k dané databázi.
javax.jdo.option.ConnectionPassword
Heslo pro přístup k dané databázi.

Pro JPOX a MySQL server může konfigurace JDO vypadat například takto (srovnejte s příkladem z předchozího článku):

Properties properties = new Properties();
properties.setProperty(„javax.jdo.PersistenceManagerFactoryClass“,
            „org.jpox.PersistenceManagerFactoryImpl“);
properties.setProperty(„javax.jdo.option.ConnectionDriverName“,
            „com.mysql.jdbc.Driver“);
properties.setProperty(„javax.jdo.option.ConnectionURL“,
            „jdbc:mysql://muj.server.com/mojedata“);
properties.setProperty(„javax.jdo.option.ConnectionUserName“,
            „login“);
properties.setProperty(„javax.jdo.option.ConnectionPassword“,
            „heslo“);
PersistenceManagerFactory pmfactory =
    JDOHelper.getPersistenceManagerFactory(properties);

Aby bylo možno aplikaci konfigurovat beze změny kódu, je možno hodnoty jednotlivých vlastností specifikovat odděleně v externím souboru vlastností. Namísto volání metody setProperty pak inicializujeme hodnoty vlastností z externího souboru pomocí volání properties.load(). Většina integrovaných vývojových prostředí pro Javu disponuje editorem souborů vlastností, který nám umožní pružně měnit konfiguraci celé implementace JDO.

Každá implementace JDO definuje další nastavitelné vlastnosti, které umožňují řídit pokročilé funkce příslušné implementace. Podrobný přehled bývá k dispozici v dokumentaci, k některým z nich se dostaneme dále.

Generování schématu databáze

Při konfiguraci JDO jsme předpokládali, že v databázovém serveru byla předem vytvořena databáze a uživatel, který k ní může přistupovat. Vytvoření schématu neboli struktury tabulek používaných pro uložení objektů je již úkolem implementace JDO. Většina implementací poskytuje dvě možnosti tvorby schématu:

  1. Automatická tvorba schématu – JDO implementace vytváří na serveru tabulky automaticky v okamžiku, kdy je třeba uložit některý persistentní objekt. Výhodou je, že při změně v perzistentních objektech není nutné upravovat strukturu databáze, změny se provedou automaticky.
  2. Manuální tvorba schématu – Schéma je vytvořeno speciálním nástrojem, který na základě definic tříd a metadat vygeneruje příslušné příkazy pro server. Tento přístup má menší režii při samotném běhu aplikace, neboť schéma je již vytvořeno předem.

Automatická tvorba schématu se ovládá opět pomocí vlastností předávaných objektu PersistenceManagerFactory. Nejedná se ovšem o standardní vlastnosti JDO, proto mají u každé implementace jiný název. Například u JPOX je třeba nastavit vlastnost org.jpox.AutoCreateSchema na hodnotu true, zatímco u TJDO se stejná vlastnost jmenuje com.triactive.jdo.autoCreateTables.

Nástroje pro ruční generování schématu se opět liší podle implementace. Například u JPOX spustíme generování schématu následujícím způsobem:

java -Djavax.jdo.option.ConnectionDriverName=com.mysql.jdbc.Driver
     -Djavax.jdo.option.ConnectionURL=jdbc:mysql://mujserver.com/data
     -Djavax.jdo.option.ConnectionUserName=login
     -Djavax.jdo.option.ConnectionPassword=password
     org.jpox.SchemaTool

Hodnoty jednotlivých vlastností předávaných přes parametr -D je samozřejmě nutno upravit podle použitého databázového serveru a jeho konfigurace.

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

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

Štítky: Články

Mohlo by vás také zajímat

Nejnovější

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *