<m o de l V er s i o n> 4 . 0 . 0 m o de l V e rs i o n> j a r p a c k a g i n g> < !−− p e r s i s t e n c e . xml −−> < !−− Scan f o r a n n o t a t e d c l a s s e s and H i b e r n a t e mapping XML f i l e s −−>
Hoofdstuk 3. Maven
14
dependency> d e p e n d e n c i e s> p r o j e c t>
Code 3.1: Maven’s Project Object Model.
Dit Project Object Model (POM) bevat alle belangrijke informatie van het project. De meeste elementen hierin zijn zeer eenvoudig en geven beschrijvende informatie over het project. In de volgende paragraaf wordt dieper ingegaan op het dependencies element.
3.2
Het gebruik van dependencies
Bij de installatie en het eerste gebruik van Maven, zal Maven een lokale repository opstellen, en daar verschillende libraries in opslaan, afhankelijk van de dependencies in het POM. In dit voorbeeld zal Maven in de standaard centrale Maven repository op zoek gaan naar de nodige bestanden om de JUnit afhankelijkheid te gebruiken. Deze zal hij dan downloaden naar de lokale repository alwaar hij de nodige jarbestanden zal bewaren. Op die manier gebruikt Maven voor elk project dezelfde lokale repository en zal niet voor elk afzonderlijk project de nodige externe bestanden opnieuw worden opgehaald. Het voordeel bij deze aanpak is dat de gebruikte dependencies enkel moeten weergegeven worden in pom.xml, zoals in codevoorbeeld 3.1. Maven zorgt ervoor dat de niet aanwezige dependencies gedownload worden naar de lokale repository.
3.3
Site generatie met Maven
Maven beschikt ook over een eenvoudig systeem om een website over het project aan te maken. dit wordt veel gebruikt bij open source toepassingen om een projectwebsite2 aan te maken. Om een site aan te maken gebruikt Maven verschillende bronnen om de informatie op te halen. Enerzijds wordt gebruik gemaakt van het pom.xml bestand om projectinformatie op te halen. Maven heeft verschillende tags die informatie meegeven aan het project. In het pom.xml bestand kan een naam, beschrijving, een lijst van programmeurs, de website,... meegegeven worden. Ook kunnen verschillende plugins gedefinieerd worden die gebruikt kunnen worden om testrapporten en Java documentatie te genereren. Het belangrijkste bestand bevindt zich in de map src/site en heeft als naam site.xml. Hierin wordt de structuur van onze site bepaald, indien men niet voldoende heeft aan de standaard website. De configuratie van dit bestand bepaalt de structuur van de website. 2
Bvb.: http://maven.apache.org
Hoofdstuk 3. Maven
15
Code 3.2: Configuratiebestand van de website
In dit bestand worden de gebruikt pagina’s gelinkt, aan een inhoudsopgave die we in onze site gebruiken. Hierbij worden enerzijds automatisch gecre¨eerde pagina’s aangemaakt, alsook zelf gemaakte pagina’s. Eigen pagina’s kunnen op verschillende manieren aangemaakt worden. Externe pagina’s of bestanden kunnen rechtstreeks in de website gelinkt worden. Deze externe resources dienen daarvoor in de map /src/site/resources geplaatst te worden. Een tweede mogelijkheid is om zelf pagina’s aan te maken in Maven’s eigen Almost Plain Text (APT) formaat. Dit is een wiki -achtige markup-taal die door Maven kan omgezet worden naar Hypertext Markup Language (HTML)-pagina’s. Deze pagina’s worden door Maven in de website ingevoegd.
Hoofdstuk 4
JPA 4.1
Inleiding
In paragraaf 1.3 werd aangehaald dat de Java Persistence API (JPA) specificatie met Hibernate als implementatie een Object/Relational Mapping (ORM) oplossing biedt om met persistente objecten om te gaan. Het gebruik van JPA in een applicatie bestaat uit drie stappen: • Het objectmodel aanmaken en de mapping bepalen door de nodige annotaties aan te brengen. • Een configuratiebestand maken, met instellingen over de gebruikte databank en eigenschappen om met deze verbindingen op te zetten. • Het gebruik van de Hibernate EntityManager om objecten aan te maken, te wijzigen en op te zoeken.
4.2
Mapping door annotaties
Met JPA-annotaties wordt de relatie tussen het objectmodel en de relationele databank aangeduid. In deze paragraaf wordt dieper ingegaan op de verschillende annotaties. Als een objectmodel gemapt dient te worden naar een databankmodel kunnen vier onderdelen onderscheiden worden. 1. Een klasse mappen naar ´e´en of meerdere tabellen. 2. De attributen naar de verschillende kolommen linken. 3. Relaties tussen objecten omzetten naar relaties gebruikt in een databankmodel. 16
Hoofdstuk 4. JPA
17
4. Overerving en polymorfisme mappen naar een databankmodel. Hierbij wordt vertrokken van een top-down benadering. Er wordt vertrokken vanuit een bestaand objectmodel dat gelinkt dient te worden aan een databank, waarbij er weinig of geen vereisten zijn voor de onderliggende databank. Deze methode laat de vrijheid om de verschillende annotaties te verklaren. Uiteraard kunnen ook andere benaderingen gebruikt worden1 . Een bottom-up benadering vertrekt vanuit een opgelegde databankmodel waarna men dan de annotaties invult, zodat de objecten dan volgens dit schema gemapt worden naar de databank. In dit hoofdstuk wordt dieper ingegaan op het gebruik van JPA aan de hand van voorbeeld 4.1. Dit objectmodel wordt gemapt naar een databankmodel.
Figuur 4.1: Klassediagram van een objectmodel dat gemapt wordt naar een databankmodel
4.2.1
Annotaties op klassen
Klassen waarvan de objecten gemapt moeten worden naar de databank, moeten aangeduid worden als een entiteit. JPA maakt voor deze aanduiding gebruik van annotaties, een toevoeging in Java 5.0. Om een klasse aan te duiden als entiteit dient men deze aan te duiden met de @Entity annotatie. Verder kan onder meer de naam van de databanktabel gespecificeerd worden met de annotatie @Table. @Entity @Table ( name = ”PERSOON” ) public c l a s s Persoon { }
Code 4.1: Mapping van een klasse 1
De databank kan dan ook automatisch gegenereerd worden met de hbm2ddl tool.
Hoofdstuk 4. JPA
18
Een klasse kan ook beschouwd worden als onderdeel van een andere klasse. Daarvoor kan de @Embeddable annotatie gebruikt worden.
4.2.2
Annotaties op velden en/of attributen
Om alle informatie van een klasse te bewaren, dienen ook de attributen van een klasse in de databank opgeslagen te worden. Eenvoudige attributen van standaard Java Development Kit (JDK) types, worden automatisch omgezet naar het overeenkomstige databanktype. Hiervoor is het voldoende om de attributen aan te duiden met een @Column annotatie. Binnen een databank dient elke tabel voorzien te zijn van een primaire sleutel. Daarom dient minstens ´e´en attribuut aangeduid te worden als primaire sleutel van de tabel. Deze kan automatisch worden ingevuld met de juiste annotaties, ook kunnen andere attributen aangeduid worden als secundaire sleutels. @Id @GeneratedValue ( s t r a t e g y = GenerationType .AUTO) @Column ( name = ”PERSOON ID” ) private long i d ; @Column ( name = ”PERSOON NAAM” ) private S t r i n g naam ;
Code 4.2: Annotaties op attributen
Deze annotaties kunnen rechtstreeks op de attributen aangebracht maken, of op de methoden die toegang geven tot de waarden, de zogenaamde getter -methoden. Afhankelijk waar de annotaties zich bevinden, vragen de onderliggende JPA-klassen hun waarden rechtstreeks aan de attributen, of vragen ze de waarde op via de geannoteerde methoden.
4.2.3
Relaties tussen klassen
De mapping van een klasse en zijn attributen naar de juiste kolommen in de databank is voor de meeste objectmodellen niet voldoende. Binnen verschillende klassen bestaan afhankelijkheden naar andere klassen. Een klasse kan een heeft-een relatie hebben met een andere klasse, of een lijst van objecten van een andere klassen bevatten. Deze relaties moeten we omzetten, naar de bestaande relaties in een databank. Een databank kan ´e´en-op-´e´en, veel-op-´e´en, of veel-op-veel relaties bevatten. Verder moet er gespecificeerd worden of deze relaties, uni- of bidirectioneel dienen te zijn.
Hoofdstuk 4. JPA
19
Een ´ e´ en-op-´ e´ en relatie In het voorgaande voorbeeld is te zien dat de klasse Persoon een relatie met zichzelf heeft. Dit dient omgezet te worden naar een ´e´en-op-´e´en relatie in de databank. In een databankmodel wordt dit ge¨ımplementeerd door een kolom toe te voegen die een verwijzing bevat naar de primaire sleutel van de Persoon die de echtgenoot voorstelt. Dit is ook duidelijk te zien in de manier waarop de annotaties dienen ingevuld te worden. @Entity @Table ( name = ”PERSOON” ) public c l a s s Persoon { @OneToOne( c a s c a d e = CascadeType . ALL) @JoinColumn ( name = ”ECHTGENOOT ID” ) private Persoon e c h t g e n o o t ; }
Code 4.3: Annotaties op een ´e´en-op-´e´en relatie
Er wordt een @OneToOne annotatie gebruikt om de relatie aan te duiden. De @JoinColumn annotatie duidt de naam van de kolom aan die daarvoor gebruikt wordt. Dit geeft een databankmodel zoals te zien in figuur 4.2.
Figuur 4.2: Een ´e´en-op-´e´en relatie in een databankmodel
Een ´ e´ en-op-veel relatie Een object van de klasse Persoon kan een inwoner zijn van een object van de klasse Huis. Een Huis kan echter meerdere inwoners hebben. Dit is te zien in het klassediagram op figuur 4.1, waar een Huis een collectie van inwoners bevat. Om dit in een databankmodel weer te geven, wordt aan een Persoon-tabel een kolom toegevoegd die de primaire sleutel van een Huis bevat. @Entity @Table ( name = ”PERSOON” ) public c l a s s Persoon {
Hoofdstuk 4. JPA
20
@ManyToOne( f e t c h = FetchType .EAGER) @JoinColumn ( name=”PERSOON HUIS ID” , referencedColumnName=”HUIS ID” ) private Huis h u i s ; }
Code 4.4: Annotaties op een ´e´en-op-veel relatie
Er wordt een @ManyToOne annotatie gebruikt om de relatie aan te duiden. De @JoinColumn annotatie duidt de naam van de kolom aan die daarvoor gebruikt wordt. Dit geeft een databankmodel zoals te zien in figuur 4.3. We duiden het type aan van de relatie die we willen defini¨eren, in dit geval dus een @ManyToOne relatie. En aan de @JoinColumn annotatie worden de kolommen meegegeven die de data van de relatie moet bevatten. Aan de andere kant van de relatie dient enkel aangeduid te worden dat de relatie bestaat en door welk attribuut ze gespecificeerd wordt. @Entity @Table ( name = ”HUIS” ) public c l a s s Huis { @OneToMany( mappedBy = ” h u i s ” ) private C o l l e c t i o n
Code 4.5: Annotaties op een ´e´en-op-veel relatie
Op deze manier wordt een databankmodel bekomen zoals in figuur 4.3.
Figuur 4.3: Een ´e´en-op-veel relatie in het databankmodel
Een veel-op-veel relatie Ook veel-op-veel relaties kunnen aangeduid worden met behulp van JPA. In een databank kunnen we deze relatie enkel defini¨eren door een tussentabel in te voegen. Op deze manier moet deze relatie dan ook aangeduid worden in het objectmodel. In het gebruikte objectmodel is te zien dat een object van de klasse Huisdier verschillende Persoon objecten als eigenaar kan hebben, en dat een object van de klasse Persoon verschillende objecten van de klasse Huisdier kan bevatten. Deze relatie wordt geannoteerd volgens codevoorbeeld 4.6.
Hoofdstuk 4. JPA
21
De annotatie @ManyToMany wordt gebruikt om de relatie aan te duiden. De annotatie @JoinTable zorgt voor een nieuwe tabel in de databank. Deze bestaat enkel uit verwijzingen naar de primaire sleutels van de objecten die bij elkaar horen. @Entity @PrimaryKeyJoinColumn ( name = ”HUISDIER ID” ) @Table ( name = ”HUISDIER” ) public c l a s s H u i s d i e r extends D i e r { @ManyToMany( f e t c h = FetchType .EAGER) @JoinTable ( name = ”HUISDIER EIGENAAR” , joinColumns = { @JoinColumn ( name = ”HUISDIER ID” ) } , i n v e r s e J o i n C o l u m n s = { @JoinColumn ( name = ”PERSOON ID” ) } ) private C o l l e c t i o n
Code 4.6: Mapping van een klasse
In het databankmodel van figuur 4.4 is duidelijk te zien dat er een extra tabel in de databank wordt ingevoegd. In de andere klasse die bij de relatie betrokken is, dient enkel aangeduid te worden door welk attribuut de relatie gespecificeerd wordt, zoals in codevoorbeeld 4.5.
Figuur 4.4: Een veel-op-veel relatie
4.2.4
Overerving en polymorfisme
Ten slotte dient nog de overerving tussen de klasse Dier en Huisdier ge¨ımplementeerd te worden. Hiervoor wordt de @Inheritance annotatie gebruikt in de superklasse. Hibernate heeft verschillende technieken ingebouwd om ervoor te zorgen dat de juiste objecten uit de databank opgehaald worden. Het strategy attribuut van de @Inheritance annotatie bepaalt welke strategie gevolgd wordt, om het databankmodel te bepalen. Deze strategie bepaalt welke SQL statements uitgevoerd worden. Deze keuze heeft meestal dan ook enkel
Hoofdstuk 4. JPA
22
belang indien men aan een vast databankmodel dient te voldoen, of kan een invloed hebben op de performantie van de uitgevoerde queries. In deze masterproef wordt hier echter niet dieper op ingegaan. @Entity @ I n h e r i t a n c e ( s t r a t e g y = I n h e r i t a n c e T y p e . JOINED) @Table ( name=”DIER” ) public c l a s s D i e r { ... }
Code 4.7: Annotaties op een superklasse
4.3
Configuratie van JPA
De JPA functionaliteit dient ook nog informatie te krijgen over welke klassen geannoteerd zijn. Alsook dienen connectiegegevens aanwezig te zijn, om de gebruikte databank te kunnen lokaliseren, en een connectie op te zetten. Deze informatie wordt opgeslagen in een XMLbestand. Default wordt dit bestand opgeslagen in de META-INF map.
Hoofdstuk 4. JPA p e r s i s t e n c e −u n i t> p e r s i s t e n c e>
Code 4.8: Voorbeeld van persistence.xml configuratiebestand
4.4
Opslaan en opvragen van objecten
23
Hoofdstuk 5
Spring Spring is een open-source framework dat tot doel heeft om de eenvoudige J2EE applicaties te ontwikkelen. Elke java-applicatie kan echter voordelen hebben bij Spring. Spring heeft verschillende hulpmiddelen om unit testen te vereenvoudigen. Spring zorgt voor een losse koppeling tussen klassen. Spring zorgt voor minder, en dus makkelijkere code, en biedt hulpklassen aan voor een verscheidenheid aan veelgebruikte technologie¨en. Spring is a lightweight dependency injection and aspect-oriented container and framework (Walls & Breidenbach, 2008) In deze masterproef gebruiken we vooral de losse koppeling die door Spring verkregen wordt, door dependecy injection te gebruiken. Alsook de hulpklassen die Spring bevat om met minder code JPA opdrachten uit te voeren.
5.1
Dependency injection
5.2
JPA en Spring
24
Bibliografie (2009). Introduction to archetypes. http://maven.apache.org/guides/introduction/ introduction-to-archetypes.html. Geraadpleegd: maart 2009. Bauer, C. & King, G. (2007). Java Persistance with Hibernate. Manning, second edition. Biswas, R. & Ort, E. (2006). The java persistence api - a simpler programming model for entity persistence. http://java.sun.com/developer/technicalArticles/J2EE/jpa/. Geraadpleegd: januari 2009. Johnson, R., Hoeller, J., Arendsen, A., Risberg, T., & Sampaleanu, C. (2005). Professional Java Development with the Spring Framework. Wiley Publishing, first edition. Massol, V. & Husted, T. (2004). JUnit in action. Manning, first edition. Massol, V., van Zyl, J., Porter, B., Casey, J., & Sanchez, C. (2008). Better Builds with Maven. DevZuz, first edition. Walls, C. & Breidenbach, R. (2008). Spring in action. Manning, second edition.
25