Vodič za SqlResultSetMapping

1. Uvod

U ovom ćemo vodiču pogledati SqlResultSetMapping, iz Java Persistent API-ja (JPA).

Osnovna funkcionalnost ovdje uključuje mapiranje skupova rezultata iz SQL izraza baze podataka u Java objekte.

2. Postavljanje

Prije nego što pogledamo njegovu upotrebu, napravimo neko postavljanje.

2.1. Ovisnost Mavena

Naše potrebne ovisnosti o Mavenu su Hibernate i H2 Database. Hibernate nam daje provedbu JPA specifikacije. Bazu podataka H2 koristimo za bazu podataka u memoriji.

2.2. Baza podataka

Dalje, izradit ćemo dvije tablice kao što se vidi ovdje:

STVORI ZAPOSLENIKA U TABLI (id BIGINT, ime VARCHAR (10));

The ZAPOSLENIK tablica pohranjuje jedan rezultat Entitet objekt. RASPORED_DANA sadrži zapise povezane s ZAPOSLENIK tablica uz stupac id zaposlenika:

STVARI RASPORED_DANA TABELE (ID IDENTITETA, ID zaposlenika VELIKI, dayOfWeek VARCHAR (10));

Skriptu za stvaranje podataka možete pronaći u kodu ovog vodiča.

2.3. Predmeti entiteta

Naše Entitet objekti bi trebali izgledati slično:

@ Entity public class Employee {@Id private Long id; privatni naziv niza; }

Entitet objekti se mogu imenovati drugačije od tablica baze podataka. Predmet možemo označiti s @Stol da ih izričito mapiramo:

@Entity @Table (name = "SCHEDULE_DAYS") javna klasa ScheduledDay {@Id @GeneratedValue private Long id; privatni Long zaposlenikId; private String dayOfWeek; }

3. Mapiranje skalara

Sad kad imamo podatke, možemo početi mapirati rezultate upita.

3.1. Rezultat stupca

Dok SqlResultSetMapping i Upit bilješke rade na Spremište klase, koristimo i napomene na Entitet razreda u ovom primjeru.

Svaki SqlResultSetMapping napomena zahtijeva samo jedno svojstvo, Ime. Međutim, bez jedne od vrsta članova, ništa se neće preslikati. Vrste članova su Rezultat stupca, Rezultat konstruktora, i Rezultat entiteta.

U ovom slučaju, Rezultat stupca preslikava bilo koji stupac na skalarni tip rezultata:

@SqlResultSetMapping (name = "FridayEfficieeResult", stupci = {@ ColumnResult (name = "workerId")})

The Rezultat stupca imovine Ime identificira stupac u našem upitu:

@NamedNativeQuery (name = "PetakZaposlenici", query = "ODABERITE ID zaposlenika IZ raspored_dana WHERE dayOfWeek = 'PETAK'", resultSetMapping = "PetakZaposlenikResult") 

Imajte na umu da vrijednost resultSetMapping u našem NamedNativeQuery bilješka je važno jer se podudara s Ime vlasništvo iz našeg ResultSetMapping deklaracija.

Kao rezultat, NamedNativeQuery skup rezultata mapira se prema očekivanjima. Također, StoredProcedure API zahtijeva ovu povezanost.

3.2. Rezultat stupca Test

Trebat će nam neki hibernate specifični objekti za pokretanje našeg koda:

@BeforeAll javna statička void postavka () {emFactory = Persistence.createEntityManagerFactory ("java-jpa-raspored-dan"); em = emFactory.createEntityManager (); }

Konačno, pozivamo imenovani upit da bismo pokrenuli naš test:

@Test javna void whenNamedQuery_thenColumnResult () {Popis zaposlenika = em.createNamedQuery ("PetakZaposlenici"). GetResultList (); assertEquals (2, workerIds.size ()); }

4. Mapiranje konstruktora

Pogledajmo kada trebamo mapirati skup rezultata na cijeli objekt.

4.1. Rezultat konstruktora

Slično našem Rezultat stupca na primjer, dodati ćemo SqlResultMapping bilješka na našem Entitet razred, ScheduledDay. Međutim, da bismo mapirali pomoću konstruktora, moramo ga stvoriti:

javni ScheduledDay (Long id, Long workerId, Integer hourIn, Integer hourOut, String dayofWeek) {this.id = id; this.employeeId = workerId; this.dayOfWeek = dayofWeek; }

Također, mapiranje navodi ciljnu klasu i stupce (oba su obavezna):

