{"id":387554,"date":"2024-06-29T07:23:15","date_gmt":"2024-06-29T07:23:15","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=387554"},"modified":"-0001-11-30T00:00:00","modified_gmt":"2024-06-29T07:23:15","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=387554","title":{"rendered":"<span>\u041f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0439 \u043e\u0431\u043c\u0435\u043d \u0432 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0432 \u043d\u0435\u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445: \u043e\u043f\u044b\u0442 \u00ab\u041c\u0430\u0433\u043d\u0438\u0442\u0430\u00bb<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/4d3\/1f5\/426\/4d31f5426974959ff060d0255cd40a55.jpg\" width=\"1800\" height=\"1100\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/4d3\/1f5\/426\/4d31f5426974959ff060d0255cd40a55.jpg\" data-blurred=\"true\"\/><\/figure>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041d\u0430\u00a0\u0441\u0432\u044f\u0437\u0438 \u0410\u043d\u0434\u0440\u0435\u0439 \u0417\u044f\u0431\u043b\u0438\u043d, Java \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u00ab\u041c\u0430\u0433\u043d\u0438\u0442\u00bb. \u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043b\u0435\u0442 \u043d\u0430\u0437\u0430\u0434, \u043f\u0440\u043e\u0434\u043b\u044f\u044f \u0434\u043e\u0447\u0435\u0440\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 \u043d\u0430\u00a0Netflix, \u044f \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b\u0441\u044f, \u043a\u0430\u043a\u00a0\u043e\u043d\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0442\u0435\u043d \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432. \u0418\u0437\u0443\u0447\u0438\u0432 \u0432\u043e\u043f\u0440\u043e\u0441, \u044f \u0443\u0432\u043b\u0451\u043a\u0441\u044f \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u043c \u0432\u00a0\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438. \u0427\u0435\u0440\u0435\u0437 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u044d\u0442\u043e \u0443\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043d\u0435\u0441\u043b\u043e \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043f\u043e\u043b\u044c\u0437\u0443 \u043f\u0440\u0438\u00a0\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0432 \u00ab\u041c\u0430\u0433\u043d\u0438\u0442\u0435\u00bb. \u0412\u00a0\u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e\u00a0\u0442\u0440\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0439 \u043e\u0431\u043c\u0435\u043d \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0437\u00a0\u0411\u0414 \u043c\u0435\u0436\u0434\u0443 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438: <\/p>\n<ol>\n<li>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c hibernate <\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c mybatis <\/p>\n<\/li>\n<li>\n<p>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043e\u0431\u043c\u0435\u043d\u0430 \u0441\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u0434\u0430\u0432\u043b\u0435\u043d\u0438\u044f (\u00abbackpressure\u00bb) \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 Bucket4j <\/p>\n<\/li>\n<\/ol>\n<h2>\u041f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0434\u0430\u0447\u0438<\/h2>\n<p>\u041d\u0430\u0448\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f\u00a0\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0435\u0442\u0438, \u0430\u00a0\u0442\u0430\u043a\u0436\u0435 \u0434\u043b\u044f\u00a0\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441\u00a0\u0433\u043e\u0441\u0443\u0434\u0430\u0440\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438 \u0432\u00a0\u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u0435\u0442\u0435\u0440\u0438\u043d\u0430\u0440\u0438\u0438 \u00ab\u0412\u0435\u0442\u0418\u0421\u00bb. <\/p>\n<p>\u0423\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a: <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/48c\/cbf\/68e\/48ccbf68e9d6d3b61f4033d31bd8f80c.png\" width=\"1213\" height=\"624\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/48c\/cbf\/68e\/48ccbf68e9d6d3b61f4033d31bd8f80c.png\"\/><\/figure>\n<p>\u0411\u0438\u0437\u043d\u0435\u0441\u2011\u0437\u0430\u043f\u0440\u043e\u0441\u044b\u00a0\u2014 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432\u00a0\u0444\u043e\u0440\u043c\u0430\u0442\u0435 json, \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u043b\u044f\u00a0\u043e\u0431\u043c\u0435\u043d\u0430 \u043d\u0430\u00a0\u0443\u0440\u043e\u0432\u043d\u0435 \u0431\u0438\u0437\u043d\u0435\u0441\u2011\u0434\u0430\u043d\u043d\u044b\u0445 (\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438, \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u043f\u0440.) \u0438 \u0440\u0430\u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0432\u00a0\u0431\u043e\u043b\u0435\u0435 \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432\u00a0\u0444\u043e\u0440\u043c\u0430\u0442\u0430\u0445, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u0433\u043e\u0441\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438. <\/p>\n<p>\u0426\u0421\u041c (\u0426\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0441\u0435\u0442\u0438 \u00ab\u041c\u0435\u0440\u043a\u0443\u0440\u0438\u0439\u00bb)\u00a0\u2014 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u043d\u0430\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438.<\/p>\n<p>BDSM\u2011CLIENT\u00a0\u2014 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441\u00a0\u0431\u0438\u0437\u043d\u0435\u0441\u2011\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u0411\u0414 \u0421\u041c (\u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0435\u0442\u0438 \u043c\u0430\u0433\u0430\u0437\u0438\u043d\u043e\u0432). <\/p>\n<p>MERCURY\u00a0\u2014 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441\u043e \u0448\u043b\u044e\u0437\u043e\u043c \u043a \u00ab\u0412\u0435\u0442\u0418\u0421\u00bb. <\/p>\n<p>PROCESSING\u00a0\u2014 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0431\u0438\u0437\u043d\u0435\u0441\u2011\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0434\u043e\u00a0\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432\u00a0\u0448\u043b\u044e\u0437. <\/p>\n<p>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u043d\u044b\u043c \u043c\u0435\u0441\u0442\u043e\u043c \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437\u00a0\u0426\u0421\u041c \u0432\u00a0\u0411\u0414 \u0421\u041c: \u043e\u0431\u044a\u0451\u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0433\u0440\u043e\u043c\u043d\u044b, \u0430\u00a0\u043d\u0430\u00a0\u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0411\u0414 \u0421\u041c \u043d\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u043b\u0441\u044f \u0442\u043e\u043d\u043a\u0438\u0439 \u043a\u043b\u0438\u0435\u043d\u0442, \u043f\u0438\u0448\u0443\u0449\u0438\u0439 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432\u00a0\u0431\u0430\u0437\u0443. <\/p>\n<p><strong>\u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u043e\u0431\u043c\u0435\u043d\u0443:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0414\u0430\u043d\u043d\u044b\u0435 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u044e\u0442\u0441\u044f \u0438\u0437\u00a0\u0411\u0414<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u044a\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0445\u00a0\u2014 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u044b \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0437\u0430\u00a0\u0441\u0435\u0430\u043d\u0441 <\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0432\u0435\u0434\u0451\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u043f\u043e\u00a0http <\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c ORM <\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0437\u0443\u0447\u0438\u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438, \u043c\u044b \u043f\u0440\u0438\u0448\u043b\u0438 \u043a\u00a0\u043c\u043d\u0435\u043d\u0438\u044e, \u0447\u0442\u043e\u00a0\u0432\u00a0\u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c. <\/p>\n<p><strong>\u0414\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0426\u0421\u041c \u0438 \u0411\u0414 \u0421\u041c<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0412\u00a0\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u0426\u0421\u041c \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434 \u043e\u0431\u043c\u0435\u043d\u0430<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f\u00a0\u043f\u0440\u0438\u0451\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430\u00a0\u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0411\u0414 \u0421\u041c \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438<\/strong>:<\/p>\n<ul>\n<li>\n<p>Java streams\u00a0<\/p>\n<\/li>\n<li>\n<p>Hibernate streamResult\u00a0<\/p>\n<\/li>\n<li>\n<p>Reactive streams\u00a0<\/p>\n<\/li>\n<li>\n<p>Spring webflux(reactor)\u00a0<\/p>\n<\/li>\n<li>\n<p>Spring webclient\u00a0<\/p>\n<\/li>\n<li>\n<p>Rsocket (\u0434\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438)\u00a0<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0413\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f:<\/strong><\/p>\n<ul>\n<li>\n<p>\u041d\u0435\u00a0\u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c R2DBC. \u041d\u0430\u00a0\u043c\u043e\u043c\u0435\u043d\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u043b\u044f\u00a0Oracle \u043d\u0435\u00a0\u0431\u044b\u043b\u043e \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430. <\/p>\n<\/li>\n<li>\n<p>Hibernate streamResult \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0430\u043a\u0442\u0438\u0432\u043d\u0443\u044e \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044e \u043d\u0430\u00a0\u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f \u0444\u0435\u0442\u0447\u0430. \u041d\u0443\u0436\u043d\u043e \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0444\u0435\u0442\u0447\u0430, \u043e\u0448\u0438\u0431\u043a\u0438, \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044e. \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432\u00a0\u0432\u0438\u0434\u0435 try\u2011catch \u043d\u0435\u00a0\u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0442 \u0432\u00a0\u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<\/ul>\n<h2>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c hibernate<\/h2>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u043b\u0430\u0441\u044c \u0432\u00a0\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441\u00a0\u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f\u043c\u0438 \u0432\u00a0\u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435. \u0414\u043b\u044f\u00a0\u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u0431\u043b\u0430\u0433\u043e Reactor \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442. \u041e\u0441\u043d\u043e\u0432\u0443 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442: <\/p>\n<ul>\n<li>\n<p>Stateless session\u00a0<\/p>\n<\/li>\n<li>\n<p>StreamResult\u00a0<\/p>\n<\/li>\n<li>\n<p>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f Flux \u0438\u0437 Stream\u00a0<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u043e\u0434.\u00a0<\/p>\n<h4>\u0421\u0443\u0449\u043d\u043e\u0441\u0442\u0438<\/h4>\n<ul>\n<li>\n<p>Customer \u2014 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a\u043e\u0432.\u00a0<\/p>\n<\/li>\n<li>\n<p>Operation \u2014 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a\u0430\u043c\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u043e\u0434\u0430\u0436\u0438.\u00a0<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"java\">public class Customer {        @Id      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = \"sequence\")      @SequenceGenerator(name = \"sequence\", sequenceName = \"SQ_CUSTOMER\", allocationSize = 1)      private Long id;        @Column(name = \"NAME\")      private String name;    }  public class Operation {        @Id      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = \"sequence\")      @SequenceGenerator(name = \"sequence\", sequenceName = \"SQ_OPERATION\", allocationSize = 1)      private Long id;        @Column(name = \"TOTAL_SUM\")      private Long totalSum;        @ManyToOne      @JoinColumn(name = \"customer_id\")      private Customer customer;        @ManyToMany      @JoinTable(          name = \"operation_detail\",          joinColumns = @JoinColumn(name = \"operation_id\"),          inverseJoinColumns = @JoinColumn(name = \"product_id\"))      private List&lt;Product> products;    }   <\/code><\/pre>\n<h4>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445\u00a0<\/h4>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430 \u0438 \u043d\u0435\u00a0\u0441\u043e\u0432\u0441\u0435\u043c \u0438\u043c\u0435\u0435\u0442 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043a\u00a0\u0442\u0435\u043c\u0435 \u0441\u0442\u0430\u0442\u044c\u0438, \u0437\u0434\u0435\u0441\u044c \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043c\u043e\u0449\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041d\u0430\u00a0\u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 reactor \u0438 \u043a\u0430\u043a\u00a0\u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443.<\/p>\n<p><u>\u041a\u043b\u0430\u0441\u0441 com.magnit.flux.common.service.InitDataService<\/u><\/p>\n<pre><code class=\"java\">private void fillCustomer() {      Flux.range(0, CUSTOMER_RECORD_LIMIT)          .map(i -> Customer.builder().name(\"Customer \" + i).build())          .subscribe(customerRepository::save);  }    private void fillProduct() {      Flux.range(0, PRODUCT_RECORD_LIMIT)          .map(i -> Product.builder().name(\"Product \" + i).build())          .subscribe(productRepository::save);  }    private void fillOperation() {      Supplier&lt;List&lt;Product>> productSupplier = () -> new Random().ints(5, 1, 8)          .boxed().distinct()          .map(productId -> Product.builder().id((long) productId).build())          .collect(Collectors.toList());      List&lt;Customer> customers = (List&lt;Customer>) customerRepository.findAll();      Flux.range(0, OPERATION_RECORD_LIMIT)          .map(i -> Operation.builder()              .totalSum((long) random.nextInt(100))              .customer(customers.get(random.nextInt(customers.size() - 1)))              .products(productSupplier.get())              .build())          .buffer(1000)          .subscribe(operationRepository::saveAll);  } <\/code><\/pre>\n<h4>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 hibernate \u0434\u043b\u044f \u0441\u0442\u0440\u0438\u043c\u0438\u043d\u0433\u0430\u00a0<\/h4>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u043e\u00a0\u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f\u043c\u0438 \u0432\u00a0\u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435. \u042d\u0442\u043e \u0447\u0442\u043e\u2011\u0442\u043e \u0432\u0440\u043e\u0434\u0435 AutoCloseable \u0432\u00a0\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445. <\/p>\n<p><u>\u041a\u043b\u0430\u0441\u0441 com.magnit.flux.hibernate.dao.HibernateFluxResultProducer<\/u><\/p>\n<pre><code class=\"java\">@RequiredArgsConstructor  public class HibernateFluxResultProducer&lt;T> {           private final EntityManagerFactory entityManagerFactory;        private StatelessSession statelessSession;        \/**       * \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 hql \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 Flux \u0438\u0437 Result Stream       *\/      public Flux&lt;T> execute(String qlString, Class&lt;T> resultClass) {          Optional.ofNullable(statelessSession).ifPresent(e -> {              throw new RuntimeException(\"Cursor already open\");          });          val sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);          \/\/\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Stateless Session \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0447\u0442\u0435\u043d\u0438\u0435 \u0437\u0430 \u0441\u0447\u0451\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f detached \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432          statelessSession = sessionFactory.openStatelessSession();          statelessSession.getTransaction().begin();          val query = statelessSession.createQuery(qlString, resultClass);          \/\/\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c hibernate \u0434\u043b\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0433\u043e \u0447\u0442\u0435\u043d\u0438\u044f \u0438\u0437 \u0411\u0414 - getResultStream          return Flux.fromStream(query.getResultStream());      }        public Mono&lt;Void> commit() {          return close(true);      }        public Mono&lt;Void> rollback() {          return close(false);      }        public Mono&lt;Void> close(boolean commitTran) {          if (statelessSession.getTransaction().isActive()) {              if (commitTran) {                  statelessSession.getTransaction().commit();              } else {                  statelessSession.getTransaction().rollback();              }            }          statelessSession.close();          return Mono.empty();      }      } <\/code><\/pre>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u0442 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044e \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 hql \u0437\u0430\u043f\u0440\u043e\u0441. \u0422\u0430\u043a\u0436\u0435 \u043e\u043d \u0438\u043c\u0435\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u044b commit \u0438 rollback. <\/p>\n<h4>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u0441 hibernate\u00a0<\/h4>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u00a0\u043f\u043e\u0442\u043e\u043a\u0430\u043c\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0432\u00a0\u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 getOperationFlux. \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u0442\u043e\u043a\u0430 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0430 Flux.usingWhen, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u043c AutoCloseable. \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0432\u0430 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430: <\/p>\n<ul>\n<li>\n<p>getOperationsStream \u2014 json \u0441\u0442\u0440\u0438\u043c\u0438\u043d\u0433\u00a0<\/p>\n<\/li>\n<li>\n<p>getOperationsWs \u2014 \u0432\u0435\u0431-\u0441\u043e\u043a\u0435\u0442\u00a0<\/p>\n<\/li>\n<\/ul>\n<p><u>\u041a\u043b\u0430\u0441\u0441 com.magnit.flux.hibernate.controller.HibernateOperationController<\/u><\/p>\n<pre><code class=\"java\">public class HibernateOperationController {        private final ObjectFactory&lt;HibernateFluxResultProducer&lt;Operation>> streamResultProducerObjectFactory;        @GetMapping(path = \"\/operations-stream\", produces = \"application\/stream+json\")      public Flux&lt;Operation> getOperationsStream() {          return getOperationFlux();      }        @MessageMapping(\"operations\")      public Flux&lt;Operation> getOperationsWs() {          return getOperationFlux();      }        private Flux&lt;Operation> getOperationFlux() {          Mono&lt;HibernateFluxResultProducer&lt;Operation>> streamResultExecutorMono = Mono              .just(streamResultProducerObjectFactory.getObject());          return Flux.usingWhen(streamResultExecutorMono,              se -> se.execute(\"select o from Operation o JOIN FETCH o.customer c\", Operation.class),              HibernateFluxResultProducer::commit);      }    } <\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432\u00a0\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435: <\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/12a\/dd2\/7fe\/12add27fe8a9988033c4a251b7f6e9d0.png\" width=\"700\" height=\"234\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/12a\/dd2\/7fe\/12add27fe8a9988033c4a251b7f6e9d0.png\"\/><\/figure>\n<p>\u041c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u043b\u0438\u00a0\u0434\u0430\u0436\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0431\u0440\u0430\u0443\u0437\u0435\u0440. \u041c\u043e\u0436\u043d\u043e \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u00a0\u043c\u0435\u0442\u043e\u0434 close \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f. <\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/18f\/63f\/8d4\/18f63f8d441a6e693d612ad9269cecec.png\" width=\"492\" height=\"108\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/18f\/63f\/8d4\/18f63f8d441a6e693d612ad9269cecec.png\"\/><\/figure>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u043c\u0435\u0442\u043e\u0434\u00a0\u2014 \u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0441\u043d\u044b\u0439. \u041d\u0430\u00a0\u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u0435 \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u043c\u0435\u043d \u043f\u043e\u00a0\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 Rsocket. \u0414\u043b\u044f\u00a0\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Rsocket \u043a\u043b\u0438\u0435\u043d\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u043d\u0430\u00a0javascript. \u0422\u0430\u043a\u0436\u0435 \u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 backpressure (\u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u0434\u0430\u0432\u043b\u0435\u043d\u0438\u0435). <\/p>\n<p><u>statis\/index.js<\/u><\/p>\n<pre><code class=\"java\">client.connect().subscribe({      onError: error => console.error(error),      onSubscribe: cancel => {      },      onComplete: socket => {          socket.requestStream({              data: null,              metadata: String.fromCharCode(\"operations\".length) + \"operations\"          })          .subscribe({              onComplete: () => console.log(\"requestStream done\"),              onError: error => {                  console.log(\"got error with requestStream\");                  console.error(error);              },              onNext: value => {                  document.getElementById(                      \"operation\").innerText = \"Operation ID: \"                      + value.data.id + \". Customer: \" + value.data.customer.name;                  \/\/\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u043c \u0434\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u041c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043d\u0430 \u043f\u0430\u0443\u0437\u0443 (\u0444\u0443\u043d\u043a\u0446\u0438\u044f pause), \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0447\u0442\u0435\u043d\u0438\u0435 (\u0444\u0443\u043d\u043a\u0446\u0438\u044f suspend)                  if (!paused) {                      subscription.request(1);                  }              },              onSubscribe: sub => {                  subscription = sub;                  subscription.request(1);              }          });      }  }); <\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.\u00a0<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/b8f\/bf0\/f1b\/b8fbf0f1bea5a9b165bb23fdb4d25125.png\" width=\"570\" height=\"200\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/b8f\/bf0\/f1b\/b8fbf0f1bea5a9b165bb23fdb4d25125.png\"\/><\/figure>\n<p>\u041a\u043d\u043e\u043f\u043a\u0438 Pause \u0438 Suspend \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u044c \u0438 \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0443 \u043f\u043e\u0442\u043e\u043a\u0430.\u00a0<\/p>\n<h2>\u041e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u043e\u0434\u0438\u043d \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c \u0438 \u043c\u043d\u043e\u0433\u0438\u0435 \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c (OneToMany &amp;ManyToMany)\u00a0<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0447\u0430\u0441\u0442\u0443\u044e \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e, \u043a\u043e\u0433\u0434\u0430 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a\u0430 \u0432\u044b\u0434\u0432\u0438\u0433\u0430\u044e\u0442\u0441\u044f \u043d\u043e\u0432\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f. \u0412\u00a0\u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0443\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440: \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a \u0432\u044b\u0434\u0432\u0438\u043d\u0443\u043b \u043d\u043e\u0432\u044b\u0435 \u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u00a0\u043e\u0431\u043c\u0435\u043d\u0443: \u0442\u0435\u043f\u0435\u0440\u044c \u043d\u0443\u0436\u043d\u043e \u0432\u044b\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0442\u043e\u0432\u0430\u0440\u044b, \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0449\u0438\u0435\u0441\u044f \u0432\u00a0\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u0445. \u0422\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u044d\u0442\u043e \u043c\u043e\u0436\u043d\u043e \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438 \u0441\u00a0hibernate, \u043d\u043e\u00a0\u0432\u043e\u0437\u043d\u0438\u043a\u0430\u044e\u0442 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u044b \u0441\u00a0\u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c\u044e. \u041a\u0430\u043a\u00a0\u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0443 \u043c\u044b \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043b\u0438 MyBatis. \u041d\u0438\u0436\u0435 \u0441\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u0435\u043c MyBatis \u0438 hiberabte. <\/p>\n<h4>MyBatis \u043a\u0430\u043a \u0431\u043e\u043b\u0435\u0435 \u0431\u044b\u0441\u0442\u0440\u0430\u044f \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 hibernate<\/h4>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<p align=\"left\"><strong>MyBatis<\/strong>\u00a0<\/p>\n<\/td>\n<td>\n<p align=\"left\"><strong>Hibernate<\/strong>\u00a0<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041f\u0440\u043e\u0441\u0442\u0430\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430, \u0442\u0430\u043a \u043a\u0430\u043a \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442 \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u0438\u0435 SQL \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432\u00a0<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0420\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0431\u043e\u043b\u0435\u0435 \u0441\u043b\u043e\u0436\u043d\u0430\u044f, \u0442\u0430\u043a \u043a\u0430\u043a hibernate \u0431\u043e\u043b\u0435\u0435 \u0433\u0440\u043e\u043c\u043e\u0437\u0434\u043a\u0438\u0439 \u0438 \u0441\u043b\u043e\u0436\u043d\u044b\u0439 \u0434\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f\u00a0<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">MyBatis \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 SQL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0411\u0414\u00a0<\/p>\n<\/td>\n<td>\n<p align=\"left\">Hibernate \u0432 \u043e\u0431\u0449\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0411\u0414\u00a0<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u0435 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u044b, \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e \u0441 \u043a\u0443\u0440\u0441\u043e\u0440\u0430\u043c\u0438 \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 out \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432\u00a0<\/p>\n<\/td>\n<td>\n<p align=\"left\">\u0412 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0441\u043b\u0443\u0447\u0430\u044f\u0445 \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u0435 \u043f\u0440\u043e\u0446\u0435\u0434\u0443\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043d\u0435\u043f\u0440\u043e\u0441\u0442\u043e\u00a0<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u0422\u0430\u043a \u043a\u0430\u043a SQL \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0411\u0414, \u0431\u0430\u0437\u0443 \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u043c\u0435\u043d\u0438\u0442\u044c \u043e\u0447\u0435\u043d\u044c \u0441\u043b\u043e\u0436\u043d\u043e\u00a0<\/p>\n<\/td>\n<td>\n<p align=\"left\">Hibernate \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043b\u0435\u0433\u043a\u043e \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u0411\u0414\u00a0<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">\u041c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0432 Mybatis \u043d\u0435 \u0440\u0430\u0437\u0432\u0438\u0442\u044b\u00a0<\/p>\n<\/td>\n<td>\n<p align=\"left\">Hibernate \u0438\u043c\u0435\u0435\u0442 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448\u0438\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u044b \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f\u00a0<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p align=\"left\">MyBatis \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u00ab\u043e\u0434\u0438\u043d \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c\u00bb \u0438 \u00ab\u043c\u043d\u043e\u0433\u0438\u0435 \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c\u00bb \u0432 \u0441\u0442\u0440\u0438\u043c\u0430\u0445\u00a0<\/p>\n<\/td>\n<td>\n<p align=\"left\">Hibernate \u043d\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u043e\u0434\u0438\u043d \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c \u0438 \u043c\u043d\u043e\u0433\u0438\u0435 \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c \u0432 \u0441\u0442\u0440\u0438\u043c\u0430\u0445\u00a0<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0432\u0430\u0436\u043d\u0430 \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c MyBatis \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u044f \u043e\u0434\u0438\u043d \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c \u0438 \u043c\u043d\u043e\u0433\u0438\u0435 \u043a\u043e \u043c\u043d\u043e\u0433\u0438\u043c \u0432 \u0441\u0442\u0440\u0438\u043c\u0430\u0445.\u00a0<\/p>\n<h4>\u0421\u0442\u0440\u0438\u043c\u0438\u043d\u0433 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 MyBatis\u00a0<\/h4>\n<ul>\n<li>\n<p>\u0412 MyBatis 3.4.0 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d \u0442\u0438\u043f \u043a\u0443\u0440\u0441\u043e\u0440 \u2014 org.apache.ibatis.cursor.Cursor, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441\u0443 Resultset \u0432 JDBC\u00a0<\/p>\n<\/li>\n<li>\n<p>\u041a\u0443\u0440\u0441\u043e\u0440 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u0442 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0438\u0442\u0435\u0440\u0430\u0442\u043e\u0440\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0435\u0433\u043e \u043e\u0447\u0435\u043d\u044c \u043f\u0440\u043e\u0441\u0442\u043e\u00a0<\/p>\n<\/li>\n<li>\n<p>\u041a\u0443\u0440\u0441\u043e\u0440 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u0438 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430\u0445, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0439 one-to-many \u0438 many-to-many\u00a0<\/p>\n<\/li>\n<\/ul>\n<h4>\u0418\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0432 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u044f\u0445\u00a0<\/h4>\n<ul>\n<li>\n<p>Product \u2014 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a \u043f\u0440\u043e\u0434\u0443\u043a\u0446\u0438\u0438\u00a0<\/p>\n<\/li>\n<li>\n<p>Operation \u2014 \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0430\u0441\u044c \u0441\u0432\u044f\u0437\u044c <a class=\"mention\" href=\"\/users\/ManyToMany\">@ManyToMany<\/a> \u0441\u043e \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a\u043e\u043c \u043f\u0440\u043e\u0434\u0443\u043a\u0446\u0438\u0438\u00a0<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"java\">@Entity  @Table(name = \"PRODUCT\")  @Getter  @Setter  @Builder  @NoArgsConstructor  @AllArgsConstructor  @ToString  public class Product {        @Id      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = \"sequence\")      @SequenceGenerator(name = \"sequence\", sequenceName = \"SQ_OPERATION_DETAIL\", allocationSize = 1)      private Long id;        @Column(name = \"NAME\")      private String name;    }        @ManyToMany  @JoinTable(      name = \"operation_detail\",      joinColumns = @JoinColumn(name = \"operation_id\"),      inverseJoinColumns = @JoinColumn(name = \"product_id\"))  private List&lt;Product> products; <\/code><\/pre>\n<h4>\u041c\u0430\u043f\u043f\u0438\u043d\u0433 \u0441\u0443\u0449\u043d\u043e\u0441\u0442\u0435\u0439\u00a0<\/h4>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0442\u043e\u043d\u043a\u043e\u0441\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u044b \u0441 MyBatis \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u043c\u0430\u043f\u043f\u0438\u043d\u0433\u0435\u00a0.<\/p>\n<pre><code class=\"java\">&lt;mapper namespace=\"com.magnit.flux.mybatis.mapper.OperationMapper\">        &lt;select id=\"getAllOperations\" resultMap=\"operationResult\" resultOrdered=\"true\">          select d.operation_id id, d.product_id, p.name product_name from operation_detail d inner          join product p on p.id = d.product_id order by d.operation_id      &lt;\/select>          &lt;resultMap id=\"operationResult\" type=\"com.magnit.flux.model.entity.Operation\">          &lt;id property=\"id\" column=\"id\"\/>          &lt;collection property=\"products\" ofType=\"com.magnit.flux.model.entity.Product\">              &lt;id property=\"id\" column=\"product_id\"\/>              &lt;result property=\"name\" column=\"product_name\"\/>          &lt;\/collection>      &lt;\/resultMap>    &lt;\/mapper><\/code><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c getAllOperations \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442 \u043e\u0442\u0441\u043e\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430\u0431\u043e\u0440 \u0434\u0430\u043d\u043d\u044b\u0445 (resultOrdered=\u201dtrue\u201d), \u0430 MyBatis \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u043e\u043c \u0433\u0440\u0443\u043f\u043f\u0438\u0440\u0443\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u043e operation.id \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 \u0432\u043b\u043e\u0436\u0435\u043d\u043d\u044b\u043c\u0438 \u043a\u043e\u043b\u043b\u0435\u043a\u0446\u0438\u044f\u043c\u0438 \u043f\u0440\u043e\u0434\u0443\u043a\u0446\u0438\u0438.\u00a0<\/p>\n<h4>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 MyBatis \u0434\u043b\u044f \u0441\u0442\u0440\u0438\u043c\u0438\u043d\u0433\u0430\u00a0<\/h4>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b\u0439 HibernateFluxResultProducer. \u041e\u043d \u0438\u043c\u0435\u0435\u0442 \u043f\u0430\u0440\u0443 \u043e\u0442\u043b\u0438\u0447\u0438\u0439:\u00a0<\/p>\n<ul>\n<li>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 \u043f\u0435\u0440\u0435\u0434\u0430\u0451\u0442\u0441\u044f \u043d\u0435 hql \u0437\u0430\u043f\u0440\u043e\u0441, \u0430 \u043b\u044f\u043c\u0431\u0434\u0430-\u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435, \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u044e\u0449\u0435\u0435 \u043a\u0443\u0440\u0441\u043e\u0440\u00a0<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u0435 \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0434\u043e\u043b\u0433\u043e\u0438\u0433\u0440\u0430\u044e\u0449\u0438\u0435 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u0438, \u0447\u0442\u043e \u0434\u0430\u0451\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u043e\u0435 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u043e \u043f\u0435\u0440\u0435\u0434 hibernate. \u041f\u043e \u043a\u0440\u0430\u0439\u043d\u0435\u0439 \u043c\u0435\u0440\u0435 DBA \u0431\u0443\u0434\u0443\u0442 \u0441\u043f\u043e\u043a\u043e\u0439\u043d\u0435\u0435).<\/p>\n<\/li>\n<\/ul>\n<p><u>\u041a\u043b\u0430\u0441\u0441 com.magnit.flux.mybatis.dao.MyBatisFluxResultProducer<\/u><\/p>\n<pre><code class=\"java\">public class MyBatisFluxResultProducer&lt;T> {           private final SqlSessionFactory sqlSessionFactory;        private Cursor&lt;T> cursor;        private SqlSession sqlSession;        \/**       * @param cursorFunction \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043f\u0440\u043e\u0434\u044e\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u0443\u0440\u0441\u043e\u0440\u0430       * @return Flux \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0443\u044e\u0449\u0435\u0433\u043e \u0442\u0438\u043f\u0430       *\/      public Flux&lt;T> execute(Function&lt;SqlSession, Cursor&lt;T>> cursorFunction) {          Optional.ofNullable(sqlSession).ifPresent(e -> {              throw new RuntimeException(\"Cursor already open\");          });            sqlSession = sqlSessionFactory.openSession();          cursor = cursorFunction.apply(sqlSession);          return Flux.fromStream(StreamSupport.stream(cursor.spliterator(), false));      }        @SneakyThrows      public Mono&lt;Void> close() {          if (cursor.isOpen()) {              cursor.close();            }          sqlSession.close();          return Mono.empty();      }    } <\/code><\/pre>\n<h4>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u0441 MyBatis\u00a0<\/h4>\n<p>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u0443, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0435\u043c\u0443 \u0441 hibrernate.<\/p>\n<p><u>\u041a\u043b\u0430\u0441\u0441 com.magnit.flux.mybatis.controller.MyBatisOperationController<\/u><\/p>\n<pre><code class=\"java\">public class MyBatisOperationController {           private final SqlSessionFactory sqlSessionFactory;        private final ObjectFactory&lt;MyBatisFluxResultProducer&lt;Operation>> streamResultProducerObjectFactory;        @GetMapping(path = \"\/operations-stream\", produces = \"application\/stream+json\")      public Flux&lt;Operation> getOperationsStream() {          return getOperationFlux();      }        private Flux&lt;Operation> getOperationFlux() {          Function&lt;SqlSession, Cursor&lt;Operation>> cursorFunction = sqlSession -> sqlSession              .getMapper(OperationMapper.class).getAllOperations();            Mono&lt;MyBatisFluxResultProducer&lt;Operation>> streamResultExecutorMono = Mono              .just(streamResultProducerObjectFactory.getObject());          return Flux.usingWhen(streamResultExecutorMono,              se -> se.execute(cursorFunction),              MyBatisFluxResultProducer::close);      }    } <\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0442\u0430\u043a\u0436\u0435 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/298\/573\/afc\/298573afc4de54d112a28de1e0002987.png\" width=\"700\" height=\"100\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/298\/573\/afc\/298573afc4de54d112a28de1e0002987.png\"\/><\/figure>\n<h2>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043f\u0440\u0438\u0451\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0411\u0414 \u0421\u041c<\/h2>\n<p>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u0441 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0435\u0439 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043e\u0431\u044a\u0451\u043c\u043e\u0432 \u0434\u0430\u043d\u043d\u044b\u0445 \u0431\u044b\u043b\u0430 \u0440\u0435\u0448\u0435\u043d\u0430, \u043d\u043e \u0432\u043e\u0437\u043d\u0438\u043a\u043b\u0430 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0437\u043a\u0438 \u0411\u0414 \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438. \u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0431\u044b\u043b\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u043d\u0430 \u0437\u0430\u043f\u0438\u0441\u044c \u0432 \u0411\u0414. \u041d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 backpressure (\u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u0434\u0430\u0432\u043b\u0435\u043d\u0438\u0435).\u00a0\u00a0<\/p>\n<h4>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 backet4j \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 backpressure\u00a0<\/h4>\n<ul>\n<li>\n<p>Bucket4j \u2014 \u044d\u0442\u043e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u044f \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u0430\u044f \u043d\u0430 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c\u0435 token-bucket\u00a0<\/p>\n<\/li>\n<li>\n<p>Bucket4j \u2014 \u044d\u0442\u043e \u043f\u043e\u0442\u043e\u043a\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u043a\u0430\u043a \u0432 \u0430\u0432\u0442\u043e\u043d\u043e\u043c\u043d\u043e\u043c \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 JVM, \u0442\u0430\u043a \u0438 \u0432 \u043a\u043b\u0430\u0441\u0442\u0435\u0440\u043d\u043e\u0439 \u0441\u0440\u0435\u0434\u0435\u00a0<\/p>\n<\/li>\n<li>\n<p>Bucket4j \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0432 \u043f\u0430\u043c\u044f\u0442\u0438 \u0438\u043b\u0438 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u043e\u0435 \u043a\u044d\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 JCache (JSR107)\u00a0<\/p>\n<\/li>\n<\/ul>\n<h4>\u0410\u043b\u0433\u043e\u0440\u0438\u0442\u043c Token Bucket<\/h4>\n<ul>\n<li>\n<p>\u0421\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043a\u043e\u0440\u0437\u0438\u043d\u0430, \u0432\u043c\u0435\u0441\u0442\u0438\u043c\u043e\u0441\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e\u043c \u0442\u043e\u043a\u0435\u043d\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u0432\u043c\u0435\u0441\u0442\u0438\u0442\u044c\u00a0<\/p>\n<\/li>\n<li>\n<p>\u0412\u0441\u044f\u043a\u0438\u0439 \u0440\u0430\u0437, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044c \u0445\u043e\u0447\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043a\u043e\u043d\u0435\u0447\u043d\u043e\u0439 \u0442\u043e\u0447\u043a\u0435 API, \u043e\u043d \u0434\u043e\u043b\u0436\u0435\u043d \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0442\u043e\u043a\u0435\u043d \u0438\u0437 \u043a\u043e\u0440\u0437\u0438\u043d\u044b\u00a0<\/p>\n<\/li>\n<li>\n<p>\u0422\u043e\u043a\u0435\u043d \u0438\u0437 \u043a\u043e\u0440\u0437\u0438\u043d\u044b \u0443\u0434\u0430\u043b\u044f\u0435\u0442\u0441\u044f, \u0435\u0441\u043b\u0438 \u043e\u043d \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d, \u0438 \u0437\u0430\u043f\u0440\u043e\u0441 \u043f\u0440\u0438\u043d\u0438\u043c\u0430\u0435\u0442\u0441\u044f\u00a0<\/p>\n<\/li>\n<li>\n<p>\u0415\u0441\u043b\u0438 \u0432 \u043a\u043e\u0440\u0437\u0438\u043d\u0435 \u043d\u0435\u0442 \u0442\u043e\u043a\u0435\u043d\u043e\u0432, \u0442\u043e \u0437\u0430\u043f\u0440\u043e\u0441 \u043e\u0442\u043a\u043b\u043e\u043d\u044f\u0435\u0442\u0441\u044f\u00a0<\/p>\n<\/li>\n<li>\n<p>\u0422\u043e\u043a\u0435\u043d\u044b \u043f\u043e\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0441 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c\u044e, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438 \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u043c\u00a0<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e bucket4j <a href=\"https:\/\/bucket4j.com\/8.1.1\/toc.html\"><u>\u0437\u0434\u0435\u0441\u044c<\/u><\/a>.<\/p>\n<h4>Bucket4j \u0438 Flux\u00a0<\/h4>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u044b \u0434\u0432\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0441\u0432\u044f\u0437\u043a\u0438 Bucket4j \u0438 Flux\u00a0<\/p>\n<ul>\n<li>\n<p>\u0411\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0430\u044f \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u0435\u0442\u043e\u0434\u043e\u0432 Flux.delayUntil \u0438 Bucket.asBlocking\u00a0<\/p>\n<\/li>\n<li>\n<p>\u0410\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u0430\u044f, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0430\u044f \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a\u043e\u043c (Subscription) \u0438 Bucket.asScheduler\u00a0<\/p>\n<\/li>\n<\/ul>\n<h4>\u0420\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043b\u0438\u0435\u043d\u0442\u0430 \u043d\u0430 java \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Bucket4j\u00a0<\/h4>\n<p>\u0412 \u043a\u043b\u0430\u0441\u0441\u0435 RateLimitService \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u044b \u0434\u0432\u0430 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0445 \u043c\u0435\u0442\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441 \u0437\u0430\u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u044c\u044e \u0444\u0435\u0442\u0447\u0430\u0442 \u0437\u0430\u043f\u0438\u0441\u0438 \u0438\u0437 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e http-\u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043e\u043f\u0438\u0441\u0430\u043d \u0432\u044b\u0448\u0435.\u00a0<\/p>\n<h4>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0435\u0433\u043e API bucket4j \u0434\u043b\u044f backpressure\u00a0<\/h4>\n<p><u>\u041a\u043b\u0430\u0441\u0441 com.magnit.fluex.client.service.RateLimitService.executeBlocking<\/u><\/p>\n<pre><code class=\"java\">public void executeBlocking(long rate) {      AtomicLong counter = new AtomicLong(0);      val limit = Bandwidth.simple(rate, Duration.ofMinutes(1));      val bucket = Bucket.builder().addLimit(limit).build();      val flux = client.get().retrieve().bodyToFlux(Operation.class);      flux.delayUntil(operation -> {          try {              bucket.asBlocking().consume(1);          } catch (InterruptedException e) {              e.printStackTrace();          }          return Mono.just(\"two\");      }).subscribe(value ->  System.out.println(counter.incrementAndGet() + \" \" + value));  } <\/code><\/pre>\n<p>\u041e\u0441\u043d\u043e\u0432\u0443 \u043b\u043e\u0433\u0438\u043a\u0438 \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043c\u0435\u0442\u043e\u0434 Flux.delayUntil \u0432 \u0441\u0432\u044f\u0437\u043a\u0435 bucket.asBlocking.\u00a0\u00a0<\/p>\n<p>\u041f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 bucket.asBlocking \u0442\u043e\u043a\u0435\u043d \u043b\u0438\u0431\u043e \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f, \u043b\u0438\u0431\u043e \u043f\u043e\u0442\u043e\u043a \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u0434\u043e \u043f\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u0440\u0437\u0438\u043d\u044b.\u00a0<\/p>\n<h4>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0448\u0435\u0434\u0443\u043b\u0438\u043d\u0433\u0430 bucket4j \u0434\u043b\u044f backpressure\u00a0<\/h4>\n<p><u>\u041a\u043b\u0430\u0441\u0441 com.magnit.flux.client.service.RateLimitService.executeScheduling<\/u><\/p>\n<pre><code class=\"java\">public void executeScheduling(long rate) {      AtomicLong counter = new AtomicLong(0);      val service = Executors.newSingleThreadScheduledExecutor();      val limit = Bandwidth.simple(rate, Duration.ofMinutes(1));      val bucket = Bucket.builder().addLimit(limit).build();      final long watTime = 50;      BaseSubscriber&lt;Operation> subscriber = new BaseSubscriber&lt;Operation>() {          private void handleFutureResult(Boolean result) {              if (result) {                  this.request(1);              } else {                  service.schedule(() -> asyncRequest(), watTime, TimeUnit.NANOSECONDS);              }          }            @SneakyThrows          private void asyncRequest() {              val future = bucket.asScheduler().tryConsume(50, watTime, service);              if (future.isDone()) {                  handleFutureResult(future.get());              } else {                  future.thenAcceptAsync(value -> {                      handleFutureResult(value);                  });              }          }            @Override          protected void hookOnSubscribe(Subscription subscription) {              asyncRequest();          }            @Override          protected void hookOnNext(Operation value) {              System.out.println(counter.incrementAndGet() + \" \" + value);              asyncRequest();          }      };      val flux = client.get().retrieve().bodyToFlux(Operation.class);      flux.subscribe(subscriber);  } <\/code><\/pre>\n<p>\u0412 \u0434\u0430\u043d\u043d\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u043f\u043e\u0442\u043e\u043a \u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442\u0441\u044f. \u0421\u043e\u0437\u0434\u0430\u0451\u0442\u0441\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u0447\u0438\u043a, \u043d\u0430\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043e\u0442 \u043a\u043b\u0430\u0441\u0441\u0430 \u0438\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 reactor \u2014 BaseSubscriber. \u0422\u043e\u043a\u0435\u043d \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c bucket.asScheduler, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0431\u044a\u0435\u043a\u0442 CompletableFuture. \u0415\u0441\u043b\u0438 \u0442\u043e\u043a\u0435\u043d \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c (CompletableFuture .isDone() == true), \u0442\u043e\u0433\u0434\u0430 \u0444\u0435\u0442\u0447\u0438\u0442\u0441\u044f \u043e\u0447\u0435\u0440\u0435\u0434\u043d\u0430\u044f \u0437\u0430\u043f\u0438\u0441\u044c, \u0438\u043d\u0430\u0447\u0435 \u0444\u0435\u0442\u0447 \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0441\u043b\u0435 \u043f\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043a\u043e\u0440\u0437\u0438\u043d\u044b. \u041e\u0436\u0438\u0434\u0430\u043d\u0438\u0435 \u043f\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e \u2014 \u043c\u0435\u0442\u043e\u0434 CompletableFuture.thenAcceptAsync.\u00a0<\/p>\n<h2>\u0412\u044b\u0432\u043e\u0434\u044b<\/h2>\n<ul>\n<li>\n<p>\u0412 \u0441\u0435\u0440\u0432\u0438\u0441\u0435 \u043d\u0430\u043c \u0443\u0434\u0430\u043b\u043e\u0441\u044c \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u0438\u0442\u044c \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0443\u044e \u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u0443\u044e \u0430\u0440\u0445\u0438\u0442\u0435\u043a\u0442\u0443\u0440\u044b\u00a0<\/p>\n<\/li>\n<li>\n<p>\u0412 \u0432\u044b\u0431\u043e\u0440\u0435 \u043c\u0435\u0436\u0434\u0443 hibernate \u0438 mybatis \u043c\u044b \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u0438\u043b\u0438\u0441\u044c \u043d\u0430 hibernate, \u0442\u0430\u043a \u043a\u0430\u043a, \u0432\u043e-\u043f\u0435\u0440\u0432\u044b\u0445, \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0431\u044b\u043b\u043e \u0443\u0436\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043e \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c hibernate, \u0430 \u0432\u043e-\u0432\u0442\u043e\u0440\u044b\u0445, \u043d\u0430\u043c \u0432\u0430\u0436\u043d\u043e \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u0434\u0430\u043d\u043d\u044b\u0445.\u00a0<\/p>\n<\/li>\n<li>\n<p>\u041f\u043e\u043c\u0438\u043c\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u0438, \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0438 \u0432\u0435\u0441\u044c \u0431\u043e\u0433\u0430\u0442\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b flux.\u00a0<\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/726090\/\"> https:\/\/habr.com\/ru\/articles\/726090\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><\/figure>\n<p>\u041f\u0440\u0438\u0432\u0435\u0442, \u0425\u0430\u0431\u0440! \u041d\u0430\u00a0\u0441\u0432\u044f\u0437\u0438 \u0410\u043d\u0434\u0440\u0435\u0439 \u0417\u044f\u0431\u043b\u0438\u043d, Java \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u00ab\u041c\u0430\u0433\u043d\u0438\u0442\u00bb. \u041d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043b\u0435\u0442 \u043d\u0430\u0437\u0430\u0434, \u043f\u0440\u043e\u0434\u043b\u044f\u044f \u0434\u043e\u0447\u0435\u0440\u0438 \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0443 \u043d\u0430\u00a0Netflix, \u044f \u0437\u0430\u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043e\u0432\u0430\u043b\u0441\u044f, \u043a\u0430\u043a\u00a0\u043e\u043d\u0438 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0442 \u043e\u0431\u0441\u043b\u0443\u0436\u0438\u0432\u0430\u043d\u0438\u0435 \u0441\u043e\u0442\u0435\u043d \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u043e\u0432 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432. \u0418\u0437\u0443\u0447\u0438\u0432 \u0432\u043e\u043f\u0440\u043e\u0441, \u044f \u0443\u0432\u043b\u0451\u043a\u0441\u044f \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u043c \u043f\u043e\u0434\u0445\u043e\u0434\u043e\u043c \u0432\u00a0\u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438. \u0427\u0435\u0440\u0435\u0437 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u044d\u0442\u043e \u0443\u0432\u043b\u0435\u0447\u0435\u043d\u0438\u0435 \u043f\u0440\u0438\u043d\u0435\u0441\u043b\u043e \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u043f\u043e\u043b\u044c\u0437\u0443 \u043f\u0440\u0438\u00a0\u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0432 \u00ab\u041c\u0430\u0433\u043d\u0438\u0442\u0435\u00bb. \u0412\u00a0\u0441\u0442\u0430\u0442\u044c\u0435 \u044f \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0443 \u043f\u0440\u043e\u00a0\u0442\u0440\u0438 \u0440\u0435\u0448\u0435\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u044b\u0439 \u043e\u0431\u043c\u0435\u043d \u0434\u0430\u043d\u043d\u044b\u043c\u0438 \u0438\u0437\u00a0\u0411\u0414 \u043c\u0435\u0436\u0434\u0443 \u0440\u0430\u0441\u043f\u0440\u0435\u0434\u0435\u043b\u0451\u043d\u043d\u044b\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u043c\u0438: <\/p>\n<ol>\n<li>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c hibernate <\/p>\n<\/li>\n<li>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0441\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c mybatis <\/p>\n<\/li>\n<li>\n<p>\u041e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438 \u043e\u0431\u043c\u0435\u043d\u0430 \u0441\u00a0\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0433\u043e \u0434\u0430\u0432\u043b\u0435\u043d\u0438\u044f (\u00abbackpressure\u00bb) \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 Bucket4j <\/p>\n<\/li>\n<\/ol>\n<h2>\u041f\u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0430 \u0437\u0430\u0434\u0430\u0447\u0438<\/h2>\n<p>\u041d\u0430\u0448\u0430 \u043a\u043e\u043c\u0430\u043d\u0434\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u043b\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f\u00a0\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u0432 \u0441\u0435\u0442\u0438, \u0430\u00a0\u0442\u0430\u043a\u0436\u0435 \u0434\u043b\u044f\u00a0\u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441\u00a0\u0433\u043e\u0441\u0443\u0434\u0430\u0440\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u043c\u0438 \u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438 \u0432\u00a0\u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u0432\u0435\u0442\u0435\u0440\u0438\u043d\u0430\u0440\u0438\u0438 \u00ab\u0412\u0435\u0442\u0418\u0421\u00bb. <\/p>\n<p>\u0423\u043f\u0440\u043e\u0449\u0435\u043d\u043d\u043e \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0430 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a: <\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u0411\u0438\u0437\u043d\u0435\u0441\u2011\u0437\u0430\u043f\u0440\u043e\u0441\u044b\u00a0\u2014 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432\u00a0\u0444\u043e\u0440\u043c\u0430\u0442\u0435 json, \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043d\u044b\u0435 \u0434\u043b\u044f\u00a0\u043e\u0431\u043c\u0435\u043d\u0430 \u043d\u0430\u00a0\u0443\u0440\u043e\u0432\u043d\u0435 \u0431\u0438\u0437\u043d\u0435\u0441\u2011\u0434\u0430\u043d\u043d\u044b\u0445 (\u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438, \u043f\u043e\u0437\u0438\u0446\u0438\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439, \u043f\u0440.) \u0438 \u0440\u0430\u0441\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u044e\u0449\u0438\u0435\u0441\u044f \u0432\u00a0\u0431\u043e\u043b\u0435\u0435 \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u044b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u0432\u00a0\u0444\u043e\u0440\u043c\u0430\u0442\u0430\u0445, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0449\u0438\u0445\u0441\u044f \u0433\u043e\u0441\u0441\u0435\u0440\u0432\u0438\u0441\u0430\u043c\u0438. <\/p>\n<p>\u0426\u0421\u041c (\u0426\u0435\u043d\u0442\u0440\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441 \u0441\u0435\u0442\u0438 \u00ab\u041c\u0435\u0440\u043a\u0443\u0440\u0438\u0439\u00bb)\u00a0\u2014 \u0440\u0430\u0437\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u043c\u043e\u0435 \u043d\u0430\u043c\u0438 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438.<\/p>\n<p>BDSM\u2011CLIENT\u00a0\u2014 \u0440\u0430\u0431\u043e\u0442\u0430 \u0441\u00a0\u0431\u0438\u0437\u043d\u0435\u0441\u2011\u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c\u0438 \u0411\u0414 \u0421\u041c (\u0431\u0430\u0437\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0441\u0435\u0442\u0438 \u043c\u0430\u0433\u0430\u0437\u0438\u043d\u043e\u0432). <\/p>\n<p>MERCURY\u00a0\u2014 \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u0435\u0442 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0441\u043e \u0448\u043b\u044e\u0437\u043e\u043c \u043a \u00ab\u0412\u0435\u0442\u0418\u0421\u00bb. <\/p>\n<p>PROCESSING\u00a0\u2014 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0443 \u0431\u0438\u0437\u043d\u0435\u0441\u2011\u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0434\u043e\u00a0\u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0432\u00a0\u0448\u043b\u044e\u0437. <\/p>\n<p>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u043d\u044b\u043c \u043c\u0435\u0441\u0442\u043e\u043c \u043e\u043a\u0430\u0437\u0430\u043b\u0430\u0441\u044c \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0438\u0437\u00a0\u0426\u0421\u041c \u0432\u00a0\u0411\u0414 \u0421\u041c: \u043e\u0431\u044a\u0451\u043c\u044b \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0433\u0440\u043e\u043c\u043d\u044b, \u0430\u00a0\u043d\u0430\u00a0\u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0411\u0414 \u0421\u041c \u043d\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u043b\u0441\u044f \u0442\u043e\u043d\u043a\u0438\u0439 \u043a\u043b\u0438\u0435\u043d\u0442, \u043f\u0438\u0448\u0443\u0449\u0438\u0439 \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432\u00a0\u0431\u0430\u0437\u0443. <\/p>\n<p><strong>\u0422\u0440\u0435\u0431\u043e\u0432\u0430\u043d\u0438\u044f \u043a \u043e\u0431\u043c\u0435\u043d\u0443:<\/strong><\/p>\n<ul>\n<li>\n<p>\u0414\u0430\u043d\u043d\u044b\u0435 \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u044e\u0442\u0441\u044f \u0438\u0437\u00a0\u0411\u0414<\/p>\n<\/li>\n<li>\n<p>\u041e\u0431\u044a\u0451\u043c \u0434\u0430\u043d\u043d\u044b\u0445\u00a0\u2014 \u043c\u0438\u043b\u043b\u0438\u043e\u043d\u044b \u0437\u0430\u043f\u0438\u0441\u0435\u0439 \u0437\u0430\u00a0\u0441\u0435\u0430\u043d\u0441 <\/p>\n<\/li>\n<li>\n<p>\u041f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u0432\u0435\u0434\u0451\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u0438\u043d\u0442\u0435\u0440\u043d\u0435\u0442 \u043f\u043e\u00a0http <\/p>\n<\/li>\n<li>\n<p>\u041d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c ORM <\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0437\u0443\u0447\u0438\u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438, \u043c\u044b \u043f\u0440\u0438\u0448\u043b\u0438 \u043a\u00a0\u043c\u043d\u0435\u043d\u0438\u044e, \u0447\u0442\u043e\u00a0\u0432\u00a0\u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0441\u0442\u044c. <\/p>\n<p><strong>\u0414\u043e\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0426\u0421\u041c \u0438 \u0411\u0414 \u0421\u041c<\/strong>:<\/p>\n<ul>\n<li>\n<p>\u0412\u00a0\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0439 \u043a\u043e\u0434 \u0426\u0421\u041c \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u0434 \u043e\u0431\u043c\u0435\u043d\u0430<\/p>\n<\/li>\n<li>\n<p>\u0414\u043b\u044f\u00a0\u043f\u0440\u0438\u0451\u043c\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u043d\u0430\u00a0\u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0411\u0414 \u0421\u041c \u043f\u0438\u0448\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0435 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c\u044b\u0435 \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0438<\/strong>:<\/p>\n<ul>\n<li>\n<p>Java streams\u00a0<\/p>\n<\/li>\n<li>\n<p>Hibernate streamResult\u00a0<\/p>\n<\/li>\n<li>\n<p>Reactive streams\u00a0<\/p>\n<\/li>\n<li>\n<p>Spring webflux(reactor)\u00a0<\/p>\n<\/li>\n<li>\n<p>Spring webclient\u00a0<\/p>\n<\/li>\n<li>\n<p>Rsocket (\u0434\u043b\u044f \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0430\u0446\u0438\u0438)\u00a0<\/p>\n<\/li>\n<\/ul>\n<p><strong>\u0413\u0440\u0430\u043d\u0438\u0447\u043d\u044b\u0435 \u0443\u0441\u043b\u043e\u0432\u0438\u044f:<\/strong><\/p>\n<ul>\n<li>\n<p>\u041d\u0435\u00a0\u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c R2DBC. \u041d\u0430\u00a0\u043c\u043e\u043c\u0435\u043d\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0434\u043b\u044f\u00a0Oracle \u043d\u0435\u00a0\u0431\u044b\u043b\u043e \u0441\u0442\u0430\u0431\u0438\u043b\u044c\u043d\u043e\u0433\u043e \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u0433\u043e \u0434\u0440\u0430\u0439\u0432\u0435\u0440\u0430. <\/p>\n<\/li>\n<li>\n<p>Hibernate streamResult \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0430\u043a\u0442\u0438\u0432\u043d\u0443\u044e \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044e \u043d\u0430\u00a0\u0432\u0441\u0451 \u0432\u0440\u0435\u043c\u044f \u0444\u0435\u0442\u0447\u0430. \u041d\u0443\u0436\u043d\u043e \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0437\u0430\u0432\u0435\u0440\u0448\u0435\u043d\u0438\u0435 \u0444\u0435\u0442\u0447\u0430, \u043e\u0448\u0438\u0431\u043a\u0438, \u0437\u0430\u043a\u0440\u044b\u0442\u0438\u0435 \u0441\u043e\u0435\u0434\u0438\u043d\u0435\u043d\u0438\u044f, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u0432\u0435\u0440\u0448\u0438\u0442\u044c \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044e. \u0421\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u0435 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0432\u00a0\u0432\u0438\u0434\u0435 try\u2011catch \u043d\u0435\u00a0\u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0442 \u0432\u00a0\u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u0438.<\/p>\n<\/li>\n<\/ul>\n<h2>\u0420\u0435\u0448\u0435\u043d\u0438\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c hibernate<\/h2>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u0430\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u043b\u0430\u0441\u044c \u0432\u00a0\u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e\u0439 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441\u00a0\u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f\u043c\u0438 \u0432\u00a0\u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435. \u0414\u043b\u044f\u00a0\u044d\u0442\u043e\u0433\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c, \u0431\u043b\u0430\u0433\u043e Reactor \u044d\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442. \u041e\u0441\u043d\u043e\u0432\u0443 \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442: <\/p>\n<ul>\n<li>\n<p>Stateless session\u00a0<\/p>\n<\/li>\n<li>\n<p>StreamResult\u00a0<\/p>\n<\/li>\n<li>\n<p>\u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f Flux \u0438\u0437 Stream\u00a0<\/p>\n<\/li>\n<\/ul>\n<p>\u0414\u0430\u043b\u0435\u0435 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043a\u043e\u0434.\u00a0<\/p>\n<h4>\u0421\u0443\u0449\u043d\u043e\u0441\u0442\u0438<\/h4>\n<ul>\n<li>\n<p>Customer \u2014 \u0441\u043f\u0440\u0430\u0432\u043e\u0447\u043d\u0438\u043a \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a\u043e\u0432.\u00a0<\/p>\n<\/li>\n<li>\n<p>Operation \u2014 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 \u0437\u0430\u043a\u0430\u0437\u0447\u0438\u043a\u0430\u043c\u0438, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u043f\u0440\u043e\u0434\u0430\u0436\u0438.\u00a0<\/p>\n<\/li>\n<\/ul>\n<pre><code class=\"java\">public class Customer {        @Id      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = \"sequence\")      @SequenceGenerator(name = \"sequence\", sequenceName = \"SQ_CUSTOMER\", allocationSize = 1)      private Long id;        @Column(name = \"NAME\")      private String name;    }  public class Operation {        @Id      @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = \"sequence\")      @SequenceGenerator(name = \"sequence\", sequenceName = \"SQ_OPERATION\", allocationSize = 1)      private Long id;        @Column(name = \"TOTAL_SUM\")      private Long totalSum;        @ManyToOne      @JoinColumn(name = \"customer_id\")      private Customer customer;        @ManyToMany      @JoinTable(          name = \"operation_detail\",          joinColumns = @JoinColumn(name = \"operation_id\"),          inverseJoinColumns = @JoinColumn(name = \"product_id\"))      private List&lt;Product> products;    }   <\/code><\/pre>\n<h4>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445\u00a0<\/h4>\n<p>\u0417\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u0430 \u0438 \u043d\u0435\u00a0\u0441\u043e\u0432\u0441\u0435\u043c \u0438\u043c\u0435\u0435\u0442 \u043e\u0442\u043d\u043e\u0448\u0435\u043d\u0438\u0435 \u043a\u00a0\u0442\u0435\u043c\u0435 \u0441\u0442\u0430\u0442\u044c\u0438, \u0437\u0434\u0435\u0441\u044c \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043c\u043e\u0449\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f. \u041d\u0430\u00a0\u0434\u0430\u043d\u043d\u043e\u043c \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043d\u043e, \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u0430 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 reactor \u0438 \u043a\u0430\u043a\u00a0\u043e\u043d\u0430 \u043c\u043e\u0436\u0435\u0442 \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442\u044c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0443.<\/p>\n<p><u>\u041a\u043b\u0430\u0441\u0441 com.magnit.flux.common.service.InitDataService<\/u><\/p>\n<pre><code class=\"java\">private void fillCustomer() {      Flux.range(0, CUSTOMER_RECORD_LIMIT)          .map(i -> Customer.builder().name(\"Customer \" + i).build())          .subscribe(customerRepository::save);  }    private void fillProduct() {      Flux.range(0, PRODUCT_RECORD_LIMIT)          .map(i -> Product.builder().name(\"Product \" + i).build())          .subscribe(productRepository::save);  }    private void fillOperation() {      Supplier&lt;List&lt;Product>> productSupplier = () -> new Random().ints(5, 1, 8)          .boxed().distinct()          .map(productId -> Product.builder().id((long) productId).build())          .collect(Collectors.toList());      List&lt;Customer> customers = (List&lt;Customer>) customerRepository.findAll();      Flux.range(0, OPERATION_RECORD_LIMIT)          .map(i -> Operation.builder()              .totalSum((long) random.nextInt(100))              .customer(customers.get(random.nextInt(customers.size() - 1)))              .products(productSupplier.get())              .build())          .buffer(1000)          .subscribe(operationRepository::saveAll);  } <\/code><\/pre>\n<h4>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 hibernate \u0434\u043b\u044f \u0441\u0442\u0440\u0438\u043c\u0438\u043d\u0433\u0430\u00a0<\/h4>\n<p>\u041a\u043b\u0430\u0441\u0441 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u043e\u0441\u043d\u043e\u0432\u043d\u0443\u044e \u0440\u0430\u0431\u043e\u0442\u0443 \u043f\u043e\u00a0\u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044e \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044f\u043c\u0438 \u0432\u00a0\u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u043e\u043c \u0440\u0435\u0436\u0438\u043c\u0435. \u042d\u0442\u043e \u0447\u0442\u043e\u2011\u0442\u043e \u0432\u0440\u043e\u0434\u0435 AutoCloseable \u0432\u00a0\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f\u0445. <\/p>\n<p><u>\u041a\u043b\u0430\u0441\u0441 com.magnit.flux.hibernate.dao.HibernateFluxResultProducer<\/u><\/p>\n<pre><code class=\"java\">@RequiredArgsConstructor  public class HibernateFluxResultProducer&lt;T> {           private final EntityManagerFactory entityManagerFactory;        private StatelessSession statelessSession;        \/**       * \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 hql \u0437\u0430\u043f\u0440\u043e\u0441 \u0438 \u0441\u043e\u0437\u0434\u0430\u0451\u0442 Flux \u0438\u0437 Result Stream       *\/      public Flux&lt;T> execute(String qlString, Class&lt;T> resultClass) {          Optional.ofNullable(statelessSession).ifPresent(e -> {              throw new RuntimeException(\"Cursor already open\");          });          val sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);          \/\/\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 Stateless Session \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0443\u0441\u043a\u043e\u0440\u0438\u0442\u044c \u0447\u0442\u0435\u043d\u0438\u0435 \u0437\u0430 \u0441\u0447\u0451\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f detached \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432          statelessSession = sessionFactory.openStatelessSession();          statelessSession.getTransaction().begin();          val query = statelessSession.createQuery(qlString, resultClass);          \/\/\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c hibernate \u0434\u043b\u044f \u043f\u043e\u0442\u043e\u043a\u043e\u0432\u043e\u0433\u043e \u0447\u0442\u0435\u043d\u0438\u044f \u0438\u0437 \u0411\u0414 - getResultStream          return Flux.fromStream(query.getResultStream());      }        public Mono&lt;Void> commit() {          return close(true);      }        public Mono&lt;Void> rollback() {          return close(false);      }        public Mono&lt;Void> close(boolean commitTran) {          if (statelessSession.getTransaction().isActive()) {              if (commitTran) {                  statelessSession.getTransaction().commit();              } else {                  statelessSession.getTransaction().rollback();              }            }          statelessSession.close();          return Mono.empty();      }      } <\/code><\/pre>\n<p>\u0414\u0430\u043d\u043d\u044b\u0439 \u043a\u043b\u0430\u0441\u0441 \u0441\u0442\u0430\u0440\u0442\u0443\u0435\u0442 \u0442\u0440\u0430\u043d\u0437\u0430\u043a\u0446\u0438\u044e \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 hql \u0437\u0430\u043f\u0440\u043e\u0441. \u0422\u0430\u043a\u0436\u0435 \u043e\u043d \u0438\u043c\u0435\u0435\u0442 \u043c\u0435\u0442\u043e\u0434\u044b commit \u0438 rollback. <\/p>\n<h4>\u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0439 \u0441 hibernate\u00a0<\/h4>\n<p>\u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0440\u0430\u0431\u043e\u0442\u044b \u0441\u00a0\u043f\u043e\u0442\u043e\u043a\u0430\u043c\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u0432\u00a0\u043f\u0440\u0438\u0432\u0430\u0442\u043d\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0435 getOperationFlux. \u0413\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u044f \u043f\u043e\u0442\u043e\u043a\u0430 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432\u044b\u0437\u043e\u0432\u043e\u043c \u043c\u0435\u0442\u043e\u0434\u0430 Flux.usingWhen, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u0430\u0441\u0438\u043d\u0445\u0440\u043e\u043d\u043d\u044b\u043c AutoCloseable. \u041a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0434\u0432\u0430 \u044d\u043d\u0434\u043f\u043e\u0438\u043d\u0442\u0430: <\/p>\n<ul>\n<li>\n<p>getOperationsStream \u2014 json \u0441\u0442\u0440\u0438\u043c\u0438\u043d\u0433\u00a0<\/p>\n<\/li>\n<li>\n<p>getOperationsWs \u2014 \u0432\u0435\u0431-\u0441\u043e\u043a\u0435\u0442\u00a0<\/p>\n<\/li>\n<\/ul>\n<p><u>\u041a\u043b\u0430\u0441\u0441 com.magnit.flux.hibernate.controller.HibernateOperationController<\/u><\/p>\n<pre><code class=\"java\">public class HibernateOperationController {        private final ObjectFactory&lt;HibernateFluxResultProducer&lt;Operation>> streamResultProducerObjectFactory;        @GetMapping(path = \"\/operations-stream\", produces = \"application\/stream+json\")      public Flux&lt;Operation> getOperationsStream() {          return getOperationFlux();      }        @MessageMapping(\"operations\")      public Flux&lt;Operation> getOperationsWs() {          return getOperationFlux();      }        private Flux&lt;Operation> getOperationFlux() {          Mono&lt;HibernateFluxResultProducer&lt;Operation>> streamResultExecutorMono = Mono              .just(streamResultProducerObjectFactory.getObject());          return Flux.usingWhen(streamResultExecutorMono,              se -> se.execute(\"select o from Operation o JOIN FETCH o.customer c\", Operation.class),              HibernateFluxResultProducer::commit);      }    } <\/code><\/pre>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0440\u0430\u0431\u043e\u0442\u044b \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043c\u0435\u0442\u043e\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432\u00a0\u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435: <\/p>\n<figure class=\"full-width\"><\/figure>\n<p>\u041c\u043e\u0436\u043d\u043e \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u0438\u0442\u044c \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0438 \u0438\u043b\u0438\u00a0\u0434\u0430\u0436\u0435 \u0437\u0430\u043a\u0440\u044b\u0442\u044c \u0431\u0440\u0430\u0443\u0437\u0435\u0440. \u041c\u043e\u0436\u043d\u043e \u0443\u0431\u0435\u0434\u0438\u0442\u044c\u0441\u044f, \u0447\u0442\u043e\u00a0\u043c\u0435\u0442\u043e\u0434 close \u0432\u0441\u0435\u0433\u0434\u0430 \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f. <\/p>\n<figure class=\"\"><\/figure>\n<p>\u0412\u0442\u043e\u0440\u043e\u0439 \u043c\u0435\u0442\u043e\u0434\u00a0\u2014 \u0431\u043e\u043b\u0435\u0435 \u0438\u043d\u0442\u0435\u0440\u0441\u043d\u044b\u0439. \u041d\u0430\u00a0\u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u0435 \u043c\u043e\u0436\u043d\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u043c\u0435\u043d \u043f\u043e\u00a0\u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b\u0443 Rsocket. \u0414\u043b\u044f\u00a0\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f Rsocket \u043a\u043b\u0438\u0435\u043d\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d \u043d\u0430\u00a0javascript. \u0422\u0430\u043a\u0436\u0435 \u0434\u0430\u043d\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440 \u0434\u0435\u043c\u043e\u043d\u0441\u0442\u0440\u0438\u0440\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u0430 backpressure (\u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u0434\u0430\u0432\u043b\u0435\u043d\u0438\u0435). <\/p>\n<p><u>statis\/index.js<\/u><\/p>\n<pre><code class=\"java\">client.connect().subscribe({      onError: error => console.error(error),      onSubscribe: cancel => {      },      onComplete: socket => {          socket.requestStream({              data: null,              metadata: String.fromCharCode(\"operations\".length) + \"operations\"          })          .subscribe({              onComplete: () => console.log(\"requestStream done\"),              onError: error => {                  console.log(\"got error with requestStream\");                  console.error(error);              },              onNext: value => {                  document.getElementById(                      \"operation\").innerText = \"Operation ID: \"                      + value.data.id + \". Customer: \" + value.data.customer.name;                  \/\/\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0431\u0440\u0430\u0442\u043d\u044b\u043c \u0434\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0432\u0440\u0443\u0447\u043d\u0443\u044e. \u041c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u043d\u0430 \u043f\u0430\u0443\u0437\u0443 (\u0444\u0443\u043d\u043a\u0446\u0438\u044f pause), \u043c\u043e\u0436\u043d\u043e \u0432\u043e\u0437\u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c \u0447\u0442\u0435\u043d\u0438\u0435 (\u0444\u0443\u043d\u043a\u0446\u0438\u044f suspend)                  if (!paused) {                      subscription.request(1);         <\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-387554","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/387554","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=387554"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/387554\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=387554"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=387554"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=387554"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}