Introduksjon til Jinq med våren

1. Introduksjon

Jinq gir en intuitiv og praktisk tilnærming for spørring av databaser i Java. I denne opplæringen vil vi utforske hvordan du konfigurerer et vårprosjekt til å bruke Jinq og noen av funksjonene illustrert med enkle eksempler.

2. Maven-avhengigheter

Vi må legge til Jinq-avhengigheten i pom.xml fil:

 org.jinq jinq-jpa 1.8.22 

For våren legger vi til våren ORM avhengighet i pom.xml fil:

 org.springframework spring-orm 5.2.5.RELEASE 

Til slutt, for testing, bruker vi en H2-minne-database, så la oss også legge til denne avhengigheten, sammen med spring-boot-starter-data-jpa til pom.xml-filen:

 com.h2database h2 1.4.200 org.springframework.boot spring-boot-starter-data-jpa 2.2.6.RELEASE 

3. Forstå Jinq

Jinq hjelper oss med å skrive enklere og mer lesbare databasespørsmål ved å utsette et flytende API som er internt basert på Java Stream API.

La oss se et eksempel der vi filtrerer biler etter modell:

jinqDataProvider.streamAll (entityManager, Car.class) .where (c -> c.getModel (). er lik (modell)) .toList ();

Jinq oversetter kodebiten ovenfor til en SQL-spørring på en effektiv måte, så den endelige spørringen i dette eksemplet vil være:

velg c. * fra bil c hvor c.modell =?

Siden vi ikke bruker ren tekst for å skrive spørsmål og bruker et typesikkert API i stedet, er denne tilnærmingen mindre utsatt for feil.

I tillegg har Jinq som mål å gi raskere utvikling ved å bruke vanlige, lettleste uttrykk.

Likevel har det noen begrensninger i antall typer og operasjoner vi kan bruke, som vi får se neste.

3.1. Begrensninger

Jinq støtter bare de grunnleggende typene i JPA og en konkret liste over SQL-funksjoner. Det fungerer ved å oversette lambda-operasjonene til et innfødt SQL-spørsmål ved å kartlegge alle objekter og metoder til en JPA-datatype og en SQL-funksjon.

Derfor kan vi ikke forvente at verktøyet oversetter alle egendefinerte typer eller alle metoder av en type.

3.2. Støttede datatyper

La oss se de støttede datatypene og metodene som støttes:

  • Stringer lik(), sammenligne med() bare metoder
  • Primitive datatyper - aritmetiske operasjoner
  • Enums og tilpassede klasser - støtter bare == og! = operasjoner
  • java.util.Collection - inneholder ()
  • Dato API - er lik(), før(), etter() bare metoder

Merk: hvis vi ønsket å tilpasse konverteringen fra et Java-objekt til et databaseobjekt, må vi registrere vår konkrete implementering av en AttributeConverter i Jinq.

4. Integrering av Jinq med våren

Jinq trenger en EntityManager eksempel for å få utholdenhetskonteksten. I denne opplæringen vil vi introdusere en enkel tilnærming med Spring for å få Jinq til å jobbe med EntityManager levert av dvalemodus.

4.1. Repository Interface

Våren bruker konseptet arkiver for å administrere enheter. La oss se på vår CarRepository grensesnitt der vi har en metode for å hente en Bil for en gitt modell:

offentlig grensesnitt CarRepository {Valgfri findByModel (strengmodell); }

4.2. Abstrakt Base Repository

Neste, vi trenger et basislager å tilby alle Jinq-mulighetene:

offentlig abstrakt klasse BaseJinqRepositoryImpl {@Autowired private JinqJPAStreamProvider jinqDataProvider; @PersistenceContext private EntityManager entityManager; beskyttet abstrakt Class entityType (); offentlig JPAJinqStream-strøm () {retur streamOf (entityType ()); } beskyttet JPAJinqStream streamOf (Class clazz) {return jinqDataProvider.streamAll (entityManager, clazz); }}

4.3. Implementering av depotet

Nå er alt vi trenger for Jinq et EntityManager forekomst og klassen enhetstype.

La oss se Bil depotimplementering ved hjelp av vårt Jinq base repository som vi nettopp definerte:

@Repository public class CarRepositoryImpl utvider BaseJinqRepositoryImpl implementerer CarRepository {@Override public Valgfri findByModel (strengmodell) {returstrøm () .where (c -> c.getModel (). Er lik (modell)) .findFirst (); } @ Override beskyttet Class entityType () {return Car.class; }}

4.4. Kabling av JinqJPAStreamProvider

For å koble til JinqJPAStreamProvider eksempel, vi legg til Jinq-leverandørkonfigurasjonen:

