En guide til SqlResultSetMapping

1. Introduksjon

I denne guiden tar vi en titt på SqlResultSetMapping, ut av Java Persistence API (JPA).

Kjernefunksjonaliteten her innebærer kartlegging av resultatsett fra database-SQL-setninger til Java-objekter.

2. Oppsett

Før vi ser på bruken, la oss gjøre noen oppsett.

2.1. Maven avhengighet

Våre nødvendige Maven-avhengigheter er dvalemodus og H2-database. Dvalemodus gir oss implementeringen av JPA-spesifikasjonen. Vi bruker H2-database for en database i minnet.

2.2. Database

Deretter lager vi to tabeller som vist her:

OPPRETT TABELL MEDARBEIDER (id BIGINT, navn VARCHAR (10));

De ANSATT bord lagrer ett resultat Enhet gjenstand. SCHEDULE_DAYS inneholder poster knyttet til ANSATT tabellen ved kolonnen Ansatt ID:

OPPRETT TABELL SCHEDULE_DAYS (id IDENTITY, employeeId BIGINT, dayOfWeek VARCHAR (10));

Et skript for dataoppretting finner du i koden til denne veiledningen.

2.3. Enhetsobjekter

Våre Enhet objekter skal se ut:

@Entity offentlig klasse ansatt {@Id privat Lang id; privat strengnavn; }

Enhet objekter kan hete annet enn databasetabeller. Vi kan kommentere klassen med @Bord for å eksplisitt kartlegge dem:

@Entity @Table (name = "SCHEDULE_DAYS") offentlig klasse Planlagt dag {@Id @GeneratedValue privat Lang id; privat Lang ansatt-ID; privat strengdagOfWeek; }

3. Scalar Mapping

Nå som vi har data, kan vi begynne å kartlegge søkeresultater.

3.1. KolonneResultat

Samtidig som SqlResultSetMapping og Spørsmål merknader jobber med Oppbevaringssted klasser også, bruker vi kommentarene på en Enhet klasse i dette eksemplet.

Hver SqlResultSetMapping kommentar krever bare en eiendom, Navn. Uten en av medlemstypene vil imidlertid ingenting bli kartlagt. Medlemstyper er KolonneResultat, ConstructorResult, og EntityResult.

I dette tilfellet, KolonneResultat tilordner hvilken som helst kolonne til en skalar resultattype:

@SqlResultSetMapping (navn = "FridayEmployeeResult", kolonner = {@ ColumnResult (navn = "ansatteId")})

De KolonneResultat eiendom Navn identifiserer kolonnen i spørringen vår:

@NamedNativeQuery (name = "FridayEmployees", query = "VELG medarbeiderId FRA planedager WHERE dayOfWeek = 'FRIDAY'", resultSetMapping = "FridayEmployeeResult") 

Noter det verdien av resultSetMapping i vår NamedNativeQuery kommentar er viktig fordi det samsvarer med Navn eiendom fra vår ResultSetMapping erklæring.

Som et resultat ble den NamedNativeQuery resultatsettet er kartlagt som forventet. Like måte, Lagret prosedyre API krever denne tilknytningen.

3.2. KolonneResultat Test

Vi trenger noen dvalemodus-spesifikke objekter for å kjøre koden vår:

@BeforeAll offentlig statisk ugyldig oppsett () {emFactory = Persistence.createEntityManagerFactory ("java-jpa-planlagt dag"); em = emFactory.createEntityManager (); }

Til slutt kaller vi den navngitte spørringen for å kjøre testen:

@Test offentlig ugyldig når NameQuery_thenColumnResult () {List medarbeiderIds = em.createNamedQuery ("FridayEmployees"). GetResultList (); assertEquals (2, ansatteIds.size ()); }

4. Konstruktorkartlegging

La oss ta en titt på når vi trenger å kartlegge et resultatsett til et helt objekt.

4.1. ConstructorResult

På samme måte som vår KolonneResultat for eksempel vil vi legge til SqlResultMapping kommentar på vår Enhet klasse, Planlagt dag. For å kartlegge ved hjelp av en konstruktør, må vi imidlertid lage en:

offentlig planlagt dag (lang id, lang medarbeider-ID, helhetstimeIn, helhetstimeut, streng dag av uke) {this.id = id; this.employeeId = ansattId; this.dayOfWeek = dayofWeek; }

Kartleggingen spesifiserer også målklassen og kolonnene (begge kreves):

