Spring Data Composable Repositories

1. Introduksjon

Når du modellerer et system eller en prosess fra den virkelige verden, er domenedrevet design (DDD) stilregister et godt alternativ. For nettopp dette formålet kan vi bruke Spring Data JPA som vårt abstraksjonslag for datatilgang.

Hvis du er ny i dette konseptet, kan du sjekke ut denne innledende opplæringen for å hjelpe deg med å få fart.

I denne opplæringen vil vi fokusere på konseptet med å lage egendefinerte så vel som komponerbare arkiver som er opprettet ved hjelp av mindre arkiver kalt fragmenter.

2. Maven-avhengigheter

Alternativet for å opprette lagringsbare arkiver er tilgjengelig fra og med våren 5.

La oss legge til den nødvendige avhengigheten for Spring Data JPA:

 org.springframework.data spring-data-jpa 2.2.2.RELEASE 

Vi trenger også å sette opp en datakilde for at datatilgangslaget vårt skal fungere. Det er en god idé å sette opp en minnedatabase som H2 for utvikling og rask testing.

3. Bakgrunn

3.1. Dvalemodus som JPA-implementering

Spring Data JPA bruker som standard dvalemodus som JPA-implementering. Vi kan lett forveksle det ene med det andre eller sammenligne dem, men de tjener forskjellige formål.

Spring Data JPA er det abstraksjonslaget for datatilgang der vi kan bruke hvilken som helst implementering. Vi kan for eksempel slå ut dvalemodus til fordel for EclipseLink.

3.2. Standardregister

I mange tilfeller trenger vi ikke skrive noen spørsmål selv.

I stedet trenger vi bare å lage grensesnitt som igjen utvider de generiske Spring datalagergrensesnittene:

offentlig grensesnitt LocationRepository utvider JpaRepository {}

Og dette i seg selv vil tillate oss å utføre vanlige operasjoner - CRUD, personsøk og sortering - på plassering objekt som har en primærnøkkel av typen Lang.

Videre er Spring Data JPA utstyrt med en spørrebyggermekanisme som gir muligheten til å generere spørsmål på våre vegne ved hjelp av metodekonvensjoner:

offentlig grensesnitt StoreRepository utvider JpaRepository {List findStoreByLocationId (Long locationId); }

3.3. Egendefinerte arkiver

Om nødvendig kan vi berike modellmagasinet vårt ved å skrive et fragmentgrensesnitt og implementere ønsket funksjonalitet. Dette kan deretter injiseres i vårt eget JPA-depot.

For eksempel, her beriker vi vårt ItemTypeRepository ved å utvide et fragmentregister:

offentlig grensesnitt ItemTypeRepository utvider JpaRepository, CustomItemTypeRepository {}

Her CustomItemTypeRepository er et annet grensesnitt:

offentlig grensesnitt CustomItemTypeRepository {void deleteCustomById (ItemType entity); }

Implementeringen kan være et arkiv av noe slag, ikke bare JPA:

offentlig klasse CustomItemTypeRepositoryImpl implementerer CustomItemTypeRepository {@Autowired private EntityManager entityManager; @ Overstyr offentlig ugyldig deleteCustomById (ItemType itemType) {entityManager.remove (itemType); }}

Vi trenger bare å sørge for at den har postfix Impl. Vi kan imidlertid angi et tilpasset postfiks ved å bruke følgende XML-konfigurasjon:

eller ved å bruke denne merknaden:

@EnableJpaRepositories (basePackages = "com.baeldung.repository", repositoryImplementationPostfix = "CustomImpl")

4. Å komponere repositorier ved hjelp av flere fragmenter

Inntil for noen utgivelser siden kunne vi bare utvide lagringsgrensesnittene våre ved å bruke en enkelt tilpasset implementering. Dette var en begrensning på grunn av hvilken vi måtte bringe all relatert funksjonalitet inn i et enkelt objekt.

Unødvendig å si, for større prosjekter med komplekse domenemodeller, fører dette til oppblåste klasser.

Nå med våren 5 har vi muligheten til å berike JPA-arkivet vårt med flere fragmentlagre. Igjen er kravet fortsatt at vi har disse fragmentene som grensesnitt-implementeringspar.

For å demonstrere dette, la oss lage to fragmenter:

offentlig grensesnitt CustomItemTypeRepository {void deleteCustom (ItemType entity); ugyldig findThenDelete (lang id); } offentlig grensesnitt CustomItemRepository {Item findItemById (Long id); ugyldig deleteCustom (elementenhet); ugyldig findThenDelete (lang id); }

Selvfølgelig må vi skrive implementeringene deres. Men i stedet for å plugge disse egendefinerte arkivene - med relaterte funksjoner - i sine egne JPA-lagringssteder, kan vi utvide funksjonaliteten til et enkelt JPA-arkiv:

offentlig grensesnitt ItemTypeRepository utvider JpaRepository, CustomItemTypeRepository, CustomItemRepository {}

Nå vil vi ha all den tilknyttede funksjonaliteten i ett enkelt depot.

5. Håndtere tvetydighet

Siden vi arver fra flere arkiver, kan det hende vi har problemer med å finne ut hvilke av implementeringene våre som vil bli brukt i tilfelle et sammenstøt. For eksempel, i vårt eksempel, har begge fragmentregister en metode, findThenDelete (), med samme signatur.

I dette scenariet, rekkefølgen på erklæringen av grensesnittene brukes til å løse tvetydigheten. Følgelig, i vårt tilfelle, metoden inni CustomItemTypeRepository vil bli brukt siden den er erklært først.

Vi kan teste dette ved å bruke denne testsaken:

@Test public void givenItemAndItemTypeWhenDeleteThenItemTypeDeleted () {Valgfri itemType = komponertRepository.findById (1L); assertTrue (itemType.isPresent ()); Vareelement = wroteRepository.findItemById (2L); assertNotNull (vare); wroteRepository.findThenDelete (1L); Valgfritt sameItemType = wroteRepository.findById (1L); assertFalse (sameItemType.isPresent ()); Element sameItem = komponertRepository.findItemById (2L); assertNotNull (sameItem); }

6. Konklusjon

I denne artikkelen tok vi en titt på de forskjellige måtene vi kan bruke Spring Data JPA repositories på. Vi så at Spring gjør det enkelt å utføre databaseoperasjoner på domeneobjektene våre uten å skrive mye kode eller til og med SQL-spørsmål.

Denne støtten kan tilpasses betydelig ved bruk av lagringsbare lagringssteder.

Kodebitene fra denne artikkelen er tilgjengelig som et Maven-prosjekt her på GitHub.


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