Jedním z problémů, který je nutno řešit při ukládání javovských objektů do jakékoli databáze, je mapování datových typů. Java disponuje množinou jednak primitivních datových typů a jednak tříd definovaných v Java API, databázové systémy oproti tomu používají své vlastní datové typy, které se navíc u různých systémů mohou mírně lišit. Zajistit správné ukládání objektů s různými typy atributů do databáze je jedním z úkolů implementace JDO.

Datové typy

Z pohledu zpracování datových typů definuje specifikace JDO dvě základní skupiny objektů:

  • First-Class Object (FCO) je persistentní objekt, který má vlastní identitu, tedy lze se na něj odkazovat. Typicky jsou to všechny objekty uložené aplikací.
  • Second-Class Object (SCO) je objekt, který nemá vlastní identitu v rámci úložiště objektů a existuje pouze jako atribut nějakého FCO. Typicky je to například objekt typu Date, který je uložen jako hodnota atributu nějakého datového objektu.

Pokud se jako úložiště persistentních objektů používá relační databáze, pro každou třídu FCO se vytváří databázová tabulka, kde každému persistentnímu atributu odpovídá jeden sloupec. Další jeden nebo více sloupců je vytvořeno pro uložení identifikátoru objektu. Každý řádek tabulky pak odpovídá jednomu uloženému objektu. Naopak pro třídy SCO se nevytváří zvláštní tabulka, jsou uloženy v rámci objektu, jehož součást tvoří.

Při ukládání objektů do úložiště je podstatné, jaké datové typy u atributů persistentních tříd jsou podporovány implementací JDO, tedy které datové typy implementace umí uložit do databáze a znovu načíst. Podle specifikace JDO 1.0.1 musí každá implementace podporovat následující datové typy pro FCO i SCO objekty:

  • Primitivní datové typy: boolean, byte, short, int, long, char, float, double.
  • Základní třídy objeků: Boolean, Character, Byte, Short, Integer, Long, Float, Double, String, Locale, BigDecimal, BigInteger.
  • Kolekce: Collection, Set, HashSet.
  • Datum: java.util.Date.

Jako FCO musí být dále podporovány tyto třídy:

  • Všechny persistentní třídy (implementují rozhraní PersisetnceCapable, což je obvykle zajištěno rozšiřováním přeložených tříd).
  • Třída Object.
  • Všechna rozhraní (interface).

Volitelně mohou být podporovány i tyto třídy:

  • Pro FCO i SCO: pole, Map, List, ArrayList, HashMap, Hashtable, LinkedList, TreeMap, TreeSet, Vector.
  • Všechny PersistenceCapable objekty i jako SCO (povinná je podpora pouze pro FCO).

Například implementace JPOX podporuje téměř všechna rozšíření, takže je schopna pracovat se všemi hlavními datovými typy používanými v Javě.

Rozhraní

Standard JDO vyžaduje od implementace podporu rozhraní (interface) jako FCO objektů. Každá persistentní třída tedy může obsahovat persistentní položky typu rozhraní. Tyto položky pak mohou obsahovat objekty libovolné třídy, která impelementuje dané rozhraní. Mějme například následující rozhraní:

public interface Ridic
{
    /** Seznam řidičských oprávnění */
    String opravneni = „AB“;
}

Dále definujme nové třídy Autobusak, Bagrista a Traktorista, které jsou odvozeny od třídy Osoba a implementují rozhraní Ridic:

public class Autobusak extends Osoba implements Ridic
{
    …
}
public class Bagrista extends Osoba implements Ridic
{
    …
}
public class Traktorista extends Osoba implements Ridic
{
    …
}

Potom můžeme vytvořit třídu VyjezdVozidla, kde jedna z datových položek je právě typu rozhraní Ridic:

public class VyjezdVozidla
{
    private Ridic ridic;
    …
}

Nyní chceme ukládat výjezdy vozidel do databáze a potřebujeme tedy, aby třída VyjezdVozidla byla persistentní. V závislosti na použité implementaci JDO je často nutné přidat do metadat dodatečné informace, neboť z definice rozhraní není možno určit, které všechny třídy je implementují. Pro JPOX je proto nutno použít následující zápis:

<class name=“VyjezdVozidla“>
    <field name=“ridic“ persistence-modifier=“persistent“>
        <extension vendor-name=“jpox“
            key=“implementation-classes“
            value=“Autobusak, Bagrista, Traktorista“/>
    </field>
</class>