@SqlResultSetMapping (name = "ScheduleResult", classes = {@ConstructorResult (targetClass = com.baeldung.sqlresultsetmapping.ScheduledDay.class, columns = {@ColumnResult (name = "id", type = Long.class), @ColumnResult (name = "ansatteId", type = Long.class), @ColumnResult (name = "dayOfWeek")})})

Rekkefølgen av KolonneResultater er veldig viktig. Hvis kolonner ikke er i orden, vil konstruktøren ikke bli identifisert. I vårt eksempel samsvarer bestillingen med tabellkolonnene, så det ville faktisk ikke være nødvendig.

@NamedNativeQuery (name = "Schedules", query = "SELECT * FROM schedule_days WHERE employeeId = 8", resultSetMapping = "ScheduleResult")

En annen unik forskjell for ConstructorResult er at den resulterende gjenstandsinstansieringen er "ny" eller "løsrevet". Kartlagt Enhet vil være i løsrevet tilstand når en samsvarende primærnøkkel eksisterer i EntityManager ellers blir det nytt.

Noen ganger kan vi støte på kjøretidsfeil på grunn av misforhold mellom SQL-datatyper og Java-datatyper. Derfor kan vi eksplisitt erklære det med type.

4.2. ConstructorResult Test

La oss teste ConstructorResult i en enhetstest:

@Test offentlig ugyldig nårNamedQuery_thenConstructorResult () {List schedDays = Collections.checkedList (em.createNamedQuery ("Schedules", ScheduledDay.class) .getResultList (), ScheduledDay.class); assertEquals (3, scheduleDays.size ()); assertTrue (schedDays.stream (). allMatch (c -> c.getEmployeeId (). longValue () == 3)); }

5. Enhetskartlegging

Til slutt, for en enkel enhetskartlegging med mindre kode, la oss ta en titt på EntityResult.

5.1. Enkel enhet

EntityResult krever at vi spesifiserer enhetsklassen, Ansatt. Vi bruker det valgfrie Enger eiendom for mer kontroll. Kombinert med Feltresultat, vi kan kartlegge aliaser og felt som ikke samsvarer:

@SqlResultSetMapping (name = "EmployeeResult", entities = {@EntityResult (entityClass = com.baeldung.sqlresultsetmapping.Employee.class, fields = {@FieldResult (name = "id", column = "employeeNumber"), @FieldResult (name = "navn", kolonne = "navn")})})

Nå bør forespørselen vår inkludere den aliaserte kolonnen:

@NamedNativeQuery (name = "Ansatte", spørring = "VELG id som ansattNummer, navn FRA MEDARBEIDER", resultSetMapping = "Medarbeiderresultat")

På samme måte som ConstructorResult, EntityResult krever en konstruktør. Imidlertid fungerer en standard her.

5.2. Flere enheter

Kartlegging av flere enheter er ganske grei når vi har kartlagt en enkelt enhet:

@SqlResultSetMapping (name = "EmployeeScheduleResults", entities = {@EntityResult (entityClass = com.baeldung.sqlresultsetmapping.Employee.class), @EntityResult (entityClass = com.baeldung.sqlresultsetmapping.ScheduledDay.class)

5.3. EntityResult Tester

La oss ta en titt på EntityResult i aksjon:

@Test offentlig ugyldig nårNamedQuery_thenSingleEntityResult () {List ansatte = Collections.checkedList (em.createNamedQuery ("Ansatte"). GetResultList (), Employee.class); assertEquals (3, ansatte.størrelse ()); assertTrue (ansatte.strøm (). allMatch (c -> c.getClass () == Ansatt.klasse)); }

Siden resultatene av flere enheter slutter seg til to enheter, er spørringsanmerkingen på bare en av klassene forvirrende.

Av den grunn definerer vi spørringen i testen:

@Test offentlig ugyldig nårNamedQuery_thenMultipleEntityResult () {Query query = em.createNativeQuery ("SELECT e.id, e.name, d.id, d.employeeId, d.dayOfWeek" + "FRA ansatt e, planlegge dager" + "WHERE e .id = d.employeeId "," EmployeeScheduleResults "); Listeresultater = query.getResultList (); assertEquals (4, results.size ()); assertTrue (results.get (0) .length == 2); Employee emp = (Employee) results.get (1) [0]; ScheduledDay day = (ScheduledDay) results.get (1) [1]; assertTrue (day.getEmployeeId () == emp.getId ()); }

6. Konklusjon

I denne guiden så vi på forskjellige alternativer for bruk av SqlResultSetMapping kommentar. SqlResultSetMapping er en viktig del av Java Persistence API.

Kodebiter finner du på GitHub.


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