Programmēšana

Noturēt datus ar Java datu objektiem, 1. daļa

"Viss būtu jāpadara pēc iespējas vienkāršāks, bet ne vienkāršāks."

Alberts Einšteins

Nepieciešamība saglabāt izpildlaika laikā izveidotos datus ir tikpat veca kā skaitļošana. Nepieciešamība uzglabāt objektorientētus datus ir apgriezta, kad objektorientētā programmēšana kļūst izplatīta. Pašlaik lielākā daļa moderno, netradicionālo lietojumprogrammu izmanto objektu orientētu paradigmu lietojumprogrammu domēnu modelēšanai. Turpretī datubāzu tirgus ir vairāk sadalīts. Lielākā daļa datu bāzu sistēmu izmanto relāciju modeli, taču objektu datu krājumi izrādās neaizvietojami daudzās lietojumprogrammās. Turklāt mums ir arī mantotas sistēmas, ar kurām mums bieži jāsaskar.

Šajā rakstā ir identificētas problēmas, kas saistītas ar datu noturību darījumu starpprogrammatūras vidēs, piemēram, J2EE (Java 2 platforma, Enterprise Edition), un parādīts, kā Java Data Objects (JDO) atrisina dažas no šīm problēmām. Šajā rakstā ir sniegts pārskats, nevis detalizēta apmācība, un tas ir rakstīts no lietojumprogrammu izstrādātāja, nevis JDO ieviešanas dizainera viedokļa.

Lasiet visu Java datu objektu sēriju:

  • 1. daļa. Satveriet ideāla noturības slāņa īpašības
  • 2. daļa. Saule JDO pret Castor JDO

Tiem Java izstrādātājiem, dizaineriem un J2EE arhitektiem, kuri strādā pie sistēmām, kurām dati jāuzglabā relāciju vai objektu datu bāzēs vai citos datu nesējos, vajadzētu izlasīt šo rakstu. Es pieņemu, ka jums ir pamatzināšanas par Java un zināmas zināšanas par objektu un attiecību terminoloģiju.

Caurspīdīga neatlaidība: Kāpēc jāuztraucas?

Vairāk nekā desmit gadus ilgie nepārtraukti mēģinājumi pārvarēt objektorientēto izpildlaiku un neatlaidību norāda uz vairākiem svarīgiem novērojumiem (uzskaitīti pēc to nozīmīguma):

  1. Ir ārkārtīgi svarīgi noturēt visas noturības detaļas un iegūt tīru, vienkāršu, objektorientētu API, lai veiktu datu glabāšanu. Mēs nevēlamies apstrādāt noturības datus un iekšējo datu attēlojumu datu krātuvēs, neatkarīgi no tā, vai tie ir relāciju, objektu vai kaut kas cits. Kāpēc mums jārisina datu krātuves modeļa zema līmeņa konstrukcijas, piemēram, rindas un kolonnas, un tās nepārtraukti jātulko turp un atpakaļ? Tā vietā mums jākoncentrējas uz šo sarežģīto lietojumprogrammu, kuru mums vajadzēja piegādāt līdz vakardienai.
  2. Mēs vēlamies izmantot plug-and-play pieeju mūsu datu krātuvēs: mēs vēlamies izmantot dažādus nodrošinātājus / ieviešanas variantus, nemainot lietojumprogrammas avota koda rindu - un, iespējams, nemainot vairāk nekā dažas rindas attiecīgajā konfigurācijas failā ( s). Citiem vārdiem sakot, mums ir nepieciešams nozares standarts piekļuvei datiem, kuru pamatā ir Java objekti, un tam ir tāda pati loma kā JDBC (Java Database Connectivity) kā nozares standartam, lai piekļūtu SQL datiem.
  3. Mēs vēlamies izmantot plug-and-play pieeju ar dažādām datu bāzes paradigmām - tas ir, mēs vēlamies pāriet no relāciju datu bāzes uz objektorientētu ar minimālām izmaiņām lietojumprogrammas kodā. Lai gan patīkami, ka praksē šī spēja bieži nav nepieciešama.

    Viens komentārs šeit: Kaut arī relāciju datu bāzēm līdz šim ir vislielākā tirgus klātbūtne, ir jēga nodrošināt vienotu noturības API un ļaut datu krātuves pakalpojumu sniedzējiem konkurēt par ieviešanas priekšrocībām neatkarīgi no paradigmas, ko šie pakalpojumu sniedzēji izmanto. Šī pieeja galu galā varētu palīdzēt izlīdzināt konkurences apstākļus starp divām dominējošajām datubāzu piegādātāju grupām: labi iesakņojušos relāciju nometni un cīņai par tirgus daļu objektorientētu nometni.

