Bibliotekssystem i Java og Postgres
Her er et ER-diagram, som cirka repræsenterer tabellerne på 3NF fra normaliseringartiklen:
I sidste uge, oprettede vi en database for biblioteket i Postgres via pgAdmin.
Vi lavedede følgende SQL-forespørgsler:
- Find en låner ud fra et specifikt laaner_id.
- Find alle lånere, og vis deres data inklusive postnummer og by.
- Find alle bøger, og deres forfattere
- Find alle lånere og de bøger de har lånt. Medtag også bogtitler og evt. forfatter
Vi lavede også følgende DML sætninger:
- Indsæt en ny låner (insert)
- Opret et nyt udlån af en bog (insert)
- Fjern et udlån (delete)
- Rediger en bogtitel (update)
Dagens opgave
I dag skal vi lave et Javaprojekt, som vha. JDBC kan lave de queries til databasen, som vi lavede vi pgAdmin.
- Lav et nyt Maven Javaprojekt i IntelliJ
- Find den XML-snippet i Toolbox som definerer en dependency til postgres. Kopier denne og sæt den ind i din pom.xml. Opdater dine Maven dependencies for få hentet driveren.
- Lav to packages i dit project og kald dem hhv. entities og persistence.
- Så skal vi have lavet entityklasser. Lav klasser, der afspejler de entiteter, du har i din database (fx
Borrower
,Book
,Author
). Overvej om du behøver entities i Java til alle dine tabeller. Giv klasserne attributter, konstruktører og get/set-metoder. - Så skal vi lave klasser, der kan hente data fra databasen og lave dem til Javaobjekter. Vi bruger det design pattern, som hedder Data Mapper, så vi laver en mapperklasse i vores persistencepakke. Start med en
BorrowerMapper
. Lav den uden at give den nogen metoder endnu. -
Vi ønsker ikke, at vores mapper er hardcodet til at forbinde sig til en specifik database. Vi ønsker at bruge dependency injection. Derfor vil vi også gerne have en klasse DatabaseConnector, som tager sig af forbindelsen til den specifikke database. Find koden til at lave en
DatabaseConnector
i Toolbox. Læg dinDatabaseConnector
i pakken persistence. Kig koden igennem og vær sikker på, at du forstår hvad der sker.Koden kompilerer ikke, for klassen gør brug af en hjemmelavet exception kaldet
DatabaseException
. Den skal vi også have lavet. Da vi gerne vil strukturere koden fornuftigt, skal du nu lave en pakke kaldet exceptions, hvor du kan lægge dine hjemmelavede exceptions. Du kan nu skrive din egenDatabaseException
eller kopiere koden fra Toolbox. -
Nu har vi en klasse, der kan forbinde til en database. Den klasse vil vi gerne gøre brug af i vores mapper
BorrowMapper
. Så vi giverBorrowMapper
en attributDatabaseConnector connector
og lader den tage en instans afDatabaseConnector
som argument til sin konstruktør. Du kan finde inspiration til koden i Toolbox -
Vi har det nødvendige for at kunne begynde at hente data fra databasen. Vi starter med at lave en metode, som kan håndtere query 1. Find en låner ud fra et specifikt laaner_id.
Lav metoden
public Borrower getBorrowerById(int id)
i dinBorrowerMapper
-klasse. Metoden skal tage et id som argument og returnere etBorrower
-objekt med data fra databasen. Find inspiration til koden i Toolbox. -
Det er tid til at teste vores kode. I main skal vi have oprettet et
DatabaseConnector
-objekt og etBorrowerMapper
-objekt.DatabaseConnector
-objektet skal oprettes med url, user, og password, der passer til den database vi vil bruge. Objektet skal gives tilBorrowerMapper
som argument til konstruktøren (dependency injection).Test i din main, at du kan kalde metoden
getBorrowerById(int id)
og få et objekt tilbage, som er populeret med data fra databasen. Du kan finde inspiration til koden i Toolbox - Lav nu mapper-metoder til de andre queries vi lavede i pgAdmin. Her skal du være opmærksom på at
- du har muligvis brug for flere mappere (fx
BookMapper
ogAuthorMapper
). - du har brug for at lave joins, hvis du vil medtage både postnummer og by, når du opretter
Borrower
-objekter. - du ikke skal sende fx et laaner_id med når du laver INSERT, da postgres selv generer nøglen. Hvis du gerne vil have id tilbage efter INSERT, skal du bruge
Statement.RETURN_GENERATED_KEYS
. Du kan finde inspiration til koden i Toolbox
- Prøv at lave mapper-metoder, som returnerer data, der ikke er entiteter. Fx kan du lave en metode, der returnerer en låner og en liste af de forfattere vedkommende har lånt bøger af. Lav en Data Transfer Object klasse, som kan bruges til de data. Læg klassen i en pakke kaldet dto.
Her kan du finde forslag til løsninger.