@Configuration offentlig klasse JinqProviderConfiguration {@Bean @Autowired JinqJPAStreamProvider jinqProvider (EntityManagerFactory emf) {returner nye JinqJPAStreamProvider (emf); }}

4.5. Konfigurere vårapplikasjonen

Det siste trinnet er å konfigurere vårapplikasjonen ved hjelp av dvalemodus og vår Jinq-konfigurasjon. Som en referanse, se vår application.properties fil, der vi bruker en H2-forekomst i minnet som database:

spring.datasource.url = jdbc: h2: ~ / jinq spring.datasource.username = sa spring.datasource.password = spring.jpa.hibernate.ddl-auto = create-drop

5. Spørringsguide

Jinq gir mange intuitive alternativer for å tilpasse den endelige SQL-spørringen med velg hvor,blir med og mer. Merk at disse har de samme begrensningene som vi allerede har introdusert ovenfor.

5.1. Hvor

De hvor klausul tillater å bruke flere filtre på en datainnsamling.

I neste eksempel vil vi filtrere biler etter modell og beskrivelse:

stream (). hvor (c -> c.getModel (). er lik (modell) && c.getDescription (). inneholder (desc)) .toList ();

Og dette er SQL som Jinq oversetter:

velg c.modell, c.beskrivelse fra bil c hvor c.model =? og finn (?, c.beskrivelse)> 0

5.2. Å velge

I tilfelle vi bare vil hente noen få kolonner / felt fra databasen, må vi bruke å velge klausul.

For å kartlegge flere verdier, gir Jinq et antall Tuple klasser med opptil åtte verdier:

stream () .select (c -> new Tuple3 (c.getModel (), c.getYear (), c.getEngine ())). toList ()

Og den oversatte SQL:

velg c.modell, c.år, c.motor fra bil c

5.3. Blir med

Jinq er i stand til å løse en-til-en og mange-til-en forhold hvis enhetene er riktig koblet.

For eksempel hvis vi legger til produsentenheten i Bil:

@Entity (name = "CAR") offentlig klasse bil {// ... @OneToOne @JoinColumn (name = "name") offentlig produsent getManufacturer () {returprodusent; }}

Og Produsent enhet med listen over Bils:

@Entity (name = "MANUFACTURER") offentlig klasse Produsent {// ... @OneToMany (mappedBy = "model") offentlig Liste getCars () {returbiler; }}

Vi er nå i stand til å få Produsent for en gitt modell:

Valgfri produsent = stream () .where (c -> c.getModel (). Er lik (modell)) .select (c -> c.getManufacturer ()) .findFirst ();

Som forventet, Jinq vil bruke en indre SQL-klausul i dette scenariet:

velg m.navn, m.by fra bil c indre sammenføyningsprodusent m på c.navn = m.navn hvor c.modell =?

I tilfelle vi trenger å ha mer kontroll over bli med klausuler for å implementere mer komplekse relasjoner over enhetene, som en mange-til-mange-relasjon, kan vi bruke bli med metode:

Liste list = streamOf (Manufacturer.class) .join (m -> JinqStream.from (m.getCars ())) .toList ()

Til slutt kan vi bruke en ytre venstre SQL-klausul ved å bruke leftOuterJoin metoden i stedet for bli med metode.

5.4. Aggregasjoner

Alle eksemplene vi har introdusert så langt bruker enten å liste opp eller findFirst metoder - for å returnere det endelige resultatet av forespørselen vår i Jinq.

Foruten disse metodene, vi har også tilgang til andre metoder for å samle resultater.

La oss for eksempel bruke telle metode for å få totalt antall biler for en konkret modell i vår database:

lang total = stream (). hvor (c -> c.getModel (). er lik (modell)). count ()

Og den endelige SQL bruker telle SQL-metode som forventet:

velg antall (c.modell) fra bil c hvor c.model =?

Jinq tilbyr også aggregeringsmetoder som sum, gjennomsnitt, min, maks, og mulighet til å kombinere forskjellige aggregeringer.

5.5. Paginering

Hvis vi vil lese data i grupper, kan vi bruke grense og hopp over metoder.

La oss se et eksempel der vi vil hoppe over de første 10 bilene og bare få 20 varer:

stream () .skip (10) .limit (20) .toList ()

Og den genererte SQL er:

velg c. * fra bil c grense? forskjøvet?

6. Konklusjon

Der går vi. I denne artikkelen har vi sett en tilnærming for å sette opp en vårapplikasjon med Jinq ved å bruke dvalemodus (minimalt).

Vi har også kort utforsket fordelene ved Jinq og noen av hovedfunksjonene.

Som alltid kan kildene finnes på GitHub.


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