Trīs iepriekš uzskaitītie atklājumi liek mums definēt a noturības slānis, ietvars, kas nodrošina augsta līmeņa Java API objektiem un attiecībām, lai pārspētu izpildlaika vides (JVM) kalpošanas laiku. Šādai sistēmai jābūt šādām īpašībām:

  • Vienkāršība
  • Minimāla ielaušanās
  • Pārredzamība, kas nozīmē, ka sistēma slēpj datu krātuves ieviešanu
  • Konsekventi, kodolīgi API objektu glabāšanai / izguvei / atjaunināšanai
  • Darījumu atbalsts, tas nozīmē, ka sistēma nosaka darījumu semantiku, kas saistīta ar pastāvīgiem objektiem
  • Atbalsts gan pārvaldītajām (piemēram, lietojumprogrammu serveriem), gan nepārvaldītajām (atsevišķajām) vidēm
  • Atbalsts nepieciešamajām ekstrām, piemēram, kešatmiņa, vaicājumi, primāro atslēgu ģenerēšana un kartēšanas rīki
  • Saprātīga maksa par licencēšanu - nav tehniska prasība, taču mēs visi zinām, ka slikta ekonomika var izraisīt lielisku projektu

Lielāko daļu iepriekš minēto īpašību es detalizēti aprakstīju nākamajās sadaļās.

Vienkāršība

Vienkāršības līmenis manā programmatūras ietvarā vai bibliotēkā nepieciešamo īpašību sarakstā ir augsts (skat. Šī raksta sākuma citātu). Izplatīto lietojumprogrammu izstrāde jau ir pietiekami sarežģīta, un daudzi programmatūras projekti neizdodas sliktas sarežģītības (un, attiecīgi, riska) pārvaldības dēļ. Vienkārši nav sinonīms vienkāršots; programmatūrai jābūt visām nepieciešamajām funkcijām, kas ļauj izstrādātājam veikt savu darbu.

Minimāla ielaušanās

Katra pastāvīgā uzglabāšanas sistēma ievieš noteiktu daudzumu ielaušanās lietojumprogrammas kodā. Ideālajam noturības slānim vajadzētu pēc iespējas samazināt ielaušanos, lai panāktu labāku modularitāti un līdz ar to plug-and-play funkcionalitāti.

Šī raksta izpratnē iejaukšanos es definēju kā:

  • Pastāvībai raksturīgā koda daudzums, kas izšļakstīts lietojumprogrammas kodā
  • Nepieciešamība modificēt lietojumprogrammas objekta modeli, vai nu ieviešot kādu noturības saskarni, piemēram, Noturīgs vai tamlīdzīgi - vai pēcapstrādājot ģenerēto kodu

Ielaušanās attiecas arī uz objektorientētām datu bāzu sistēmām, un, kaut arī parasti tur ir mazāk problēmu salīdzinājumā ar relāciju datu krātuvēm, tas var ievērojami atšķirties starp ODBMS (objektorientētās datu bāzes pārvaldības sistēmas) piegādātājiem.

Pārredzamība

