Programování

Zachovat data pomocí Java Data Objects, část 1

„Všechno by mělo být co nejjednodušší, ale ne jednodušší.“

Albert Einstein

Potřeba přetrvávat data vytvořená za běhu je stejně stará jako výpočetní technika. Když se objektově orientované programování stalo všudypřítomným, objevila se potřeba ukládat objektově orientovaná data. V současné době většina moderních netriviálních aplikací používá k modelování domén aplikací objektově orientované paradigma. Naproti tomu je trh s databázemi více rozdělen. Většina databázových systémů používá relační model, ale objektová úložiště dat se v mnoha aplikacích ukazují jako nezbytná. Navíc máme také starší systémy, ke kterým často potřebujeme rozhraní.

Tento článek popisuje problémy spojené s perzistencí dat v prostředích transakčního middlewaru, jako je J2EE (Java 2 Platform, Enterprise Edition), a ukazuje, jak Java Data Objects (JDO) řeší některé z těchto problémů. Tento článek poskytuje přehled, nikoli podrobný kurz, a je psán z hlediska vývojáře aplikací, nikoli návrháře implementace JDO.

Přečtěte si celou sérii o Java Data Objects:

  • Část 1. Uchopte kvality za ideální vrstvou vytrvalosti
  • Část 2. Sun JDO vs. Castor JDO

Tento článek by si měli přečíst ti vývojáři, designéři a architekti J2EE, kteří pracují na systémech, které musí ukládat data v relačních nebo objektových databázích nebo na jiných úložných médiích. Předpokládám, že máte základní znalosti jazyka Java a určitou znalost objektově-relačních problémů a terminologie.

Transparentní vytrvalost: Proč se obtěžovat?

Více než deset let nepřetržitých pokusů o přemostění objektově orientovaného běhu a vytrvalosti ukazuje na několik důležitých pozorování (uvedených v pořadí podle důležitosti):

  1. Abstrahování od jakýchkoli údajů o vytrvalosti a mít čisté, jednoduché, objektově orientované API k provádění ukládání dat je prvořadé. Nechceme zpracovávat podrobnosti o perzistenci a interní reprezentaci dat v úložištích dat, ať už relačních, objektově založených, nebo něco jiného. Proč bychom se měli zabývat nízkoúrovňovými konstrukcemi modelu úložiště dat, jako jsou řádky a sloupce, a neustále je překládat sem a tam? Místo toho se musíme soustředit na tu komplexní aplikaci, kterou jsme museli doručit do včerejška.
  2. Chceme s našimi datovými úložišti použít přístup typu plug-and-play: Chceme používat různé poskytovatele / implementace beze změny řádku zdrojového kódu aplikace - a možná bez úpravy více než několika řádků v příslušném konfiguračním souboru ( s). Jinými slovy, potřebujeme průmyslový standard pro přístup k datům na základě objektů Java, který hraje roli podobnou té, kterou JDBC (Java Database Connectivity) hraje jako průmyslový standard pro přístup k datům založeným na SQL.
  3. Chceme použít přístup plug-and-play s různými paradigmaty databáze - to znamená, že chceme přejít z relační databáze na objektově orientovanou s minimálními změnami kódu aplikace. Ačkoli je hezké mít, v praxi tato schopnost často není vyžadována.

    Jeden komentář zde: Zatímco relační databáze se těší největší přítomnosti na trhu zdaleka, poskytování jednotného perzistence API a umožnění poskytovatelům datových úložišť soutěžit o silné stránky implementace má smysl, bez ohledu na paradigma, které tito poskytovatelé používají. Tento přístup může nakonec pomoci vyrovnat podmínky mezi dvěma dominantními skupinami dodavatelů databází: dobře zakořeněný relační tábor a objektově orientovaný tábor bojující za podíl na trhu.

Tři výše uvedené objevy nás vedou k definování a vytrvalostní vrstva, rámec, který poskytuje vysoce kvalitní rozhraní Java API pro objekty a vztahy, které přežije životnost modulu runtime environment (JVM). Takový rámec musí mít následující vlastnosti:

  • Jednoduchost
  • Minimální vniknutí
  • Transparentnost, což znamená, že rámec skrývá implementaci úložiště dat
  • Konzistentní, stručné API pro ukládání / načítání / aktualizaci objektů
  • Podpora transakcí, což znamená, že rámec definuje transakční sémantiku spojenou s trvalými objekty
  • Podpora pro spravovaná (např. Aplikační serverová) i nespravovaná (samostatná) prostředí
  • Podpora nezbytných doplňků, jako je ukládání do mezipaměti, dotazy, generování primárního klíče a nástroje pro mapování
  • Přiměřené licenční poplatky - není to technický požadavek, ale všichni víme, že špatná ekonomika může zkazit vynikající projekt

