{"id":326777,"date":"2021-07-21T09:01:03","date_gmt":"2021-07-21T09:01:03","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=326777"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=326777","title":{"rendered":"\u0420\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 SQL \u0441 jOOQ 3.15 \u0438 R2DBC"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043d\u043e\u0432\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0432\u044b\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0433\u043e jOOQ 3.15 &#8212; \u044d\u0442\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e&nbsp;<a href=\"https:\/\/r2dbc.io\/\" rel=\"noopener noreferrer nofollow\">R2DBC<\/a>.&nbsp;\u042d\u0442\u043e \u0431\u044b\u043b \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0438 \u043c\u044b \u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u0435\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0438.  <\/p>\n<p>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c jOOQ \u0442\u0430\u043a, \u043a\u0430\u043a \u0432\u044b \u043f\u0440\u0438\u0432\u044b\u043a\u043b\u0438, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044f \u0442\u0438\u043f\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 SQL, \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0432 Java, kotlin \u0438\u043b\u0438 scala, \u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0432\u0430\u0448\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442\u0441\u044f.&nbsp;\u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u0432\u0430\u0448 jOOQ <code>ResultQuery <\/code>\u0438\u043b\u0438&nbsp;<code>Query <\/code>\u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a&nbsp;<code>Publisher&lt;R&gt; <\/code>\u0438\u043b\u0438&nbsp;<code>Publisher&lt;Integer&gt; <\/code>\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 reactive-streams  (\u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432) \u043f\u043e \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u044b\u0431\u043e\u0440\u0443.<\/p>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e (\u0438\u043b\u0438 \u0432 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a) \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432\u0430\u0448\u0435\u0433\u043e jOOQ&nbsp;<code>DSLContext <\/code>\u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e JDBC&nbsp;<code>java.sql.Connection <\/code>\u0438\u043b\u0438&nbsp;<code>javax.sql.DataSource <\/code>\u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0435\u0433\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e R2DBC&nbsp;<code>io.r2dbc.spi.Connection <\/code>\u0438\u043b\u0438&nbsp;<code>io.r2dbc.spi.ConnectionFactory<\/code>:<\/p>\n<pre><code class=\"java\">ConnectionFactory connectionFactory = ConnectionFactories.get(     ConnectionFactoryOptions         .parse(\"r2dbc:h2:file:\/\/localhost\/~\/r2dbc-test\")         .mutate()         .option(ConnectionFactoryOptions.USER, \"sa\")         .option(ConnectionFactoryOptions.PASSWORD, \"\")         .build() );   DSLContext ctx = DSL.using(connectionFactory);<\/code><\/pre>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 Spring Boot \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 jOOQ \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<blockquote>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u043e\u0431\u0437\u043e\u0440:&nbsp;<a href=\"https:\/\/t.co\/tUgNkwzCK4\" rel=\"noopener noreferrer nofollow\">pic.twitter.com\/tUgNkwzCK4<\/a><\/p>\n<p>&#8212; \u0410\u043d\u0433\u0435\u043b \u041b\u0435\u043e\u043d\u0430\u0440\u0434 (@anghelleonard)&nbsp;<a href=\"https:\/\/twitter.com\/anghelleonard\/status\/1415531963616727042?ref_src=twsrc%5Etfw\" rel=\"noopener noreferrer nofollow\">15 \u0438\u044e\u043b\u044f 2021 \u0433.<\/a><\/p>\n<\/blockquote>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u044d\u0442\u043e\u0442&nbsp;<code>DSLContext<\/code>, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e, \u043d\u043e \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0435&nbsp;\u043c\u0435\u0442\u043e\u0434\u044b <code>execute() <\/code>\u0438\u043b\u0438&nbsp;<code>fetch()<\/code>, \u0432\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0431\u0435\u0440\u043d\u0438\u0442\u0435 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432&nbsp;<code>Flux<\/code>, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440.&nbsp;\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u0432\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043a\u043e\u0434\u0430 jOOQ \u043d\u0430 \u0441\u0432\u043e\u0435\u0439 H2&nbsp;<code>INFORMATION_SCHEMA<\/code>, \u0442\u043e\u0433\u0434\u0430 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c:<\/p>\n<pre><code class=\"java\">record Table(String schema, String table) {}   Flux.from(ctx         .select(             INFORMATION_SCHEMA.TABLES.TABLE_SCHEMA,             INFORMATION_SCHEMA.TABLES.TABLE_NAME)         .from(INFORMATION_SCHEMA.TABLES))       \/\/ Type safe mapping from Record2&lt;String, String&gt; to Table::new     .map(Records.mapping(Table::new))     .doOnNext(System.out::println)     .subscribe();<\/code><\/pre>\n<p>jOOQ \u043f\u043e\u043b\u0443\u0447\u0438\u0442 R2DBC&nbsp;<code>Connection <\/code>\u0443 <code>ConnectionFactory <\/code>\u0438 \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442 \u0435\u0435 \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438, \u0447\u0442\u043e \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043b\u043e\u0436\u043d\u043e \u0441 R2DBC \u0438 reactor.&nbsp;\u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0432\u044b\u0448\u0435 \u043a\u043e\u0434 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u043c\u0443 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0437\u0430\u043f\u0440\u043e\u0441\u0443:  <\/p>\n<pre><code class=\"java\">Flux.usingWhen(         connectionFactory.create(),         c -&gt; c.createStatement(                 \"\"\"                 SELECT table_schema, table_name                 FROM information_schema.tables                 \"\"\"              ).execute(),         c -&gt; c.close()     )     .flatMap(it -&gt; it.map((r, m) -&gt;           new Table(r.get(0, String.class), r.get(1, String.class))     ))     .doOnNext(System.out::println)     .subscribe();<\/code><\/pre>\n<p>\u041e\u0431\u0430 \u043d\u0430\u043f\u0435\u0447\u0430\u0442\u0430\u044e\u0442 \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td colspan=\"3\" rowspan=\"2\">\n<p>Table[schema=INFORMATION_SCHEMA, table=TABLE_PRIVILEGES] Table[schema=INFORMATION_SCHEMA, table=REFERENTIAL_CONSTRAINTS] Table[schema=INFORMATION_SCHEMA, table=TABLE_TYPES] Table[schema=INFORMATION_SCHEMA, table=QUERY_STATISTICS] Table[schema=INFORMATION_SCHEMA, table=TABLES] Table[schema=INFORMATION_SCHEMA, table=SESSION_STATE] Table[schema=INFORMATION_SCHEMA, table=HELP] Table[schema=INFORMATION_SCHEMA, table=COLUMN_PRIVILEGES] Table[schema=INFORMATION_SCHEMA, table=SYNONYMS] Table[schema=INFORMATION_SCHEMA, table=SESSIONS] Table[schema=INFORMATION_SCHEMA, table=IN_DOUBT] Table[schema=INFORMATION_SCHEMA, table=USERS] Table[schema=INFORMATION_SCHEMA, table=COLLATIONS] Table[schema=INFORMATION_SCHEMA, table=SCHEMATA] Table[schema=INFORMATION_SCHEMA, table=TABLE_CONSTRAINTS] Table[schema=INFORMATION_SCHEMA, table=INDEXES] Table[schema=INFORMATION_SCHEMA, table=ROLES] Table[schema=INFORMATION_SCHEMA, table=FUNCTION_COLUMNS] Table[schema=INFORMATION_SCHEMA, table=CONSTANTS] Table[schema=INFORMATION_SCHEMA, table=SEQUENCES] Table[schema=INFORMATION_SCHEMA, table=RIGHTS] Table[schema=INFORMATION_SCHEMA, table=FUNCTION_ALIASES] Table[schema=INFORMATION_SCHEMA, table=CATALOGS] Table[schema=INFORMATION_SCHEMA, table=CROSS_REFERENCES] Table[schema=INFORMATION_SCHEMA, table=SETTINGS] Table[schema=INFORMATION_SCHEMA, table=DOMAINS] Table[schema=INFORMATION_SCHEMA, table=KEY_COLUMN_USAGE] Table[schema=INFORMATION_SCHEMA, table=LOCKS] Table[schema=INFORMATION_SCHEMA, table=COLUMNS] Table[schema=INFORMATION_SCHEMA, table=TRIGGERS] Table[schema=INFORMATION_SCHEMA, table=VIEWS] Table[schema=INFORMATION_SCHEMA, table=TYPE_INFO] Table[schema=INFORMATION_SCHEMA, table=CONSTRAINTS]<\/p>\n<\/td>\n<\/tr>\n<tr><\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 JDBC, \u0430 \u043d\u0435 R2DBC, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c jOOQ API \u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c\u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0432\u044b\u0448\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0432\u0430\u0448\u0430 \u043b\u044e\u0431\u0438\u043c\u0430\u044f \u0421\u0423\u0411\u0414 \u0435\u0449\u0435 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0434\u0440\u0430\u0439\u0432\u0435\u0440 R2DBC.&nbsp;\u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 <a href=\"https:\/\/r2dbc.io\/drivers\/\" rel=\"noopener noreferrer nofollow\">\u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u0432<\/a> \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e <a href=\"https:\/\/r2dbc.io\/\" rel=\"noopener noreferrer nofollow\">r2dbc.io<\/a> \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/github.com\/oracle\/oracle-r2dbc\" rel=\"noopener noreferrer nofollow\">oracle-r2dbc<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/r2dbc\/r2dbc-h2\" rel=\"noopener noreferrer nofollow\">r2dbc-h2<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/pgjdbc\/r2dbc-postgresql\" rel=\"noopener noreferrer nofollow\">r2dbc-postgresql<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/mirromutth\/r2dbc-mysql\" rel=\"noopener noreferrer nofollow\">r2dbc-mysql<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/r2dbc\/r2dbc-mssql\" rel=\"noopener noreferrer nofollow\">r2dbc-mssql<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/mariadb-corporation\/mariadb-connector-r2dbc\" rel=\"noopener noreferrer nofollow\">mariadb-connector-r2dbc<\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u0435 \u0438\u0437 \u043d\u0438\u0445 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0441 jOOQ 3.15+.<\/p>\n<h2>\u0420\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440<\/h2>\n<p>\u041f\u043e\u0438\u0433\u0440\u0430\u0439\u0442\u0435 \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u043c \u0437\u0434\u0435\u0441\u044c: <a href=\"https:\/\/github.com\/jOOQ\/jOOQ\/tree\/main\/jOOQ-examples\/jOOQ-r2dbc-example\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/jOOQ\/jOOQ\/tree\/main\/jOOQ-examples\/jOOQ-r2dbc-example<\/a> <\/p>\n<p>\u041e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0445\u0435\u043c\u0443:<\/p>\n<pre><code class=\"sql\">CREATE TABLE r2dbc_example.author (   id INT NOT NULL AUTO_INCREMENT,   first_name VARCHAR(100) NOT NULL,   last_name VARCHAR(100) NOT NULL,       CONSTRAINT pk_author PRIMARY KEY (id) );   CREATE TABLE r2dbc_example.book (   id INT NOT NULL AUTO_INCREMENT,   author_id INT NOT NULL,   title VARCHAR(100) NOT NULL,       CONSTRAINT pk_book PRIMARY KEY (id),   CONSTRAINT fk_book_author FOREIGN KEY (id)      REFERENCES r2dbc_example.author );<\/code><\/pre>\n<p>\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434<\/p>\n<pre><code class=\"java\">Flux.from(ctx         .insertInto(AUTHOR)         .columns(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)         .values(\"John\", \"Doe\")         .returningResult(AUTHOR.ID))     .flatMap(id -&gt; ctx         .insertInto(BOOK)         .columns(BOOK.AUTHOR_ID, BOOK.TITLE)         .values(id.value1(), \"Fancy Book\"))     .thenMany(ctx         .select(              BOOK.author().FIRST_NAME,               BOOK.author().LAST_NAME,               BOOK.TITLE)         .from(BOOK))     .doOnNext(System.out::println)     .subscribe();<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0434\u0432\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c, \u043f\u043e\u043b\u0443\u0447\u0438\u0432 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<p>FIRST_NAME<\/p>\n<\/td>\n<td>\n<p>LAST_NAME<\/p>\n<\/td>\n<td>\n<p>TITLE<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>John      <\/p>\n<\/td>\n<td>\n<p>Doe      <\/p>\n<\/td>\n<td>\n<p>Fancy Book<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<\/div>\n<p> \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\/post\/568830\/\"> https:\/\/habr.com\/ru\/post\/568830\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<p>\u041e\u0434\u043d\u0430 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u043d\u043e\u0432\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u043d\u0435\u0434\u0430\u0432\u043d\u043e \u0432\u044b\u043f\u0443\u0449\u0435\u043d\u043d\u043e\u0433\u043e jOOQ 3.15 &#8212; \u044d\u0442\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e&nbsp;<a href=\"https:\/\/r2dbc.io\/\" rel=\"noopener noreferrer nofollow\">R2DBC<\/a>.&nbsp;\u042d\u0442\u043e \u0431\u044b\u043b \u043e\u0447\u0435\u043d\u044c \u043f\u043e\u043f\u0443\u043b\u044f\u0440\u043d\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u0438 \u043c\u044b \u043d\u0430\u043a\u043e\u043d\u0435\u0446 \u0435\u0433\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u043b\u0438.  <\/p>\n<p>\u0412\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c jOOQ \u0442\u0430\u043a, \u043a\u0430\u043a \u0432\u044b \u043f\u0440\u0438\u0432\u044b\u043a\u043b\u0438, \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0432\u0430\u044f \u0442\u0438\u043f\u043e\u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u044b\u0439 SQL, \u0432\u0441\u0442\u0440\u043e\u0435\u043d\u043d\u044b\u0439 \u0432 Java, kotlin \u0438\u043b\u0438 scala, \u043d\u043e \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u0432\u0430\u0448\u0438\u0445 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432 \u0431\u043e\u043b\u044c\u0448\u0435 \u043d\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u0435\u0442\u0441\u044f.&nbsp;\u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e \u0432\u0430\u0448 jOOQ <code>ResultQuery <\/code>\u0438\u043b\u0438&nbsp;<code>Query <\/code>\u043c\u043e\u0436\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043a\u0430\u043a&nbsp;<code>Publisher&lt;R&gt; <\/code>\u0438\u043b\u0438&nbsp;<code>Publisher&lt;Integer&gt; <\/code>\u0432 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 reactive-streams  (\u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432) \u043f\u043e \u0432\u0430\u0448\u0435\u043c\u0443 \u0432\u044b\u0431\u043e\u0440\u0443.<\/p>\n<p>\u0412\u043c\u0435\u0441\u0442\u043e (\u0438\u043b\u0438 \u0432 \u0434\u043e\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u0435 \u043a) \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0432\u0430\u0448\u0435\u0433\u043e jOOQ&nbsp;<code>DSLContext <\/code>\u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e JDBC&nbsp;<code>java.sql.Connection <\/code>\u0438\u043b\u0438&nbsp;<code>javax.sql.DataSource <\/code>\u043f\u0440\u043e\u0441\u0442\u043e \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0435\u0433\u043e \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e R2DBC&nbsp;<code>io.r2dbc.spi.Connection <\/code>\u0438\u043b\u0438&nbsp;<code>io.r2dbc.spi.ConnectionFactory<\/code>:<\/p>\n<pre><code class=\"java\">ConnectionFactory connectionFactory = ConnectionFactories.get(     ConnectionFactoryOptions         .parse(\"r2dbc:h2:file:\/\/localhost\/~\/r2dbc-test\")         .mutate()         .option(ConnectionFactoryOptions.USER, \"sa\")         .option(ConnectionFactoryOptions.PASSWORD, \"\")         .build() );   DSLContext ctx = DSL.using(connectionFactory);<\/code><\/pre>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 Spring Boot \u0434\u043b\u044f \u0430\u0432\u0442\u043e\u043c\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u043d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 jOOQ \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c:<\/p>\n<blockquote>\n<p>\u041a\u043e\u043d\u0435\u0447\u043d\u043e, \u0445\u043e\u0440\u043e\u0448\u0438\u0439 \u043e\u0431\u0437\u043e\u0440:&nbsp;<a href=\"https:\/\/t.co\/tUgNkwzCK4\" rel=\"noopener noreferrer nofollow\">pic.twitter.com\/tUgNkwzCK4<\/a><\/p>\n<p>&#8212; \u0410\u043d\u0433\u0435\u043b \u041b\u0435\u043e\u043d\u0430\u0440\u0434 (@anghelleonard)&nbsp;<a href=\"https:\/\/twitter.com\/anghelleonard\/status\/1415531963616727042?ref_src=twsrc%5Etfw\" rel=\"noopener noreferrer nofollow\">15 \u0438\u044e\u043b\u044f 2021 \u0433.<\/a><\/p>\n<\/blockquote>\n<p>\u0418\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u044d\u0442\u043e\u0442&nbsp;<code>DSLContext<\/code>, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u0441\u0442\u0440\u043e\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u044b \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e, \u043d\u043e \u0432\u043c\u0435\u0441\u0442\u043e \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u0443\u044e\u0449\u0438\u0435&nbsp;\u043c\u0435\u0442\u043e\u0434\u044b <code>execute() <\/code>\u0438\u043b\u0438&nbsp;<code>fetch()<\/code>, \u0432\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043e\u0431\u0435\u0440\u043d\u0438\u0442\u0435 \u0437\u0430\u043f\u0440\u043e\u0441 \u0432&nbsp;<code>Flux<\/code>, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440.&nbsp;\u041f\u0440\u0435\u0434\u043f\u043e\u043b\u043e\u0436\u0438\u043c, \u0447\u0442\u043e \u0432\u044b \u0437\u0430\u043f\u0443\u0441\u0442\u0438\u043b\u0438 \u0433\u0435\u043d\u0435\u0440\u0430\u0442\u043e\u0440 \u043a\u043e\u0434\u0430 jOOQ \u043d\u0430 \u0441\u0432\u043e\u0435\u0439 H2&nbsp;<code>INFORMATION_SCHEMA<\/code>, \u0442\u043e\u0433\u0434\u0430 \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c:<\/p>\n<pre><code class=\"java\">record Table(String schema, String table) {}   Flux.from(ctx         .select(             INFORMATION_SCHEMA.TABLES.TABLE_SCHEMA,             INFORMATION_SCHEMA.TABLES.TABLE_NAME)         .from(INFORMATION_SCHEMA.TABLES))       \/\/ Type safe mapping from Record2&lt;String, String&gt; to Table::new     .map(Records.mapping(Table::new))     .doOnNext(System.out::println)     .subscribe();<\/code><\/pre>\n<p>jOOQ \u043f\u043e\u043b\u0443\u0447\u0438\u0442 R2DBC&nbsp;<code>Connection <\/code>\u0443 <code>ConnectionFactory <\/code>\u0438 \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442 \u0435\u0435 \u043f\u043e\u0441\u043b\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0443\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0435\u0441\u0443\u0440\u0441\u0430\u043c\u0438, \u0447\u0442\u043e \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0441\u043b\u043e\u0436\u043d\u043e \u0441 R2DBC \u0438 reactor.&nbsp;\u0414\u0440\u0443\u0433\u0438\u043c\u0438 \u0441\u043b\u043e\u0432\u0430\u043c\u0438, \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u043d\u044b\u0439 \u0432\u044b\u0448\u0435 \u043a\u043e\u0434 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u043c\u0443 \u0432\u0440\u0443\u0447\u043d\u0443\u044e \u0437\u0430\u043f\u0440\u043e\u0441\u0443:  <\/p>\n<pre><code class=\"java\">Flux.usingWhen(         connectionFactory.create(),         c -&gt; c.createStatement(                 \"\"\"                 SELECT table_schema, table_name                 FROM information_schema.tables                 \"\"\"              ).execute(),         c -&gt; c.close()     )     .flatMap(it -&gt; it.map((r, m) -&gt;           new Table(r.get(0, String.class), r.get(1, String.class))     ))     .doOnNext(System.out::println)     .subscribe();<\/code><\/pre>\n<p>\u041e\u0431\u0430 \u043d\u0430\u043f\u0435\u0447\u0430\u0442\u0430\u044e\u0442 \u0447\u0442\u043e-\u0442\u043e \u0432\u0440\u043e\u0434\u0435 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u0433\u043e:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td colspan=\"3\" rowspan=\"2\">\n<p>Table[schema=INFORMATION_SCHEMA, table=TABLE_PRIVILEGES] Table[schema=INFORMATION_SCHEMA, table=REFERENTIAL_CONSTRAINTS] Table[schema=INFORMATION_SCHEMA, table=TABLE_TYPES] Table[schema=INFORMATION_SCHEMA, table=QUERY_STATISTICS] Table[schema=INFORMATION_SCHEMA, table=TABLES] Table[schema=INFORMATION_SCHEMA, table=SESSION_STATE] Table[schema=INFORMATION_SCHEMA, table=HELP] Table[schema=INFORMATION_SCHEMA, table=COLUMN_PRIVILEGES] Table[schema=INFORMATION_SCHEMA, table=SYNONYMS] Table[schema=INFORMATION_SCHEMA, table=SESSIONS] Table[schema=INFORMATION_SCHEMA, table=IN_DOUBT] Table[schema=INFORMATION_SCHEMA, table=USERS] Table[schema=INFORMATION_SCHEMA, table=COLLATIONS] Table[schema=INFORMATION_SCHEMA, table=SCHEMATA] Table[schema=INFORMATION_SCHEMA, table=TABLE_CONSTRAINTS] Table[schema=INFORMATION_SCHEMA, table=INDEXES] Table[schema=INFORMATION_SCHEMA, table=ROLES] Table[schema=INFORMATION_SCHEMA, table=FUNCTION_COLUMNS] Table[schema=INFORMATION_SCHEMA, table=CONSTANTS] Table[schema=INFORMATION_SCHEMA, table=SEQUENCES] Table[schema=INFORMATION_SCHEMA, table=RIGHTS] Table[schema=INFORMATION_SCHEMA, table=FUNCTION_ALIASES] Table[schema=INFORMATION_SCHEMA, table=CATALOGS] Table[schema=INFORMATION_SCHEMA, table=CROSS_REFERENCES] Table[schema=INFORMATION_SCHEMA, table=SETTINGS] Table[schema=INFORMATION_SCHEMA, table=DOMAINS] Table[schema=INFORMATION_SCHEMA, table=KEY_COLUMN_USAGE] Table[schema=INFORMATION_SCHEMA, table=LOCKS] Table[schema=INFORMATION_SCHEMA, table=COLUMNS] Table[schema=INFORMATION_SCHEMA, table=TRIGGERS] Table[schema=INFORMATION_SCHEMA, table=VIEWS] Table[schema=INFORMATION_SCHEMA, table=TYPE_INFO] Table[schema=INFORMATION_SCHEMA, table=CONSTRAINTS]<\/p>\n<\/td>\n<\/tr>\n<tr><\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e, \u0435\u0441\u043b\u0438 \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435 JDBC, \u0430 \u043d\u0435 R2DBC, \u0432\u044b \u043c\u043e\u0436\u0435\u0442\u0435 \u043f\u0440\u043e\u0434\u043e\u043b\u0436\u0430\u0442\u044c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c jOOQ API \u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c\u0438 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0445 \u043f\u043e\u0442\u043e\u043a\u043e\u0432 \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0431\u043b\u043e\u043a\u0438\u0440\u043e\u0432\u043a\u0438 \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a \u0436\u0435, \u043a\u0430\u043a \u0443\u043a\u0430\u0437\u0430\u043d\u043e \u0432\u044b\u0448\u0435, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0435\u0441\u043b\u0438 \u0432\u0430\u0448\u0430 \u043b\u044e\u0431\u0438\u043c\u0430\u044f \u0421\u0423\u0411\u0414 \u0435\u0449\u0435 \u043d\u0435 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u0442 \u0440\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u044b\u0439 \u0434\u0440\u0430\u0439\u0432\u0435\u0440 R2DBC.&nbsp;\u0412 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0441\u043f\u0438\u0441\u043e\u043a \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u044b\u0445 <a href=\"https:\/\/r2dbc.io\/drivers\/\" rel=\"noopener noreferrer nofollow\">\u0434\u0440\u0430\u0439\u0432\u0435\u0440\u043e\u0432<\/a> \u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e <a href=\"https:\/\/r2dbc.io\/\" rel=\"noopener noreferrer nofollow\">r2dbc.io<\/a> \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u0442:<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/github.com\/oracle\/oracle-r2dbc\" rel=\"noopener noreferrer nofollow\">oracle-r2dbc<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/r2dbc\/r2dbc-h2\" rel=\"noopener noreferrer nofollow\">r2dbc-h2<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/pgjdbc\/r2dbc-postgresql\" rel=\"noopener noreferrer nofollow\">r2dbc-postgresql<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/mirromutth\/r2dbc-mysql\" rel=\"noopener noreferrer nofollow\">r2dbc-mysql<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/r2dbc\/r2dbc-mssql\" rel=\"noopener noreferrer nofollow\">r2dbc-mssql<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/mariadb-corporation\/mariadb-connector-r2dbc\" rel=\"noopener noreferrer nofollow\">mariadb-connector-r2dbc<\/a><\/p>\n<\/li>\n<\/ul>\n<p>\u0412\u0441\u0435 \u0438\u0437 \u043d\u0438\u0445 \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0441 jOOQ 3.15+.<\/p>\n<h2>\u0420\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u044b\u0439 \u043f\u0440\u0438\u043c\u0435\u0440<\/h2>\n<p>\u041f\u043e\u0438\u0433\u0440\u0430\u0439\u0442\u0435 \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u043c, \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u043d\u044b\u043c \u0437\u0434\u0435\u0441\u044c: <a href=\"https:\/\/github.com\/jOOQ\/jOOQ\/tree\/main\/jOOQ-examples\/jOOQ-r2dbc-example\" rel=\"noopener noreferrer nofollow\">https:\/\/github.com\/jOOQ\/jOOQ\/tree\/main\/jOOQ-examples\/jOOQ-r2dbc-example<\/a> <\/p>\n<p>\u041e\u043d \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0443\u044e \u0441\u0445\u0435\u043c\u0443:<\/p>\n<pre><code class=\"sql\">CREATE TABLE r2dbc_example.author (   id INT NOT NULL AUTO_INCREMENT,   first_name VARCHAR(100) NOT NULL,   last_name VARCHAR(100) NOT NULL,       CONSTRAINT pk_author PRIMARY KEY (id) );   CREATE TABLE r2dbc_example.book (   id INT NOT NULL AUTO_INCREMENT,   author_id INT NOT NULL,   title VARCHAR(100) NOT NULL,       CONSTRAINT pk_book PRIMARY KEY (id),   CONSTRAINT fk_book_author FOREIGN KEY (id)      REFERENCES r2dbc_example.author );<\/code><\/pre>\n<p>\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434<\/p>\n<pre><code class=\"java\">Flux.from(ctx         .insertInto(AUTHOR)         .columns(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)         .values(\"John\", \"Doe\")         .returningResult(AUTHOR.ID))     .flatMap(id -&gt; ctx         .insertInto(BOOK)         .columns(BOOK.AUTHOR_ID, BOOK.TITLE)         .values(id.value1(), \"Fancy Book\"))     .thenMany(ctx         .select(              BOOK.author().FIRST_NAME,               BOOK.author().LAST_NAME,               BOOK.TITLE)         .from(BOOK))     .doOnNext(System.out::println)     .subscribe();<\/code><\/pre>\n<p>\u0427\u0442\u043e\u0431\u044b \u0432\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0434\u0432\u0435 \u0437\u0430\u043f\u0438\u0441\u0438 \u0438 \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c \u0437\u0430\u043f\u0438\u0441\u044c, \u043f\u043e\u043b\u0443\u0447\u0438\u0432 \u0432 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0435:<\/p>\n<div>\n<div class=\"table\">\n<table>\n<tbody>\n<tr>\n<td>\n<p>FIRST_NAME<\/p>\n<\/td>\n<td>\n<p>LAST_NAME<\/p>\n<\/td>\n<td>\n<p>TITLE<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td>\n<p>John      <\/p>\n<\/td>\n<td>\n<p>Doe      <\/p>\n<\/td>\n<td>\n<p>Fancy Book<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<\/div>\n<\/div>\n<p> \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\/post\/568830\/\"> https:\/\/habr.com\/ru\/post\/568830\/<\/a><br \/><\/br><\/br><\/p>\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-326777","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/326777","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=326777"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/326777\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=326777"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=326777"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=326777"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}