Pastāvīgā slāņa caurspīdīguma koncepcija ir diezgan vienkārša: lietojumprogramma izmanto to pašu API neatkarīgi no datu krātuves veida (datu krātuves veida pārredzamība) vai datu krātuves pārdevēja (datu krātuves pārdevēja pārredzamība). Pārredzamība ievērojami vienkāršo lietojumprogrammas un uzlabo to uzturēšanu, maksimāli slēpjot datu krātuves ieviešanas detaļas. Jo īpaši attiecībā uz izplatītajiem relāciju datu krājumiem, atšķirībā no JDBC, jums nav nepieciešams kodēt SQL priekšrakstus vai kolonnu nosaukumus vai atcerēties kolonnu secību, ko atdod vaicājums. Patiesībā jums nav jāzina SQL vai relāciju algebra, jo tie ir pārāk specifiski ieviešanai. Pārredzamība, iespējams, ir noturības slāņa vissvarīgākā iezīme.

Konsekventa, vienkārša API

Noturības slāņa API ir samērā mazs darbību kopums:

  • CRUD (radīšana, lasīšana, atjaunināšana, dzēšana) elementāras darbības ar pirmās klases objektiem
  • Darījumu vadība
  • Lietojumprogrammu un noturības objektu identitāšu pārvaldība
  • Kešatmiņas pārvaldība (t.i., atsvaidzināšana un izlikšana)
  • Vaicājumu izveidošana un izpilde

A piemērs Noturības slānis API:

 public void persist (Object obj); // Saglabāt obj datu krātuvē. publiskā objekta slodze (c klase, objekta pK); // Lasiet obj ar norādīto primāro atslēgu. public void update (Object obj); // Atjauniniet modificēto objektu obj. public void delete (Object obj); // Dzēst obj no datu bāzes. publisks kolekcijas atradums (vaicājums q); // Atrodiet objektus, kas atbilst mūsu vaicājuma nosacījumiem. 

Darījumu atbalsts

Labam noturības slānim ir nepieciešamas vairākas pamatfunkcijas, lai sāktu, izdarītu vai atceltu darījumu. Šeit ir piemērs:

// Darījuma (tx) norobežošana. public void startTx (); publiska anulēšana sitoutTx (); public void rollbackTx (); // Galu galā izvēlieties noturīgu objektu padarīt pārejošu. public void makeTransient (objekts o) 

Piezīme: Darījumu norobežošanas API galvenokārt tiek izmantoti nepārvaldītās vidēs. Pārvaldītās vidēs iebūvētais darījumu pārvaldnieks bieži uzņemas šo funkcionalitāti.

Pārvaldītās vides atbalsts

Pārvaldītās vides, piemēram, J2EE lietojumprogrammu serveri, ir kļuvušas populārākas izstrādātāju vidū. Kurš mūsdienās vēlas rakstīt vidējos līmeņus no sākuma, kad mums ir pieejami lieliski lietojumprogrammu serveri? Pienācīgam noturības slānim jāspēj darboties jebkura galvenā lietojumprogrammu servera EJB (Enterprise JavaBean) konteinerā un sinhronizēt ar tā pakalpojumiem, piemēram, JNDI (Java Naming and Directory Interface) un darījumu pārvaldību.

Vaicājumi

API vajadzētu būt iespējai izdot patvaļīgus vaicājumus datu meklēšanai. Tajā jāiekļauj elastīga un jaudīga, bet viegli lietojama valoda - API kā formālie vaicājuma parametri jāizmanto Java objekti, nevis SQL tabulas vai citi datu krātuves attēlojumi.

Kešatmiņas pārvaldība

Kešatmiņas pārvaldība var radīt brīnumus par lietojumprogrammas veiktspēju. Skaņas noturības slānim jānodrošina pilna datu kešatmiņa, kā arī atbilstoši API, lai iestatītu vēlamo darbību, piemēram, bloķēšanas līmeņus, izlikšanas politikas, slinku ielādi un sadalītu kešatmiņas atbalstu.

Galvenās atslēgas ģenerēšana

Automātiskās identitātes ģenerēšanas nodrošināšana datiem ir viens no visizplatītākajiem noturības pakalpojumiem. Katram pienācīgam noturības slānim jānodrošina identitātes ģenerēšana ar atbalstu visiem galvenajiem primāro atslēgu ģenerēšanas algoritmiem. Primāro atslēgu ģenerēšana ir labi izpētīts jautājums, un pastāv daudzi primārās atslēgas algoritmi.

