Java >> Java tutorial >  >> Tag >> Spring

Sådan bruges navngivne forespørgsler med Spring Data JPA

Spring Data JPA giver forskellige muligheder for at definere og udføre forespørgsler. De bruger alle JPA's forespørgselsfunktioner, men gør dem meget nemmere at bruge. Du kan:

  • henviser til en navngivet indbygget eller JPQL-forespørgsel,
  • afled forespørgsler fra navnet på en lagermetode og
  • erklær en forespørgsel ved hjælp af @Query-annotationen.

Jeg har allerede forklaret 2. og 3. muligheder i tidligere artikler. I denne tutorial vil jeg fokusere på den første mulighed:henvisningen til en navngivet indfødt eller JPQL-forespørgsel i et Spring Data JPA-lager. Det gør det meget nemmere at udføre din forespørgsel, fordi Spring Data tager sig af al den standardkode, der kræves af JPA.

Definition af en navngivet forespørgsel med JPA

Navngivne forespørgsler er et af kernebegreberne i JPA. De giver dig mulighed for at erklære en forespørgsel i dit persistenslag og henvise til den i din virksomhedskode. Det gør det nemt at genbruge en eksisterende forespørgsel. Det giver dig også mulighed for at adskille definitionen af ​​din forespørgsel fra din virksomhedskode.

Du kan definere en navngivet forespørgsel ved hjælp af en @NamedQuery annotering på en enhedsklasse eller ved hjælp af en element i din XML-tilknytning. I denne artikel vil jeg vise dig den annotationsbaserede kortlægning. Det er den langt den mest almindelige tilgang til at oprette en navngivet forespørgsel.

Når du definerer en navngivet forespørgsel, kan du angive en JPQL-forespørgsel eller en indbygget SQL-forespørgsel på meget lignende måder. Lad os tage et kig på begge muligheder.

Definition af en navngivet JPL-forespørgsel

JPA-specifikationen definerer sit eget forespørgselssprog. Det hedder JPQL, og dets syntaks ligner SQL. Men der er 2 væsentlige forskelle mellem disse 2:

  1. Du definerer din JPQL-forespørgsel baseret på din enhedsmodel. Når du udfører det, genererer din persistensudbyder en SQL-forespørgsel baseret på dine entitetstilknytninger og den medfølgende JPQL-sætning. Det giver dig mulighed for at definere databaseuafhængige forespørgsler, men begrænser dig også til de funktioner, der understøttes af din persistensudbyder.
  2. JPQL understøtter kun en lille delmængde af SQL-standarden og næsten ingen databasespecifikke funktioner.

Definitionen af ​​en navngivet JPQL-forespørgsel er ret enkel. Du skal bare annotere en af ​​dine enhedsklasser med @NamedQuery og giv 2 strenge s for navnet og forespørgsel attributter.

navnet af din forespørgsel skal være unik i din persistens kontekst. Du skal bruge det i din virksomhedskode eller lagerdefinition til at referere til forespørgslen.

Navnet behøver ikke at følge nogen konventioner, hvis du vil referere til forespørgslen programmatisk. Men hvis du vil henvise til det i et Spring Data JPA-lager, skal navnet starte med navnet på enhedsklassen efterfulgt af et "." og navnet på lagermetoden.

Værdien af ​​forespørgslen attribut skal være en streng, der indeholder en gyldig JPQL-sætning. Hvis din forespørgsel returnerer en enhed, kan du definere din projektion implicit, som du kan se i Author.findByFirstName forespørgsel. Author.findByFirstNameAndLastName forespørgslen indeholder en SELECT-sætning for at definere projektionen eksplicit.

JPQL understøtter selvfølgelig langt flere funktioner, end jeg bruger i disse enkle eksempler. Du kan lære mere om det i min ultimative guide til JPQL-forespørgsler med JPA og Hibernate.

@Entity
@NamedQuery(name = "Author.findByFirstName", query = "FROM Author WHERE firstName = ?1")
@NamedQuery(name = "Author.findByFirstNameAndLastName", query = "SELECT a FROM Author a WHERE a.firstName = ?1 AND a.lastName = ?2")
public class Author { ... }

Hvis du vil definere flere JPQL-forespørgsler og bruge mindst JPA 2.2 eller Hibernate 5.2, kan du annotere din klasse med flere @NamedQuery anmærkninger. Hvis du bruger en ældre JPA- eller Hibernate-version, skal du indpakke din @NamedQuery annotation i en @NamedQueries anmærkning.

Definition af en navngivet indbygget forespørgsel


Følg mig på YouTube for ikke at gå glip af nye videoer.

Native SQL-forespørgsler er mere kraftfulde og fleksible end JPQL-forespørgsler. Din persistensudbyder analyserer ikke disse forespørgsler og sender dem direkte til databasen. Det giver dig mulighed for at bruge alle SQL-funktioner, der understøttes af din database. Men du skal også håndtere de forskellige databasedialekter, hvis du skal understøtte flere DBMS.

Du kan definere en navngivet indbygget forespørgsel på næsten samme måde, som du angiver en navngivet JPQL-forespørgsel. De 3 vigtigste forskelle er:

  1. Du skal bruge en @NamedNativeQuery i stedet for en @NamedQuery anmærkning.
  2. Værdien af ​​forespørgselsattributten skal være en SQL-sætning i stedet for en JPQL-sætning.
  3. Du kan definere en enhedsklasse eller en reference til en @SqlResultSetMapping som vil blive brugt til at kortlægge resultatet af din forespørgsel. Spring Data JPA kan levere et sæt standardkortlægninger, så du ofte ikke behøver at angive det.

