Programmering

Objekt persistens og Java

Objektets holdbarhet, eller standhaftighet, er begrepet du ofte hører brukt i forbindelse med problemet med lagring av objekter i databaser. Persistens forventes å operere med transaksjonsintegritet, og som sådan er det underlagt strenge betingelser. (Se ressursdelen i denne artikkelen for mer informasjon om transaksjonsbehandling.) I motsetning til dette er språktjenester som tilbys gjennom standard språkbiblioteker og pakker ofte uten transaksjonsbegrensninger.

Som vi vil se i denne artikkelen, tyder bevis på at enkel Java-utholdenhet sannsynligvis vil stamme fra selve språket, mens sofistikert databasefunksjonalitet vil bli tilbudt av databaseleverandører.

Ingen gjenstander er en øy

I den virkelige verden finner du sjelden et objekt som mangler forhold til andre objekter. Objekter er komponenter i objektmodeller. Spørsmålet om objektets holdbarhet overskrider problemet med objektmodellens holdbarhet og distribusjon når vi først observerer at objekter er sammenkoblet i kraft av deres forhold til hverandre.

Den relasjonelle tilnærmingen til datalagring har en tendens til å samle data etter type. Rader i en tabell representerer det fysiske aggregatet av objekter av samme type på disken. Forholdet mellom objekter blir deretter representert av nøkler som deles på tvers av mange tabeller. Selv om relasjonsdatabaser gjennom databaseorganisering noen ganger tillater at tabeller som sannsynligvis vil bli brukt sammen, blir samlokalisert (eller gruppert) i den samme logiske partisjonen, for eksempel et databasesegment, har de ingen mekanisme for å lagre objektrelasjoner i databasen. Derfor, for å konstruere en objektmodell, konstrueres disse forholdene fra de eksisterende nøklene i løpetid i en prosess referert til som bordet blir med. Dette er den samme kjente egenskapen til relasjonsdatabasene som kalles datauavhengighet. Nesten alle varianter av objektdatabaser tilbyr en eller annen mekanisme for å forbedre ytelsen til et system som involverer komplekse objektrelasjoner i forhold til tradisjonelle relasjonsdatabaser.

For å søke eller navigere?

Når vi lagrer objekter på disken, står vi overfor valget av samlokalisering av relaterte objekter for bedre å imøtekomme navigasjonstilgang, eller for å lagre objekter i tabellignende samlinger som samler objekter etter type for å lette predikatbasert tilgang (spørringer), eller begge deler . Samlokaliseringen av objekter i vedvarende lagring er et område der relasjonelle og objektorienterte databaser er vidt forskjellige. Valget av spørringsspråk er et annet område å vurdere. Structured Query Language (SQL) og utvidelser av det har gitt relasjonssystemer en predikatbasert tilgangsmekanisme. Object Query Language (OQL) er en objektvariant av SQL, standardisert av ODMG, men støtte for dette språket er foreløpig lite. Polymorfe metoder gir enestående eleganse i å konstruere en semantisk forespørsel om en samling objekter. Tenk deg for eksempel en polymorf oppførsel for konto kalt erInGoodStanding. Det kan returnere boolsk sant for alle kontoer med god anseelse, og ellers falskt. Tenk deg elegansen ved å spørre samlingen av kontoer, hvor inGoodStanding implementeres annerledes basert på forretningsregler, for alle kontoer med god anseelse. Det kan se ut som:

setOfGoodCustomers = setOfAccounts.query (account.inGoodStanding ());

Mens flere av de eksisterende objektdatabasene er i stand til å behandle en slik spørringsstil i C ++ og Smalltalk, er det vanskelig for dem å gjøre det for større (for eksempel 500+ gigabyte) samlinger og mer komplekse spørreuttrykk. Flere av de relasjonelle databaseselskapene, som Oracle og Informix, vil snart tilby annen SQL-basert syntaks for å oppnå det samme resultatet.

Utholdenhet og type

En objektorientert språkentusiast vil si at utholdenhet og type er ortogonale egenskaper til et objekt; dvs. vedvarende og forbigående gjenstander av samme type kan være identiske fordi den ene egenskapen ikke skal påvirke den andre. Den alternative oppfatningen hevder at utholdenhet er en oppførsel som bare støttes av vedvarende objekter, og at visse atferd bare kan gjelde for vedvarende objekter. Sistnevnte tilnærming krever metoder som instruerer vedvarende objekter om å lagre og hente seg fra vedvarende lagring, mens førstnevnte gir applikasjonen en sømløs oversikt over hele objektmodellen - ofte ved å utvide det virtuelle minnesystemet.