U ostatních implementací je použití rozhraní vždy nutno konzultovat s manuálem.

Kolekce

Standard JDO podporuje tři základní typy javovských kolekcí, Set, List a Map. Jednotlivé implementace JDO dále podporují různé implementace těchto kolekcí z balíku java.util jako například Vector, Hashtable, Stack, a další.

V případě kolekcí pracujeme nejméně se dvěma třídami objektů. První z nich je persistentní třída, která obsahuje persistentní vlastnost typu kolekce. Tuto třídu budeme nazývat vlastníkem kolekce. Kolekce v Javě jsou obecně tvořeny prvky typu Object, což umožňuje do kolekce vkládat současně objekty různých tříd. V případě persistentních objektů ovšem musíme řešit způsob ukládání obsahu kolekce a přístup k jednotlivým prvkům kolekce uloženým v úložišti objektů. Proto je nutné předem specifikovat třídu objektů, které budou tvořit prvky kolekce. Tuto třídu nazveme třídou prvků kolekce. Její specifikace je součástí metadat vlastníka kolekce.

Množiny a seznamy

Množina (třída implementující javovské rozhraní java.util.Set) je kolekce, která neobsahuje duplikáty prvků, takže pro žádné dva prvky (objekty) p1 a p2 v množině neplatí p1.equals(p2). Pořadí prvků v množině nehraje roli. Oproti tomu seznam (třída implementující rozhraní java.util.List) je uspořádaná kolekce objektů, tedy pořadí jednotlivých prvků je důležité a jeden prvek se v seznamu může vyskytovat vícekrát.

Pokud některý atribut persistentní třídy je typu kolekce (množina nebo seznam), stává se třída vlastníkem kolekce a v jejích metadatech je třeba zadat třídu prvků, které budou v kolekci obsaženy. Rozšiřme třídu osoba tak, že přidáme atribut adresy:

public class Osoba
{
    protected String jmeno;
    protected String prijmeni;
    protected int vek;
    protected Collection adresy;

}

Dále definujme třídu Adresa, která bude tvořit prvky kolekce (seznamu nebo množiny) adres:

public class Adresa
{
    protected String ulice;
    protected String mesto;
    protected String psc;
    public Adresa() { }
}

V metadatech třídy se kolekce projeví následujícím způsobem:

<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“/>
    <field name=“adresy“>
        <collection element-type=“Adresa“ embedded-element=“false“/>
    </field>
</class>

Element <collection> v metadatech označuje, že atribut třídy je kolekce. Atribut element-type udává třídu prvků kolekce (musí se také jednat o persistentní třídu). Atribut embedded-element může nabývat hodnot true nebo false a říká, zda budou prvky kolekce uloženy jako FCO (hodnota true) nebo SCO (vnořené, hodnota false). FCO jsou uloženy odděleně v úložišti objektů a každý má svoji vlastní identitu. SCO jsou uloženy v rámci objektu vlastnícího kolekci a nemají vlastní identitu v úložišti. Nelze k nim tedy přistupovat odděleně. Implicitní hodnota tohoto atributu je false.

Dále je samozřejmě nutné specifikovat metadata třídy Adresa, tedy parametry persistence pro atributy ulice, mesto a psc, což již probíhá zcela standardním způsobem.

Mapy

Mapa (třída implementující rozhraní java.util.Map) je třída přiřazující klíče k hodnotám, kde klíče i hodnoty jsou libovolné objekty. Každému klíči je přiřazena právě jedna hodnota. U mapy tedy pracujeme se třemi třídami – třídou vlastníka, třídou objektů, které tvoří hodnoty, a navíc s třídou objektů, které jsou použity jako klíč.

Použití map se příliš neliší od množin a seznamů, pouze v metadatech je třeba uvést třídu hodnot i klíčů, což zajistíme následujícím způsobem (například pro klíče typu String):

<class name=“Osoba“ identity-type=“datastore“>

    <field name=“adresy“>
        <map key-type=“java.lang.String“ value-type=“Adresa“/>
    </field>
</class>

Z příkladu je patrné, že třídu klíčů i hodnot udávají atributy key-type a value-type. Dále lze specifikovat, zda klíče a hodnoty budou samostatné objekty (FCO) nebo vnořené (SCO) pomocí atributů embedded-key a embedded-value. Význam a použití těchto atributů je obdobný jako v případě seznamů a množin, pokud nejsou zadány, implicitní hodnota je false.

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

Odpovědět