Databaser med objekt i stället för tabeller =========================================== Tue Feb 24 13:51:17 CET 2015 Egentligen: Databaser med objekt i stället för rader i tabeller Databaser med klasser i stället för tabeller Bakgrund -------- 1970-talet: Relationsdatabaser uppfanns 1980-talet: Relationsdatabaser blev dominerande På 1990-talet när objektorientering började dominera i programmering: 1. Man kanske skulle ha objekt i databaserna också? 2. Objekten från programmet behöver lagras persistent! Traditionellt: Databasen först, med tabeller Nu blev det ofta: Programmet först, med klasser och objekt Sen: Spara objekten i en relationsdatabas - impedance mismatch Objektorienterade databaser?! Nej, det blev översättning i stället, bland annat ORM MEN o-o db i en del specialiserade tillämpningar Det där med tillämpningar ------------------------- ("MEN o-o db i en del specialiserade tillämpningar") RDBMS bra för: * Många, enkla data * Många, enkla, korta transaktioner * Höga krav på säkerhet och konstistens Ex: Bankkonton! RDBMS inte så bra för: * Komplexa data, få instanser * Kanske nya, specialiserade datatyper, och index * Få, komplexa, långa transaktioner * Lägre krav på säkerhet och konstistens Ex: CAD! Likheter mellan objektorientering och relationsmodellen ------------------------------------------------------- Ett objektorienterat språk (C++/Java/C#): class Punkt { int x; int y; }; int main(void) { Punkt p1 = { 7, 17 }; Punkt p2 = { -3, 2 }; Punkt p3 = { -3, 2 }; } Eller en vanlig relationsdatabashanterare (RDBMS) med SQL: CREATE TABLE Punkter (x INTEGER, y INTEGER); INSERT INTO Punkter (x, y) VALUES (7, 17); INSERT INTO Punkter (x, y) VALUES (-3, 2); INSERT INTO Punkter (x, y) VALUES (-3, 2); Skillnader ---------- 1. Det ena är ett program i primärminne och det andra en databas (duh!): persistens, deklarativt frågespråk, transaktioner... 2. Objektidentitet, Objektidentifierare (OID:er) 3. Extent: SELECT * FROM Punkter; 4. Beteende (dvs: metoder/funktioner) 5. Arv, polymorfism 6. Skydd (private/public/...) 7. Deklarativt frågespråk!!! Två sorter av databaser med objekt, kan man säga ------------------------------------------------ 1. ODB, objektdatabas = har klasser, arv, objekt och (ibland) metoder (tidigare: objektorienterade databaser, ibland också: första generationens objektorienterade databaser) Ungefär: Ta ett oo-språk (som C++) och lägg till db-egenskaper ODBMS Men: dåliga databasegenskaper (frågespråk, transaktioner, ...) 2. ORDB, Objekt-relationella databaser (ibland också: andra generationens objektorienterade databaser) Ungefär: Ta en databashanterare och lägg till oo-egenskaper ORDBMS Och två sorter ORDBMS också: 2A. Vanlig RDBMS och lägg till objektorientering 2B. Helt nytt system (kanske liknar SQL lite, men inte kompatibelt) Vi ska först prata om ORDB, för de är mest "databasiga" 2A. SQL-99-standarden försökte lägga till OO till vanlig SQL ------------------------------------------------------------ Vanlig SQL: CREATE TABLE Punkter (x INTEGER, y INTEGER); SQL med användardefinierade typer (UDT), dvs klasser och objekt: CREATE TYPE Punkt AS (x INTEGER, y INTEGER); -- Olika! Oracle: CREATE TYPE Punkt AS OBJECT (x INTEGER, y INTEGER); CREATE TABLE Punkter (ID INTEGER, punkten Punkt); CREATE TABLE Punkter OF Punkt; CREATE TYPE Linje AS (p1 Punkt, p2 Punkt); CREATE TYPE BredLinje UNDER Linje AS (bredd INTEGER); 2B. Amos = helt nytt system, liknar men inte kompatibelt med vanlig SQL ----------------------------------------------------------------------- create type Apple properties (farg charstring, vikt integer); create Apple (farg, vikt) instances ('rott', 1.0), ('gront', 2.3); select farg(a) from Apple a; select farg(a), vikt(a) from Apple a; *** Än så länge väldigt SQL-igt. *** select a.farg, a.namn from Apple as a; *** Men: select a from Apple a; create Apple (farg, vikt) instances :a1 ('rott', 1.4), :a2 ('rott', 1.0); select :a1; select farg(:a1); :a1; farg(:a1); -- Nu finns det två likadana äpplen: select farg(a), vikt(a) from Apple a; select a from Apple a; create type Mask properties (namn charstring, langd real, bostad Apple); create Mask (namn, langd, bostad) instances ('Max', 1.0, :a1), ('Mats', 2.0, :a1); create Mask (namn, langd, bostad) instances :m1 ('Marcus', 1.0, :a2); select namn(m) from Mask m; select namn(m), langd(m), bostad(m) from Mask m; select namn(m), langd(m), farg(bostad(m)) from Mask m; *** Frågor som använder flera tabeller, jag menar klasser/extents select farg(a) from Apple a, Mask m where namn(m) = 'Max' and bostad(m) = a; select namn(m) from Apple a, Mask m where bostad(m) = a and farg(a) = 'rott'; select namn(m) from Mask m where farg(bostad(m)) = 'rott'; *** Spara i en variabel: select m into :max from Mask m where namn(m) = 'Max'; *** Aggregatfunktioner... count(select m from Mask m); sum(select m from Mask m); sum(select langd(m) from Mask m); avg(select langd(m) from Mask m); max(select langd(m) from Mask m); select farg(a), count(a) from Apple a group by farg(a); select farg(a), count(m) from Apple a, Mask m where bostad(m) = a group by farg(a); select a, count(m) from Apple a, Mask m where bostad(m) = a group by a; *** Nu ska vi göra motsatsen till bostad... bostad(:m1); select m from Mask m where bostad(m) = :a1; create function maskar (Apple a) -> Mask as select m from Mask m where bostad(m) = a; maskar(:a1); maskar(bostad(:max)); namn(maskar(bostad(:max))); *** Lägg till fler properties ("attribut", "egenskaper", "medlemsvariabler"): create function bredd (Mask) -> integer as stored; create function favorit (Mask) -> Apple as stored; create Mask (namn, langd, bostad, bredd, favorit) instances :m2 ('Mart', 1.0, :a2, 4, :a1); select bredd(m) from Mask m; select m, bredd(m) from Mask m; bredd(:m1); set bredd(:m1) = 2; bredd(:m1); select m, bredd(m) from Mask m; *** Men riktig objektorientering kräver arv och klasshierarkier! create type Djur properties (namn charstring, vikt real); create type Katt under Djur properties (mjauighet integer); create type Hund under Djur; create Katt (namn, vikt, mjauighet) instances :pelle ('Pelle', 2, 4); create Katt (namn, vikt, mjauighet) instances :maja ('Maja', 3, 5); create Hund (namn, vikt) instances ('Fido', 25); create Djur (namn, vikt) instances ('Kaa', 25); select k from Katt k; select namn(k) from Katt k; select namn(d) from Djur d; create type Mus under Djur properties (pipighet integer, uppaten_av Katt); create Mus (namn, vikt, uppaten_av) instances :m1 ('Musse Pigg', 0.02, :pelle); create Mus (namn, vikt, uppaten_av) instances :m2 ('Mimmi', 0.02, :maja); create Mus (namn, vikt, uppaten_av) instances :m3 ('Jerry', 0.02, :maja); uppaten_av(:m3); namn(uppaten_av(:m3)); create function uppatna (Katt k) -> Mus as select m from Mus m where uppaten_av(m) = k; uppatna(:maja); create function uppatna (Katt k) -> Mus m as select m where uppaten_av(m) = k; create function matvikt (Katt k) -> real as sum(vikt(uppatna(k))); matvikt(:maja); *** Funktioner som returnerar mängder create Katt (namn, vikt, mjauighet) instances :mans ('Mans', 3, 4); create Katt (namn, vikt, mjauighet) instances :bill ('Bill', 3, 4); create Katt (namn, vikt, mjauighet) instances :bull ('Bull', 4, 4); -- Nej, default för as stored är ETT värde som resultat! create function vanner (Katt k) -> Katt as stored; set vanner(:mans) = :bill; vanner(:mans); namn(vanner(:mans)); add vanner(:mans) = :bull; -- Error 50, Violating unique index: #[OID 1808 "P_KATT.VANNER->KATT"] -- Gör så här: create function vanner (Katt k) -> bag of Katt as stored; add vanner(:mans) = :bill; vanner(:mans); add vanner(:mans) = :bull; vanner(:mans); namn(vanner(:mans)); select namn(k) from Katt k where k in vanner(:mans); *** Funktioner som returnerar tupler: create function namnochvikt (Mus m) -> (charstring, real) as select namn(m), vikt(m); namnochvikt(:m1); *** Amos är en primärminnesdatabas! Spara och ladda: AmosQL 6> save 'foo2.dmp'; > ./amos2 foo2.dmp *** Skriv kommandon, eller klipp och klistra, eller från fil: AmosQL 1> < '../demo/tutorial.amosql'; *** Avsluta: exit; Objektdatabaser (ODB och inte ORDB) ----------------------------------- Kom ihåg: ta ett vanligt oo-programspråk (som C++) och lägg till persistens och annan db-funktionalitet Varför alls om det nu finns ORDB? Jo: Nya tillämpningar, som CAD Prestanda, ex: pekare, pointer swizzling Om man bara vill spara objekt kan en ORDBMS vara overkill