Kanonisering og språkuavhengighet

Objekter av samme type på et språk skal lagres i vedvarende lagring med samme layout, uavhengig av rekkefølgen grensesnittene deres vises i. Prosessene for å transformere et objektoppsett til dette vanlige formatet er samlet kjent som kanonisering av objektrepresentasjon. I kompilerte språk med statisk skriving (ikke Java) skal objekter skrevet på samme språk, men kompilert under forskjellige systemer, være representert identisk i vedvarende lagring.

En utvidelse av kanonisering tar for seg språkuavhengig objektrepresentasjon. Hvis objekter kan representeres på en språkuavhengig måte, vil det være mulig for forskjellige representasjoner av det samme objektet å dele den samme vedvarende lagringen.

En mekanisme for å utføre denne oppgaven er å innføre et ekstra nivå av indireksjon gjennom et språk for grensesnittdefinisjon (IDL). Objektdatabasegrensesnitt kan lages gjennom IDL og tilhørende datastrukturer. Ulempen med IDL-stilbindinger er to ganger: For det første krever det ekstra innireksjonsnivået alltid et ekstra nivå av oversettelse, noe som påvirker systemets totale ytelse; for det andre begrenser det bruken av databasetjenester som er unike for bestemte leverandører og som kan være verdifulle for applikasjonsutviklere.

En lignende mekanisme er å støtte objekttjenester gjennom en utvidelse av SQL. Relasjonelle databaseleverandører og mindre objekt- / relasjonsleverandører er tilhengere av denne tilnærmingen; Det gjenstår imidlertid å se hvor vellykkede disse selskapene vil være med å utforme rammene for objektlagring.

Men spørsmålet gjenstår: Er objektets utholdenhet en del av objektets oppførsel, eller er det en ekstern tjeneste som tilbys til objekter via separate grensesnitt? Hva med samlinger av objekter og metoder for å spørre dem? Relasjonelle, utvidede relasjonelle og objekt / relasjonelle tilnærminger pleier å argumentere for et skille mellom språk, mens objektdatabaser - og selve Java-språket - ser utholdenhet som iboende for språket.

Innfødt Java-utholdenhet via serialisering

Objektserialisering er den Java-språkspesifikke mekanismen for lagring og henting av Java-objekter og primitiver til strømmer. Det er verdt å merke seg at selv om kommersielle tredjepartsbiblioteker for serialisering av C ++ - objekter har eksistert i noen tid, har C ++ aldri tilbudt en innfødt mekanisme for objektserialisering. Slik bruker du Java's serialisering:

// Skrive "foo" til en strøm (for eksempel en fil)

// Trinn 1. Opprett en utgangsstrøm

// det vil si opprette bøtte for å motta byte

FileOutputStream ut = ny FileOutputStream ("fooFile");

// Trinn 2. Opprett ObjectOutputStream

// det vil si lage en slange og sette hodet i bøtta

ObjectOutputStream os = ny ObjectOutputStream (ut)

// Trinn 3. Skriv en streng og et objekt til strømmen

// det vil si la bekken strømme inn i bøtta

os.writeObject ("foo");

os.writeObject (ny Foo ());

// Trinn 4. Skyll dataene til destinasjonen

os.flush ();

De Skrivobjekt metoden serialiserer foo og dens transitive lukking - det vil si alle objekter som kan refereres til fra foo i grafen. Innenfor strømmen eksisterer bare én kopi av det serielle objektet. Andre referanser til objektene lagres som objekthåndtak for å spare plass og unngå sirkulære referanser. Det serielle objektet starter med klassen etterfulgt av feltene i hver klasse i arvshierarkiet.

// Lesing av et objekt fra en strøm

// Trinn 1. Opprett en inngangsstrøm

FileInputStream in = ny FileInputStream ("fooFile");

// Trinn 2. Opprett en objektinngangsstrøm

ObjectInputStream ins = ny ObjectInputStream (in);

// Trinn 3. Fikk vite hva du leser

String fooString = (String) ins.readObject ();

Foo foo = (Foo) s.readObject ();

Objektserialisering og sikkerhet

