Programrendszerek Fejlesztése 14/4
A mai előadás tartalma Object serialization API ORM Perzisztencia Hibernate Bevezetés Architektúra Hello world Java File Mapping file Műveletek Konfiguráció Interfaces Mappelés (Kollekciók,Asszociációk,Leszármazások) Lekérdezések Optimalizálás(fetching and caching) Tesztelés
Perzisztencia Perzisztens objektum: a létrehozó program állapotától függetlenül is létezik Az objektumhierarchia egy részének kimentése/betöltése transzparens módon Fájlba (Object Serialization API) Kevésbé típusos (bájtsorozat) Objektum referenciák?Keresések?Biztonság? Objektum orientált adatbázisba Nem kellene átkonvertálni(objektumrelációk) Még nem elég hatékony az adatkezelés Nem népszerűek, kiforratlanok, nincs komplett implementáció Relációs adatbázisba Nagyon macerás a leképezés/átkonvertálás
Perzisztencia megvalósítása Közös bázisosztály Közös tulajdonságok egybegyűjtése Magunknak kell megírni a műveleteket Adatmanipulációs nyelv Kiterjeszti a nyelv szintaxisát Könnyen megvalósítható konkurens hozzáférés tranzakciók Sérül a hordozhatóság Hibrid megoldás (így a leghatékonyabb) A Java felépítése támogatja Wrapper osztályok, interfészek, adatfolyamok
Object serialization API Sokszor ez is megfelelő lehet, felesleges a Hibernate Java 1.1 java.io csomag része volt Bázisosztály alapú megoldás (Serializable interface) A referenciákat, kapcsolatokat is megőrzi Hierarchiák is menthetőek vele (fa,gráf, körkörös hivatkozások) Elmentés: Visszaolvasás:
Egy összetettebb példa
Obektum Relációs Leképezés (ORM) Objektumok automatikus és transzparens perzisztálása Java applikációból relációs adatbázisba Metadata segítségével írja le a kapcsolatot Konverzió 2 reprezentáció között A Metadata használata kevesebb idő mint kézzel megírni Egy ORM megoldás 4 része: API az objektumok CRUD (create/read/update/delete) műveleteire Lekérdező nyelv/API az osztályokra és azok adattagjaira vonatkozóan A leképezések definiálására egy keretrendszer „Piszkos adatok” ellenőrzése,laza kapcsolatok felderítése, egyéb optimalizáló funkciók megvalósítása
ORM megoldások Relációs – minden relációs modell szerint készül el Portabilitás? Karbantarthatóság? Tárolt eljárások? Könnyűsúlyú objektum leképezés Manuális leképezés Ismert tervezési minták rejtik el az SQL kódot Középsúlyú objektum leképezés Java alapú tervezés Az SQL fordítás időben generálódik Az objektumok gyorstárazva vannak
ORM megoldások Teljes objektum leképezés Fejlett objektum modellezés Kompozíció Öröklődés Laza, Buzgó betöltés Gyorsítótárazási stratégiák
ORM kérdések Hogyan nézzen ki a lementet objektum? Hogyan definiáljuk a leképezést leíró metaadatot? Hogyan képezzük le a származási hierarchiákat? Hogyan kezeljük az objektumok egyezőségét? Hogyan működik együtt az ORM az üzelti logikával futási időben? Mi az objektum életciklusa? Milyen aggregáló és rendező megoldásokat biztosít? Hogyan kezeljük az asszociációkat? Tranzakciók, párhuzamosság? Gyorsítótárazás?
ORM előnyök Fejlesztési ciklus Karbantarthatóság Sebesség Gyártó függetlenség
Hibernate ORMF (Object-Relational Mapping Frameworks) javahoz Híd az objektumorientált és a relációs szemlélet között Réteg a DB és az alkalmazás között A JEMS (JBoss Enterprise Middleware System) része Nyílt forráskód A leképezéssel kapcsolatos munka 95% át megspórolja Támogatja: OO perzisztens osztályok kezelése, asszociációt, öröklődést, polimorfizmust, kompozíciót, kollekciót
Hibernate Adat perzisztencia Relációs adatbázis Objektum vs. Rekord Tárolt eljárások Kézzel elkészített CRUD (create/read/update/delete)? SQL dialektusok (DDL/DML)? Objektum orientált adatbázisok? Object Relational Mapping – ORM Adatbázis kezelés Üzleti logika Serializáció Csak együtt kezelhető EJB 2.1 Objektum orientált adatbázisok ODMG - Nem népszerűek, kiforratlanok, nincs komplett implementáció
Paradigma ütközés/Granularitás
Paradigma ütközés/Granularitás Cím mint Külön tábla Külön oszlopok Külön típus User Defined Type – SQL kiterjesztés Oszlopként
Öröklődés/Polimorfizmus Hogyan tároljuk le? Polimorfikus lekérdezés?
Azonosítás Java SQL Referencia szerint (==) Érték szerint (Equals()) Elsődleges kulcs Mi legyen az? Név? Független kulcs?
Viszonyok Java M:M SQL 1:M 1:1
Navigáció Navigáció? Java egzakt SQL tetszőleges: Obejktum gráf bejárás x.d.g.getZ(); SQL tetszőleges: N+1 select problémája Minimalizálni kell a kérések számát – join Előre kell tudnunk mit akarunk lekérni User User join Billing details
Az eltérés ára 30% a programozó idejéből Bonyolult adatbázis absztrakciós réteg Projekt bukás lehet Az objektum réteg átalakítása, hogy megfeleljen a relációs rétegnek JDBC Strukturális kényszereket legalább háromszor meg kell adni (insert/update/delete) DAO
Architektúra
Architektúra
Architektúra
Fogalmak: SessionFactory (net.sf.hibernate.SessionFactory): Egy tárolóhely a lefordított mappingek részére. Innen érhető el a Session és a ConectionProvider. Tartalmazhat egy másod-szintű tárolót, ami a tranzakciók között használhatók fel processz vagy klaszterszinten. Session (net.sf.hibernate.Session): Ez egy rövid életű objektum, ami egy kapcsolatot reprezentál a tároló és az applikáció között, Magába foglal egy JDBC kapcsolatot. Innen kérhetőek el a tranzakció objetumok. Egy elsőszintű tároló tartozik hozzá a perzisztens objektumok számára. Amikor lépkedünk az objektum gráfban, vagy azonosító alapján keresünk, akkor van rá szükség. Perzisztens Objektumok: Szintén rövid életű objektumok, amelyek pontosan 1 session-el vannak kapcsolatban. Amikor a session bezárul, akkor szabaddá válnak és más applikációs szintek is használhatják. Tranziens Objektumok: Akkor beszélünk tranziens objektumokról amikor még sohasem voltak elmentve (tehát még nem voltak perzisztensek), így például ezeknek általában még nincs azonosítójuk.
Fogalmak: Tranzakció (net.sf.hibernate.Transaction): Rövid életű objektum ami egy atomi egységet valósít meg (tehát vagy teljesül az összes művelet vagy egyik sem, ha valamilyen hiba folytán nem teljesül akkor vissza kell tudni vonni a már bekövetkezett módosításokat). Egy session-ben több tranzakció is megvalósulhat. ConnectionProvider (net.sf.hibernate.connection.ConnectionProvider): Innen kérhetjük el a JDBC kapcsolatokat (itt a kapcsolatok tárolódnak is). Leválasztja az alkalmazást az alsóbb rétegektől (DataSource, DriverManager). A fejlesztő által implementálható. TransactionFactory (net.sf.hibernate.TransactionFactory): Itt kérhetjük el a tranzakció objektumokat. A fejlesztő által implementálható.
Hibernate- felépítés 3 rész: Java osztály Relációs adatbázisbeli táblák Leíró (descriptor) Definiálja a konverziós szabályokat A nyelvezete inkább java-centrikus 2 fajtája van: Xml file (*.xml.hbm kiterjesztés) Annotáció Sokan kézzel szerkesztik pedig XDoclet, Middlegen, AndroMDA.
Hello World – Java osztály Id Elsődleges kulcs az adatbázisban (hibernate automatikusan generálja) Getter-Setter minden adattaghoz (JavaBean) A java kódban nem kell Hibernate specifikus dolgokat használni! (nem „erőszakos”) Ugyanugy használjuk az osztályt ahogyan eddig: Message message = new Message("Hello World"); System.out.println( message.getText() ); Nem kell külön konténer ahogyan EJB-ben
Hello World - Leíró
Hello – World fő applikáció
Hello – World fő applikáció
Hello World – hibernate.cfg.xml
Hello World – hibernate.cfg.xml
A hibernate konfigurálása Mivel sok a változó azért széles a config paraméterlista A hibernate.propertiesből sok ötletet meríthetünk. 2 lehetőségünk van konfigurálásra: Progaramból állítjuk be a dolgokat A hibernate.cfg.xml A keresési útvonal gyökerébe kell tenni Egyben ki vannak gyűjtve a beállítások A hbm.xml –ek helyét is meg lehet adni benne A SessionFactory elkérése : SessionFactory sf = new Configuration().configure().buildSessionFactory(); Több konfig file-t is létrehozhatunk, majd később dinamikusan válogathatunk köztük: SessionFactory sf = new Configuration().configure("/my/package/catdb.cfg.xml") .buildSessionFactory();
Példák programból történő konfigurációra: Egy mappinf file regisztrálása: Configuration cfg = new Configuration().addResource("Message.hbm.xml"); Alternatív mód (az osztály regisztrálása) Configuration cfg = new Configuration() .addClass(helloWorld.Message.class); A Properties objektum használata: Properties props = new Properties(); ... Configuration cfg = new Configuration() .addClass(org.hibernate.auction.Item.class) .addClass(org.hibernate.auction.Bid.class) .setProperties(props);
Néhány egyéb config property: A legfontosabb JDBC kapcsolatért felelős property-k: Property name Purpose hibernate.connection.driver_ classjdbc driver class hibernate.connection.url jdbcURL hibernate.connection.username database user hibernate.connection.password database user password hibernate.connection.pool_size maximum number of pooled connections A Hibernate a kapcsolatokat olykor a Jndi ből kéri el : Property name Purpose hibernate.connection.datasource datasource JNDI name hibernate.jndi.url URL of the JNDI provider (optional) hibernate.jndi.class class of the JNDI InitialContextFactory (optional) hibernate.connection.username database user (optional) hibernate.connection.password database user password (optional)
Interfészek I. Session SessionFactory Configuration interface Könnyűsúlyú A Hibernate viszonyok nem szálbiztosak ! SessionFactory Nem könnyűsúlyú Szálak között megosztva használható Egy adatbázis/egy SessionFactory A második szintű gyorstár itt található Configuration interface Konfigfájlok helye, …. Transaction interface Nem kötelező használni – az adatbázis tranzakcióit használja
Interfészek II. Query, Criteria Callback interfaces Extension HQL/SQL lekérdezések futtatása Könnyűsúlyú Callback interfaces Lifecycle, Validate – CRUD műveletek Extension Primary key generator Sql dialect …
Alap konfiguráció Menedzselt környezet Nem menedzselt környezet Gyűjteményez (adatbázis kapcsolat, …) Jboss/GlassFish, … Nem menedzselt környezet Alap párhuzamosság kezelés (szál gyűjteményekkel) Tomcat/Jetty
Types Egy java típus egy vagy több oszlophoz rendel Saját típus Currency Calendar Byte[] … Saját típus UserType CompositeUserType
Alkalmazsáfejlesztés Gazdag domain model Csak a domainra vonatkozó kódot tartalmazza Aggodalom/Gond csorgás EJB interceptor Transzparens perzisztencia A kód független a perzisztencia típusától Kollekciók az interfészből származzanak ne az implementációból Argumentum nélküli konstruktor POJO Üzleti metódusok Tulajdonságok Automatizált perzisztencia
Követelmények Transzparens perzisztencia Kollekció típusok Nincs ősosztály, interfész követelmény Bárhol felhasználható POJO Üzleti logika Tulajdonságok Kollekció típusok A kollekció interfész szerint legyenek létrehozva (HashSet -> Set) Kötelező az üres konstruktor Java Bean elnevezési konvenciók
Alap tulajdonság és osztály leképezés Sok default megoldás <property name="description" column="DESCRIPTION" type="string"/> <property name="description" column="DESCRIPTION"/> Leszármaztatott értékek (csak select): <property name="totalIncludingTax" formula="TOTAL + TAX_RATE * TOTAL" type="big_decimal"/> <property name="averageBidAmount" formula="( select AVG(b.AMOUNT) from BID b ➾where b.ITEM_ID = ITEM_ID )"
Tulajdonság kezelő stratégiák Hozzáférő függvényen keresztül Közvetlenül <property name="name" column="NAME" type="string" access="field"/> Inster/Update kezelés insert="false" update="false"/>
Elnevezési konvenciók public class CENamingStrategy implements NamingStrategy { public String classToTableName(String className) { return tableName( StringHelper.unqualify(className).toUpperCase() ); } public String propertyToColumnName(String propertyName) { return propertyName.toUpperCase(); public String tableName(String tableName) { return "CE_" + tableName; public String columnName(String columnName) { return columnName; public String propertyToTableName(String className, String propertyName) { return classToTableName(className) + '_' + propertyToColumnName(propertyName);
Használata Configuration cfg = new Configuration(); cfg.setNamingStrategy( new CENamingStrategy() ); SessionFactory sessionFactory = cfg.configure().buildSessionFactory();
Objektum identitás Objektum azonosság Objektum egyenlőség Adatbázis egyenlőség <class name="Category" table="CATEGORY"> <id name="id" column="CATEGORY_ID" type="long"> <generator class="native"/> </id> ... </class> Sok kulcs generáló megoldás Sajátot is lehet írni
Objektum modellek Több objektum mint tábla Entitás Érték Komponensek
Származás leképezése Minden osztálynak egy tábla Egy tábla osztály hierarchiaként Alosztályonként tábla
Asszociációk Asszociáció Szülő gyermek viszony Egyirányú Kétirányú Láncolt műveletek
Perzisztencia
Perzisztencia menedzser CRUD Lekérdezés Tranzakció Gyorstár
Objektumok betöltése Azonosító alapján HQL Kritérium alapján Minta alapján
Betöltés Azonnali Laza/Lusta Mohó Kötegelt
Optimalizálás - Gyorstárak
Tranzakció Adatbázis szintű Alkalmazás szintű
A következő előadás tartalma Alkalmazás keretrendszerek J2EE JNDI RMI EJB