Většinu výše uvedených kvalit podrobně popisuji v následujících částech.

Jednoduchost

Míra jednoduchosti vysoko na mém seznamu požadovaných vlastností jakéhokoli softwarového rámce nebo knihovny (viz úvodní citace tohoto článku). Vývoj distribuovaných aplikací je již dostatečně tvrdý a mnoho softwarových projektů selhává kvůli špatné složitosti (a rozšířením rizika) řízení. Jednoduchý není synonymem pro zjednodušující; software by měl mít všechny potřebné funkce, které vývojářům umožňují vykonávat svou práci.

Minimální vniknutí

Každý trvalý úložný systém zavádí do kódu aplikace určité množství narušení. Ideální vrstva perzistence by měla minimalizovat narušení, aby se dosáhlo lepší modularity a tedy funkce plug-and-play.

Pro účely tohoto článku definuji narušení jako:

  • Množství kódu specifického pro perzistenci roztříštěného napříč kódem aplikace
  • Potřeba upravit váš objektový model aplikace buď tím, že budete muset implementovat nějaké perzistenční rozhraní - například Vytrvalý nebo podobně - nebo dodatečným zpracováním vygenerovaného kódu

Vniknutí se vztahuje také na objektově orientované databázové systémy, ai když je zde obvykle menší problém ve srovnání s úložišti relačních dat, může se významně lišit u prodejců ODBMS (objektově orientovaný systém správy databáze).

Průhlednost

Koncept transparentnosti trvalé vrstvy je docela jednoduchý: aplikace používá stejné API bez ohledu na typ úložiště dat (průhlednost typu datového úložiště) nebo dodavatele datového úložiště (průhlednost datového úložiště-dodavatele). Transparentnost výrazně zjednodušuje aplikace a zlepšuje jejich udržovatelnost skrýváním podrobností implementace datového úložiště v maximální možné míře. Zejména pro převládající úložiště relačních dat, na rozdíl od JDBC, nemusíte pevně kódovat příkazy SQL nebo názvy sloupců, ani si pamatovat pořadí sloupců vrácené dotazem. Ve skutečnosti nepotřebujete znát SQL nebo relační algebru, protože jsou příliš specifické pro implementaci. Transparentnost je možná nejdůležitější vlastností vrstvy perzistence.

Konzistentní, jednoduché API

Rozhraní API vrstvy perzistence se scvrkává na relativně malou sadu operací:

  • Základní operace CRUD (vytváření, čtení, aktualizace, mazání) na prvotřídních objektech
  • Správa transakcí
  • Správa identit aplikačních a persistenčních objektů
  • Správa mezipaměti (tj. Osvěžující a vystěhování)
  • Vytváření a provádění dotazů

Příklad a Persistence Layer API:

 public void persist (Object obj); // Uložit obj do datového úložiště. veřejné zatížení objektu (třída c, objekt pK); // Číst obj s daným primárním klíčem. public void update (Object obj); // Aktualizace upraveného objektu obj. public void delete (Object obj); // Odstranit obj z databáze. hledání veřejné sbírky (Dotaz q); // Najděte objekty, které splňují podmínky našeho dotazu. 

Podpora transakcí

Dobrá vrstva stálosti potřebuje ke spuštění, potvrzení nebo vrácení transakce několik základních funkcí. Zde je příklad:

// Vymezení transakce (tx). public void startTx (); public void commitTx (); public void rollbackTx (); // Nakonec se rozhodnete udělat přechodný objekt přechodný. public void makeTransient (objekt o) 

Poznámka: Transakční rozhraní API pro vymezení transakcí se primárně používají v nespravovaných prostředích. Ve spravovaných prostředích tuto funkci předpokládá integrovaný správce transakcí.

Podpora spravovaných prostředí

Spravovaná prostředí, jako jsou aplikační servery J2EE, si u vývojářů oblíbila. Kdo chce dnes psát střední úrovně od nuly, když máme k dispozici vynikající aplikační servery? Slušná vrstva vytrvalosti by měla být schopna pracovat v jakémkoli kontejneru EJB (Enterprise JavaBean) aplikačního serveru a synchronizovat se s jeho službami, jako je JNDI (Java Naming and Directory Interface) a správa transakcí.

