Uvod u Jinqa s proljećem

1. Uvod

Jinq pruža intuitivan i praktičan pristup za upite o bazama podataka u Javi. U ovom uputstvu istražit ćemo kako konfigurirati proljetni projekt da koristi Jinq a neke od njegovih značajki ilustrirane su jednostavnim primjerima.

2. Ovisnosti Mavena

Trebat ćemo dodati ovisnost Jinq u pom.xml datoteka:

 org.jinq jinq-jpa 1.8.22 

Za Proljeće ćemo dodati ovisnost Spring ORM u pom.xml datoteka:

 org.springframework spring-orm 5.2.5.OBUSTAVLJANJE 

Napokon, za testiranje ćemo upotrijebiti H2 bazu podataka u memoriji, pa dodajmo i ovu ovisnost, zajedno s spring-boot-starter-data-jpa u datoteku pom.xml:

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

3. Razumijevanje Jinqa

Jinq nam pomaže da napišemo lakše i čitljivije upite baze podataka izlažući tečni API koji se interno temelji API Java Stream.

Pogledajmo primjer gdje filtriramo automobile prema modelu:

jinqDataProvider.streamAll (entityManager, Car.class) .where (c -> c.getModel (). jednako (model)) .toList ();

Jinq na učinkovit način prevodi gornji isječak koda u SQL upit, tako da bi konačni upit u ovom primjeru bio:

odaberite c. * iz automobila c gdje je c.model =?

Budući da ne koristimo obični tekst za pisanje upita i umjesto toga koristimo API koji je siguran za tip, ovaj je pristup manje podložan pogreškama.

Osim toga, Jinq želi omogućiti brži razvoj korištenjem uobičajenih izraza koji se lako čitaju.

Ipak, ima određena ograničenja u broju vrsta i operacija koje možemo koristiti, kao što ćemo vidjeti dalje.

3.1. Ograničenja

Jinq podržava samo osnovne tipove u JPA i konkretan popis SQL funkcija. Djeluje prevođenjem lambda operacija u izvorni SQL upit mapiranjem svih objekata i metoda u JPA tip podataka i SQL funkciju.

Stoga ne možemo očekivati ​​da će alat prevesti svaki prilagođeni tip ili sve metode tipa.

3.2. Podržani tipovi podataka

Pogledajmo podržane vrste podataka i podržane metode:

  • Nizjednako (), compareTo () samo metode
  • Primitivni tipovi podataka - aritmetičke operacije
  • Enum i prilagođene klase - podržava samo operacije == i! =
  • java.util.Collection - sadrži ()
  • Datum API - jednako (), prije(), nakon() samo metode

Napomena: ako želimo prilagoditi pretvorbu iz Java objekta u objekt baze podataka, trebamo registrirati našu konkretnu implementaciju AttributeConverter u Jinqu.

4. Integriranje Jinqa s proljećem

Jinq treba EntityManager instancu za dobivanje konteksta postojanosti. U ovom uputstvu predstavit ćemo jednostavan pristup s Springom kako bi Jinq radio s EntityManager osigurao Hibernate.

4.1. Sučelje spremišta

Spring koristi koncept spremišta za upravljanje entitetima. Pogledajmo naše CarRepository sučelje gdje imamo metodu za dohvaćanje a Automobil za zadani model:

javno sučelje CarRepository {Neobvezno findByModel (model niza); }

4.2. Repozitorij sažetih osnova

Sljedeći, trebat će nam osnovno spremište pružiti sve Jinq mogućnosti:

javna apstraktna klasa BaseJinqRepositoryImpl {@Autowired private JinqJPAStreamProvider jinqDataProvider; @PersistenceContext private EntityManager entityManager; zaštićena apstraktna klasa entityType (); javni JPAJinqStream stream () {return streamOf (entityType ()); } zaštićeni JPAJinqStream streamOf (Class clazz) {return jinqDataProvider.streamAll (entityManager, clazz); }}

4.3. Implementacija spremišta

Sad, za Jinqa trebamo samo EntityManager instance i klasa tipa entiteta.

Da vidimo Automobil implementacija spremišta koristeći naše Jinq osnovno spremište koje smo upravo definirali:

@Repository javna klasa CarRepositoryImpl proširuje BaseJinqRepositoryImpl implementira CarRepository {@Override public Neobvezna findByModel (model niza) {return stream (). Where (c -> c.getModel (). Equals (model)) .findFirst (); } @Override protected Class entityType () {return Car.class; }}

4.4. Ožičenje JinqJPAStreamProvider