Som standard skriver og leser ikke-statiske og ikke-forbigående felt fra strømmen. Denne egenskapen kan brukes som en sikkerhetsmekanisme ved å erklære felt som kanskje ikke serialiseres som private forbigående. Hvis en klasse kanskje ikke blir seriell i det hele tatt, writeObject og readObject metoder skal implementeres for å kaste NoAccessException.

Persistens med transaksjonsintegritet: Introduksjon av JDBC

Modelleret etter X / Open's SQL CLI (Client Level Interface) og Microsofts ODBC-abstraksjoner, tar Java-databasekonnektivitet (JDBC) sikte på å gi en databasetilkoblingsmekanisme som er uavhengig av det underliggende databasestyringssystemet (DBMS). For å bli JDBC-kompatibel, drivere trenger å støtte minst ANSI SQL-2 API på inngangsnivå, som gir tredjeparts verktøyleverandører og applikasjoner nok fleksibilitet for databasetilgang.

JDBC er designet for å være i samsvar med resten av Java-systemet. Leverandører oppfordres til å skrive et API som er sterkere skrevet enn ODBC, noe som gir større statisk typekontroll ved kompileringstidspunktet.

Her er en beskrivelse av de viktigste JDBC-grensesnittene:

  • java.sql.Driver.Manager håndterer lasting av drivere og gir støtte for nye databaseforbindelser.

  • java.sql.Tilkobling representerer en forbindelse til en bestemt database.

  • java.sql. uttalelse fungerer som en container for å utføre en SQL-setning på en gitt forbindelse.

  • java.sql.ResultSet kontrollerer tilgang til resultatsettet.

Du kan implementere en JDBC-driver på flere måter. Det enkleste ville være å bygge sjåføren som en bro til ODBC. Denne tilnærmingen er best egnet for verktøy og applikasjoner som ikke krever høy ytelse. En mer utvidbar design vil introdusere et ekstra nivå av indireksjon til DBMS-serveren ved å tilby en JDBC-nettverksdriver som får tilgang til DBMS-serveren gjennom en publisert protokoll. Den mest effektive driveren ville imidlertid få direkte tilgang til DBMS proprietære API.

Objektdatabaser og Java-utholdenhet

En rekke pågående prosjekter i bransjen tilbyr Java-utholdenhet på objektnivå. Imidlertid, når dette skrives, er Object Designs PSE (Persistent Storage Engine) og PSE Pro de eneste fullt Java-baserte, objektorienterte databasepakkene som er tilgjengelige (i det minste jeg er klar over). Sjekk ressursdelen for mer informasjon om PSE og PSE Pro.

Java-utvikling har ført til et avvik fra det tradisjonelle utviklingsparadigmet for programvareleverandører, spesielt i tidslinjen for utviklingsprosessen. For eksempel er PSE og PSE Pro utviklet i et heterogent miljø. Og fordi det ikke er et koblingstrinn i utviklingsprosessen, har utviklere vært i stand til å lage forskjellige funksjonelle komponenter uavhengig av hverandre, noe som resulterer i bedre, mer pålitelig objektorientert kode.

PSE Pro har muligheten til å gjenopprette en ødelagt database fra en avbrutt transaksjon forårsaket av systemfeil. Klassene som er ansvarlige for denne ekstra funksjonaliteten er ikke til stede i PSE-utgivelsen. Det er ingen andre forskjeller mellom de to produktene. Disse produktene er det vi kaller "dribbleware" - programvareutgivelser som forbedrer funksjonaliteten ved å koble til nye komponenter. I en ikke så fjern fremtid ville konseptet med å kjøpe stor, monolitisk programvare bli en saga blott. Det nye forretningsmiljøet i cyberspace, sammen med Java-databehandling, gjør det mulig for brukere å kjøpe bare de delene av objektmodellen (objektgrafen) de trenger, noe som resulterer i mer kompakte sluttprodukter.

PSE arbeider ved etterbehandling og merking av klassefiler etter at de er opprettet av utvikleren. Fra PSEs synspunkt er klasser i en objektgraf enten vedvarende eller vedvarende klar. Vedvarende klasser kan vedvare selv mens vedvarende klasser kan operere på vedvarende gjenstander. Dette skillet er nødvendig fordi utholdenhet kanskje ikke er en ønsket oppførsel for visse klasser. Klassefilen etterbehandler gjør følgende endringer i klassene:

$config[zx-auto] not found$config[zx-overlay] not found