Увод у реактивни приступ релационим базама података са Спринг и Р2ДБЦ

Не тако давно, пуштена је реактивна варијанта ЈДБЦ управљачког програма, позната као Р2ДБЦ. Омогућава асинхрони пренос података до било којих крајњих тачака које су се претплатиле на њих. Користећи реактивни управљачки програм попут Р2ДБЦ заједно са Спрингом, ВебФлук вам омогућава да напишете потпуну апликацију која асинхроно управља примањем и слањем података.

У овом посту ћемо се фокусирати на базу података, од повезивања са базом података, а затим коначно спремања и преузимања података. Да бисмо то урадили, користићемо Спринг Дата. Као и код свих Спринг Дата модула, пружа нам конфигурацију изван оквира. Ово смањује количину основног кода коју треба да напишемо да бисмо поставили нашу апликацију. Поврх свега, пружа слој на управљачком програму базе података који олакшава обављање једноставних задатака, а теже задатке мало мање болно.

За садржај овог поста користим базу података Постгрес. У време писања овог текста, само Постгрес, Х2 и Мицрософт СКЛ Сервер имају сопствене имплементације Р2ДБЦ управљачких програма.

Претходно сам написао два поста о реактивним библиотекама Спринг Дата, један о Монгу и други о Цассандри. Можда сте приметили да ниједна од ових база података није РДБМС база података. Сада постоје и други реактивни покретачки програми (писао сам пост у Монго пре скоро две године), али у време писања реактивног покретачког програма за базу података РДБМС још увек је прилично нова ствар. Овај пост ће слиједити формат сличан онима.

Даље, такође сам написао пост о коришћењу Спринг ВебФлук-а који сам споменуо у уводу. Слободно погледајте то ако сте заинтересовани за производњу потпуно реактивне веб апликације.

Зависности

Овде треба истаћи неколико ствари.

Што више користите Спринг Боот, то ћете се више навикавати на увоз једне spring-boot-starterзависности за ону цоол ствар коју желите да урадите. На пример, надао сам се да би постојала spring-boot-starter-r2dbcзависност, али нажалост, не постоји. Ипак.

Једноставно речено, ова библиотека је на новијој страни и у време писања овог чланка нема свој модул Спринг Боот који садржи све зависности које су му потребне, заједно са бржим подешавањем путем аутоматске конфигурације. Сигуран сам да ће ове ствари кад-тад доћи и учинити подешавање Р2ДБЦ управљачког програма још лакшим.

За сада ћемо морати ручно да попунимо неколико додатних зависности.

Даље, Р2ДБЦ библиотеке имају само издања Милестоне (још доказа да су нова), тако да морамо осигурати да унесемо спремиште Спринг Милестоне. Вероватно ћу морати да ажурирам овај пост у будућности када добије верзију за издање.

Повезивање са базом података

Захваљујући Спринг Дата-у који за нас ради пуно посла, једини Беан који треба ручно креирати је онај ConnectionFactoryкоји садржи детаље везе базе података:

Прво што овде треба приметити је проширење AbstractR2dbcConfiguration. Ова класа садржи хрпу пасуља који више не морамо ручно да креирамо. Имплементација connectionFactoryје једини захтев класе јер је потребна за креирање DatabaseClientБеан-а. Оваква структура је типична за Спринг Дата модуле, тако да се чини прилично познатом када испробавате другу. Штавише, очекивао бих да ће се ова ручна конфигурација уклонити када буде доступна аутоматска конфигурација и да ће се покретати искључиво путем application.properties.

Овде сам уврстио portсвојство, али ако се нисте поиграли са вашом Постгрес конфигурацијом, можете се ослонити на подразумевану вредност 5432.

Четири својства: host, database, usernameа passwordдефинисан је PostgresqlConnectionFactoryсу минимум то се ради. Све мање и имаћете изузетака током покретања.

Коришћењем ове конфигурације Спринг може да се повеже са покренутом инстанцом Постгрес.

Последња информација вредна пажње из овог примера је употреба @EnableR2dbcRepositories. Ова напомена наводи Спринг да пронађе било који интерфејс спремишта који проширује Спрингов Repositoryинтерфејс. Ово се користи као основни интерфејс за инструментацију спремишта Спринг Дата. Ово ћемо погледати мало ближе у следећем одељку. Главна информација коју ћете одавде одузети је та да морате да користите @EnableR2dbcRepositoriesнапомену да бисте у потпуности искористили могућности Спринг Дата-а.

Креирање пролећног спремишта података

Као што је горе дотакнуто, у овом одељку ћемо погледати додавање Спринг Дата Репоситори-а. Ова спремишта су лепа карактеристика Спринг Дата-а, што значи да вам није потребно исписати пуно додатног кода да бисте једноставно написали упит.

Нажалост, бар за сада Спринг Р2ДБЦ не може да изводи упите на исти начин на који то тренутно раде други модули Спринг Дата (сигуран сам да ће то бити додато у једном тренутку). То значи да ћете морати да користите @Queryнапомену и да ручно напишете СКЛ. Хајде да погледамо:

Овај интерфејс се проширује R2dbcRepository. Ово се заузврат протеже, ReactiveCrudRepositoryа затим све до Repository. ReactiveCrudRepositoryпружа стандардне ЦРУД функције и, колико сам разумео, R2dbcRepositoryне пружа никакве додатне функције и уместо тога је интерфејс створен за боље именовање ситуације.

R2dbcRepositoryузима два генеричка параметра, један је класа ентитета који узима као улаз и производи као излаз. Други је тип примарног кључа. Стога у овој ситуацији, Personкласом управља PersonRepository(има смисла), а поље Примарни кључ унутар Personје Int.

Повратни типови функција у овој класи и они које пружају ReactiveCrudRepositoryјесу Fluxи Mono(нису овде приказани). То су типови Пројецт Реацтор-а које Спринг користи као подразумеване типове реактивног тока. Fluxпредставља ток више елемената док Monoје а један резултат.

Коначно, као што сам споменуо пре примера, свака функција је означена са @Query. Синтакса је прилично исправна, а СКЛ је низ унутар напомене. $1( $2, $3Итд ... За више улаза) представља улазна вредност у функцији. Једном када то учините, Спринг ће се позабавити остатком и прослиједити улаз (е) у њихов одговарајући улазни параметар, прикупити резултате и мапирати их у класу ентитета назначену у спремишту.

Врло брз поглед на ентитет

Овде нећу рећи пуно, већ једноставно показати Personкласу коју користи PersonRepository.

Заправо, овде треба истаћи једну ствар. idје поништено и обезбеђена је подразумевана вредност nullкоја омогућава Постгресу да сам генерише следећу одговарајућу вредност. Ако ово није нулл и ако idје наведена вредност, Спринг ће заправо покушати да изврши исправку уместо уметка након спремања. Постоје и други начини око тога, али мислим да је ово довољно добро.

Овај ентитет ће се мапирати у peopleдоњу дефинисану табелу:

Видевши све то на делу

Хајде сада да погледамо како то заправо нешто ради. Испод је неки код који убацује неколико записа и преузима их на неколико различитих начина:

Једну ствар коју ћу споменути у вези са овим кодом. Постоји врло стварна могућност да се изврши без стварног уметања или читања неких записа. Али, кад боље размислите, то има смисла. Реактивне апликације треба да раде ствари асинхроно и зато је ова апликација започела обраду позива функције у различитим нитима. Без блокирања главне нити, ови асинхрони процеси се можда никада неће у потпуности извршити. Из овог разлога Thread.sleepу овом коду има неколико позива, али сам их уклонио из примера да све буде уредно.

Излаз за покретање горњег кода изгледао би отприлике као доле:

[ main] onSubscribe(FluxConcatMap.ConcatMapImmediate)[ main] request(unbounded)[actor-tcp-nio-1] onNext(Person(id=35, name=Dan Newton, age=25))[actor-tcp-nio-1] onNext(Person(id=36, name=Laura So, age=23))[actor-tcp-nio-1] onComplete()[actor-tcp-nio-2] findAll - Person(id=35, name=Dan Newton, age=25)[actor-tcp-nio-2] findAll - Person(id=36, name=Laura So, age=23)[actor-tcp-nio-4] findAllByName - Person(id=36, name=Laura So, age=23)[actor-tcp-nio-5] findAllByAge - Person(id=35, name=Dan Newton, age=25)

Неколико ствари које треба одузети овде:

  • onSubscribe and request occur on the main thread where the Flux was called from. Only saveAll outputs this since it has included the log function. Adding this to the other calls would have lead to the same result of logging to the main thread.
  • The execution contained within the subscribe function and the internal steps of the Flux are run on separate threads.

This is not anywhere close to a real representation of how you would use Reactive Streams in an actual application but hopefully demonstrates how to use them and gives a bit of insight into how they execute.

Conclusion

Закључно, реактивни токови су дошли до неких база података РДБМС-а захваљујући управљачком програму Р2ДБЦ и Спринг Дата који граде слој на врху да би све било мало уредније. Коришћењем Спринг Дата Р2ДБЦ у могућности смо да створимо везу са базом података и почнемо да је питамо без потребе за превише кода.

Иако Пролеће већ чини много за нас, могло би и више. Тренутно нема подршку за аутоматско подешавање Спринг Боот-а. Што је помало досадно. Али, сигуран сам да ће се неко ускоро забавити и учинити све још бољим него што већ јесте.

Код кориштен у овом посту може се наћи на мом ГитХуб-у.

Ако вам је овај пост био користан, можете ме пратити на Твиттер-у на @ЛанкиДанДев да бих пратио моје нове постове.

Погледајте све поруке аутора Дан Невтон

Првобитно објављено на ланкиданблог.цом 16. фебруара 2019.