Da bi se žica JinqJPAStreamProvider primjerice, mi ćemo dodajte konfiguraciju dobavljača Jinq:

@Configuration javna klasa JinqProviderConfiguration {@Bean @Autowired JinqJPAStreamProvider jinqProvider (EntityManagerFactory emf) {return new JinqJPAStreamProvider (emf); }}

4.5. Konfiguriranje proljetne aplikacije

Posljednji korak je konfigurirajte našu aplikaciju Spring koristeći Hibernate i našu Jinq konfiguraciju. Kao referencu pogledajte našu primjena.svojstva datoteka, u kojoj kao bazu podataka koristimo instancu H2 u memoriji:

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

5. Vodič za upite

Jinq nudi mnoge intuitivne mogućnosti za prilagodbu konačnog SQL upita odaberite, gdje,pridružuje i više. Imajte na umu da oni imaju ista ograničenja koja smo već uveli gore.

5.1. Gdje

The gdje klauzula omogućuje primjenu više filtara na zbirku podataka.

U sljedećem primjeru želimo filtrirati automobile prema modelu i opisu:

stream (). where (c -> c.getModel (). equals (model) && c.getDescription (). contains (desc)) .toList ();

A ovo je SQL koji Jinq prevodi:

odaberite c.model, c.opis iz automobila c gdje je c.model =? i pronađite (?, c.description)> 0

5.2. Odaberi

U slučaju da iz baze podataka želimo dohvatiti samo nekoliko stupaca / polja, trebamo koristiti Odaberi klauzula.

Kako bi mapirao više vrijednosti, Jinq nudi niz Korijen razredi s do osam vrijednosti:

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

I prevedeni SQL:

odaberite c.model, c.godinu, c.motor iz automobila c

5.3. Pridružuje se

Jinq je u stanju riješiti odnose jedan na jedan i više na jedan ako su entiteti pravilno povezani.

Na primjer, ako entitet proizvođača dodamo u Automobil:

@Entity (name = "CAR") javni razred automobila {// ... @OneToOne @JoinColumn (name = "name") javni proizvođač getManufacturer () {return proizvođač; }}

I Proizvođač entitet s popisom Automobils:

@Entity (name = "MANUFACTURER") Javna klasa Proizvođač {// ... @OneToMany (mappedBy = "model") javni popis getCars () {povratak automobila; }}

Sada smo u mogućnosti dobiti Proizvođač za zadani model:

Neobvezno proizvođač = stream (). Where (c -> c.getModel (). Jednako (model)) .select (c -> c.getManufacturer ()) .findFirst ();

Očekivano, Jinq će koristiti unutarnju SQL klauzulu pridruživanja u ovom scenariju:

odaberite m.name, m.city iz automobila c unutarnje spajanje proizvođača m na c.name = m.name gdje je c.model =?

U slučaju da trebamo imati veću kontrolu nad pridružiti klauzule kako bismo implementirali složenije odnose nad entitetima, poput relacije mnogi prema mnogima, možemo koristiti pridružiti metoda:

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

Napokon, mogli bismo koristiti lijevu vanjsku SQL klauzulu pridruživanja pomoću leftOuterJoin metoda umjesto pridružiti metoda.

5.4. Zbirke

Svi primjeri koje smo do sada uveli koriste ili izlistati ili findFirst metode - za vraćanje konačnog rezultata našeg upita u Jinqu.

Osim ovih metoda, imamo pristup i drugim metodama za prikupljanje rezultata.

Na primjer, upotrijebimo računati metoda za dobivanje ukupnog broja automobila za konkretni model u našoj bazi podataka:

long total = stream (). where (c -> c.getModel (). equals (model)) .count ()

I konačni SQL koristi računati SQL metoda prema očekivanjima:

odaberite broj (c.model) iz automobila c gdje je c.model =?

Jinq također nudi metode agregacije poput iznos, prosječno, min, maksimum, i mogućnost kombiniranja različitih agregacija.

5.5. Paginacija

U slučaju da želimo čitati podatke u serijama, možemo koristiti ograničiti i preskočiti metode.

Pogledajmo primjer gdje želimo preskočiti prvih 10 automobila i dobiti samo 20 predmeta:

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

A generirani SQL je:

odaberite c. * iz automobila c limit? offset?

6. Zaključak

Idemo tamo. U ovom smo članku vidjeli pristup postavljanju proljetne aplikacije s Jinqom koristeći Hibernate (minimalno).

Također smo ukratko istražili Jinqove prednosti i neke od njegovih glavnih značajki.

Kao i uvijek, izvore možete pronaći na GitHubu.


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