Her kan du se de samme forespørgsler som i det foregående eksempel. Men denne gang er de defineret som native SQL-forespørgsler i stedet for JPQL-forespørgsler.

@Entity
@NamedNativeQuery(name = "Author.findByFirstName", query = "SELECT * FROM author WHERE first_name = ?", resultClass = Author.class)
@NamedNativeQuery(name = "Author.findByFirstNameAndLastName", query = "SELECT * FROM author WHERE first_name = ? AND last_name = ?", resultClass = Author.class)
public class Author { ... }

Udførelse af en navngivet forespørgsel programmatisk med JPA

Brug af JPA's EntityManager , kan du køre navngivne native og navngivne JPQL-forespørgsler på samme måde:

  1. Du kalder createNamedQuery metode på EntityManager med navnet på den navngivne forespørgsel, du vil udføre. Det giver dig en forekomst af en Forespørgsel eller TypedQuery grænseflade.
  2. Du kalder derefter setParameter-metoden på den returnerede grænseflade for hver bindeparameter, der bruges i din forespørgsel.
  3. Som et sidste trin kalder du getSingleResult eller getResultSet metode på Forespørgsel eller TypedQuery interface. Det udfører forespørgslen og returnerer 1 eller flere resultatsætposter.

Her kan du se den nødvendige kode for at udføre Author.findByFirstName forespørgsel, som vi definerede i de 2 foregående eksempler.

Query q = em.createNamedQuery("Author.findByFirstName");
q.setParameter(1, "Thorben");
List a = q.getResultList();

Før du kører denne kode, bør du aktivere logningen af ​​SQL-sætninger. Du kan derefter se den udførte SQL-sætning og de anvendte bind-parameterværdier i din logfil. I dette eksempel kaldte jeg @NamedNativeQuery version af den tidligere viste Author.findByFirstName forespørgsel.

2019-06-24 19:20:32.061 DEBUG 10596 - – [           main] org.hibernate.SQL                        : 
    SELECT
        * 
    FROM
        author 
    WHERE
        first_name = ?
2019-06-24 19:20:32.073 TRACE 10596 - – [           main] o.h.type.descriptor.sql.BasicBinder      : binding parameter [1] as [VARCHAR] - [Thorben]
2019-06-24 19:20:32.116 TRACE 10596 - – [           main] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([id] : [NUMERIC]) - [1]
2019-06-24 19:20:32.118 TRACE 10596 - – [           main] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([first_name] : [VARCHAR]) - [Thorben]
2019-06-24 19:20:32.119 TRACE 10596 - – [           main] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([last_name] : [VARCHAR]) - [Janssen]
2019-06-24 19:20:32.121 TRACE 10596 - – [           main] o.h.type.descriptor.sql.BasicExtractor   : extracted value ([version] : [INTEGER]) - [0]

Henvisning til en navngivet forespørgsel i et Spring Data JPA-lager

Som du har set i det foregående eksempel, udføres en navngivet forespørgsel ved hjælp af JPA's EntityManager er ikke kompliceret, men det kræver flere trin.

Spring Data JPA sørger for det, hvis du refererer til en navngivet forespørgsel i din depotdefinition. At gøre det er ekstremt enkelt, hvis du følger Spring Datas navnekonvention. Navnet på din forespørgsel skal starte med navnet på din enhedsklasse efterfulgt af "." og navnet på din lagermetode.

I de foregående eksempler definerede jeg de navngivne forespørgsler Author.findByFirstName og Author.findByFirstNameAndLastName som JPQL og native forespørgsler. Du kan referere til begge versioner af disse forespørgsler ved at tilføje metoderne findByFirstName og findByFirstNameAndLastName til AuthorRepository .

public interface AuthorRepository extends JpaRepository<Author, Long> {

    List<Author> findByFirstName(String firstName);

    List<Author> findByFirstNameAndLastName(String firstName, String lastName);

}

Du kan derefter injicere et AuthorRepository forekomst i din virksomhedskode og kalder lagermetoderne for at udføre de navngivne forespørgsler.

Som du kan se i det følgende kodestykke, kan du bruge disse repository-metoder på samme måde som en repository-metode, der udfører en afledt forespørgsel eller en erklæret forespørgsel. Spring Data JPA håndterer instansieringen af ​​den navngivne forespørgsel, indstiller bindeparameterværdierne, udfører forespørgslen og kortlægger resultatet.

List<Author> a = authorRepository.findByFirstName("Thorben");

Konklusion

Navngivne forespørgsler er en af ​​de forskellige muligheder for at forespørge data fra din database, som er defineret af JPA-specifikationen.

Spring Data JPA giver en meget behagelig måde at bruge navngivne forespørgsler i dit lager. Det tager sig af al den gentagne boilerplate-kode, der kræves af JPA-specifikationen. Som standard søger Spring Data JPA efter en navngivet JPQL eller en navngivet indbygget forespørgsel, der følger navnekonventionen . før den forsøger at udlede en forespørgsel fra metodenavnet.


Java tag