@SqlResultSetMapping (name = "ScheduleResult", klase = {@ConstructorResult (targetClass = com.baeldung.sqlresultsetmapping.ScheduledDay.class, columns = {@ColumnResult (name = "id", type = Long.class), @ColumnRes) = "ID zaposlenika", tip = Long.class), @ColumnResult (name = "dayOfWeek")})}))

Redoslijed Rezultati stupca je vrlo važno. Ako stupci nisu u redu, konstruktor neće biti prepoznat. U našem primjeru poredak se podudara sa stupcima tablice, pa zapravo ne bi bio potreban.

@NamedNativeQuery (name = "Raspored", query = "SELECT * FROM raspored_dana WHERE zaposlenikId = 8", resultSetMapping = "ScheduleResult")

Još jedna jedinstvena razlika za Rezultat konstruktora je da rezultirajuća instancija objekta bude "nova" ili "odvojena". Kartirano Entitet bit će u izdvojenom stanju kada odgovarajući primarni ključ postoji u EntityManager inače će biti novo.

Ponekad se možemo susresti s pogreškama u izvršavanju zbog neusklađenosti SQL tipova podataka s Java vrstama podataka. Stoga ga možemo izričito izjaviti sa tip.

4.2. Rezultat konstruktora Test

Isprobajmo Rezultat konstruktora u jediničnom testu:

@Test public void whenNamedQuery_thenConstructorResult () {List scheduleDays = Collections. CheckList (em.createNamedQuery ("Schedules", ScheduledDay.class) .getResultList (), ScheduledDay.class); assertEquals (3, scheduleDays.size ()); assertTrue (scheduleDays.stream (). allMatch (c -> c.getEfficieeId (). longValue () == 3)); }

5. Mapiranje entiteta

Konačno, pogledajmo jedno jednostavno mapiranje entiteta s manje koda Rezultat entiteta.

5.1. Pojedinačni entitet

Rezultat entiteta zahtijeva da odredimo klasu entiteta, Zaposlenik. Koristimo neobavezno polja svojstvo za veću kontrolu. U kombinaciji sa Rezultat polja, možemo mapirati pseudonime i polja koja se ne podudaraju:

@SqlResultSetMapping (name = "EmployeeResult", entiteti = {@EntityResult (entityClass = com.baeldung.sqlresultsetmapping.E Employee.class, fields = {@FieldResult (name = "id", column = "workerNumber"), @FieldResult (@FieldResult = "ime", stupac = "ime")})})

Sada bi naš upit trebao uključivati ​​alias stupac:

@NamedNativeQuery (name = "Zaposlenici", query = "ODABERI id kao broj zaposlenika, ime FROM EMPLOYEE", resultSetMapping = "EmployeeResult")

Slično kao Rezultat konstruktora, Rezultat entiteta zahtijeva konstruktor. Međutim, ovdje radi zadani.

5.2. Više entiteta

Mapiranje više entiteta prilično je jednostavno nakon što mapiramo jedan entitet:

@SqlResultSetMapping (name = "EmployeeScheduleResults", entiteti = {@EntityResult (entityClass = com.baeldung.sqlresultsetmapping.Efficiee.class), @EntityResult (entityClass = com.baeldung.sqlresultledayping.Sclars

5.3. Rezultat entiteta Ispitivanja

Pogledajmo Rezultat entiteta u akciji:

@Test public void whenNamedQuery_thenSingleEntityResult () {Popis zaposlenika = Collections. CheckList (em.createNamedQuery ("Zaposlenici"). GetResultList (), Employee.class); assertEquals (3, zaposlenici.size ()); assertTrue (zaposlenici.stream (). allMatch (c -> c.getClass () == Employee.class)); }

Budući da se rezultati više entiteta spajaju s dva entiteta, napomena upita samo za jednu od klasa zbunjuje.

Iz tog razloga upit definiramo u testu:

@Test public void whenNamedQuery_thenMultipleEntityResult () {Query query = em.createNativeQuery ("SELECT e.id, e.name, d.id, d.employeeId, d.dayOfWeek" + "FROM worker e, schedule_days d" + "WHERE e .id = d.employeeId "," EmployeeScheduleResults "); Popis rezultata = query.getResultList (); assertEquals (4, results.size ()); assertTrue (results.get (0) .length == 2); Zaposlenik emp = (Zaposlenik) results.get (1) [0]; ScheduledDay day = (ScheduledDay) results.get (1) [1]; assertTrue (day.getEfficieeId () == emp.getId ()); }

6. Zaključak

U ovom smo vodiču pogledali različite mogućnosti korištenja SqlResultSetMapping bilješka. SqlResultSetMapping je ključni dio Java Persistent API-ja.

Isječke koda možete pronaći na GitHubu.


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