Kartēšana, tikai relāciju datu bāzēm

Izmantojot relāciju datu bāzes, rodas datu kartēšanas problēma: vajadzība objektus tulkot tabulās un attiecības, piemēram, atkarības un atsauces, tulkot papildu kolonnās vai tabulās. Tā pati par sevi ir nenozīmīga problēma, īpaši sarežģītu objektu modeļu gadījumā. Objektu-relāciju modeļa tēma pretestības neatbilstība pārsniedz šī raksta darbības jomu, bet tiek labi reklamēta. Plašāku informāciju skatiet sadaļā Resursi.

Šis noturības slānī nav nepieciešams šāds ar kartēšanu un / vai relāciju datu krātuvēm saistīto papildinājumu saraksts, taču tie ievērojami atvieglo izstrādātāja dzīvi:

  • GUI (grafiskā lietotāja saskarne) kartēšanas rīks
  • Kodu ģeneratori: DDL (datu apraksta valodas) automātiska ģenerēšana, lai izveidotu datu bāzes tabulas, vai Java koda un kartēšanas failu automātiska ģenerēšana no DDL
  • Galvenie atslēgu ģeneratori: Atbalstīt vairākus atslēgu ģenerēšanas algoritmus, piemēram, UUID, HIGH-LOW un SEQUENCE
  • Bināru lielu objektu (BLOB) un uz rakstzīmēm balstītu lielu objektu atbalsts (CLOBs)
  • Pašreferences attiecības: Tipa objekts Bārs atsauce uz citu tipa objektu Bārs, piemēram
  • Neapstrādāts SQL atbalsts: Pārejas SQL vaicājumi

Piemērs

Šis koda fragments parāda, kā izmantot noturības slāņa API. Pieņemsim, ka mums ir šāds domēna modelis: Uzņēmumam ir viena vai vairākas atrašanās vietas, un katrai atrašanās vietai ir viens vai vairāki lietotāji. Lietojumprogrammas koda piemērs varētu būt šāds:

PersistenceManager pm = PMFactory.inicialize (..); Company co = jauns uzņēmums ("MyCompany"); Atrašanās vieta l1 = jauna atrašanās vieta1 ("Boston"); Atrašanās vieta l2 = jauna atrašanās vieta ("Ņujorka"); // Izveidot lietotājus. Lietotājs u1 = jauns lietotājs ("Atzīmēt"); Lietotājs u2 = jauns lietotājs ("Toms"); Lietotājs u3 = jauns lietotājs ("Marija"); // Pievienojiet lietotājus. Lietotājs var "piederēt" tikai vienai atrašanās vietai. L1.addUser (u1); L1.addUser (u2); L2.addUser (u3); // Pievienojiet uzņēmumam atrašanās vietas. co.addLocation (l1); co.addLocation (l2); // Un visbeidzot, visu koku glabājiet datu bāzē. pm.turēt (c); 

Citā sesijā varat meklēt uzņēmumus, kas nodarbina lietotāju Toms:

PersistenceManager pm = PMFactory.initialize (...) Inkasācijas uzņēmumiEmployingToms = pm.find ("company.location.user.name = 'Tom'"); 

Relāciju datu krātuvēm jāizveido papildu kartēšanas fails. Tas varētu izskatīties šādi:

    Uzņēmuma atrašanās vietas lietotājs 

Noturības slānis rūpējas par pārējo, kas ietver:

  • Atkarīgo objektu grupu atrašana
  • Lietojumprogrammas objekta identitātes pārvaldība
  • Pastāvīgo objektu identitāšu (primāro atslēgu) pārvaldība
  • Katra objekta noturēšana atbilstošā secībā
  • Kešatmiņas pārvaldības nodrošināšana
  • Pareiza darījumu konteksta nodrošināšana (vai mēs nevēlamies, lai saglabātu tikai daļu objekta koka?)
  • Nodrošinot lietotāja izvēlētus bloķēšanas režīmus
$config[zx-auto] not found$config[zx-overlay] not found