Dotazy

API by mělo být schopné vydávat libovolné dotazy pro vyhledávání dat. Mělo by zahrnovat flexibilní a výkonný, ale snadno použitelný jazyk - rozhraní API by mělo jako formální parametry dotazu používat objekty Java, nikoli tabulky SQL nebo jiné reprezentace datového úložiště.

Správa mezipaměti

Správa mezipaměti dokáže s výkonem aplikace zázraky. Zvuková vrstva perzistence by měla poskytovat úplné ukládání do mezipaměti dat a také příslušná rozhraní API pro nastavení požadovaného chování, jako jsou úrovně uzamčení, zásady vystěhování, líné načítání a podpora distribuovaného ukládání do mezipaměti.

Generování primárního klíče

Poskytování automatického generování identity pro data je jednou z nejběžnějších služeb persistence. Každá slušná vrstva perzistence by měla poskytovat generování identity s podporou všech hlavních algoritmů generování primárních klíčů. Generování primárního klíče je dobře prozkoumaný problém a existuje mnoho algoritmů primárního klíče.

Mapování, pouze pro relační databáze

U relačních databází vzniká problém s mapováním dat: potřeba překládat objekty do tabulek a překládat vztahy, jako jsou závislosti a odkazy, do dalších sloupců nebo tabulek. Jedná se o netriviální problém sám o sobě, zejména u komplexních objektových modelů. Téma objektově-relačního modelu neshoda impedance přesahuje rámec tohoto článku, ale je dobře zveřejněn. Další informace najdete v části Zdroje.

Následující seznam doplňků souvisejících s mapováním a / nebo relačními datovými úložišti není ve vrstvě perzistence vyžadován, ale výrazně usnadňuje život vývojáře:

  • Nástroj pro mapování GUI (grafické uživatelské rozhraní)
  • Generátory kódu: Autogenerace DDL (jazyk popisu dat) k vytvoření databázových tabulek nebo autogenerace kódu Java a mapovacích souborů z DDL
  • Generátory primárního klíče: Podpora více algoritmů generování klíčů, jako jsou UUID, HIGH-LOW a SEQUENCE
  • Podpora pro binární velké objekty (BLOBs) a znakové velké objekty (CLOBY)
  • Autoreferenční vztahy: Objekt typu Bar odkazování na jiný objekt typu Bar, například
  • Podpora surového SQL: Předávací dotazy SQL

Příklad

Následující fragment kódu ukazuje, jak používat rozhraní API persistence layer. Předpokládejme, že máme následující model domény: Společnost má jedno nebo více míst a každé umístění má jednoho nebo více uživatelů. Následuje příklad kódu aplikace:

PersistenceManager pm = PMFactory.initialize (..); Company co = new Company ("MyCompany"); Místo l1 = nové Místo1 („Boston“); Místo l2 = nové místo („New York“); // Vytváření uživatelů. Uživatel u1 = nový uživatel („Označit“); Uživatel u2 = nový uživatel („Tom“); Uživatel u3 = nový uživatel („Mary“); // Přidat uživatele. Uživatel může „patřit“ pouze jednomu místu. L1.addUser (u1); L1.addUser (u2); L2.addUser (u3); // Přidejte umístění do společnosti. co.addLocation (l1); co.addLocation (l2); // A nakonec uložte celý strom do databáze. pm.perist (c); 

V jiné relaci můžete vyhledat společnosti zaměstnávající uživatele Tom:

PersistenceManager pm = PMFactory.initialize (...) Collection companiesEmployingToms = pm.find ("company.location.user.name = 'Tom'"); 

Pro úložiště relačních dat musíte vytvořit další soubor mapování. Může to vypadat takto:

    Uživatel umístění společnosti 

O zbytek se stará vrstva perzistence, která zahrnuje následující:

  • Hledání skupin závislých objektů
  • Správa identity objektu aplikace
  • Správa trvalých identit objektů (primární klíče)
  • Zachování každého objektu v příslušném pořadí
  • Poskytování správy mezipaměti
  • Poskytnutí správného transakčního kontextu (nechceme, aby přetrvávala pouze část stromu objektů, že?)
  • Poskytování uživatelsky volitelných režimů uzamčení
$config[zx-auto] not found$config[zx-overlay] not found