Реактивное программирование — это новое модное слово, которое по сути означает просто асинхронное программирование или обмен сообщениями.
Факт заключается в том, что функциональный синтаксис очень помогает при структурировании цепочек асинхронного выполнения, и сегодня мы увидим, как мы можем сделать это в Java 8, используя jOOQ и новый API CompletableFuture .
На самом деле все довольно просто:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
// Initiate an asynchronous call chain CompletableFuture // This lambda will supply an int value // indicating the number of inserted rows .supplyAsync(() -> DSL .using(configuration) .insertInto(AUTHOR, AUTHOR.ID, AUTHOR.LAST_NAME) .values( 3 , "Hitchcock" ) .execute() ) // This will supply an AuthorRecord value // for the newly inserted author .handleAsync((rows, throwable) -> DSL .using(configuration) .fetchOne(AUTHOR, AUTHOR.ID.eq( 3 )) ) // This should supply an int value indicating // the number of rows, but in fact it'll throw // a constraint violation exception .handleAsync((record, throwable) -> { record.changed( true ); return record.insert(); }) // This will supply an int value indicating // the number of deleted rows .handleAsync((rows, throwable) -> DSL .using(configuration) .delete(AUTHOR) .where(AUTHOR.ID.eq( 3 )) .execute() ) // This tells the calling thread to wait for all // chained execution units to be executed .join(); |
Что на самом деле здесь произошло? Ничего необычного. Есть 4 исполнительных блока:
- Тот, который вставляет новый АВТОР
- Тот, который получает тот же самый АВТОР снова
- Тот, который повторно вставляет вновь извлеченный AUTHOR (выбрасывая исключение)
- Тот, который игнорирует выброшенное исключение и снова удаляет АВТОРА
Наконец, когда цепочка выполнения установлена, вызывающий поток объединит всю цепочку с помощью метода CompletableFuture.join()
, который по сути аналогичен Future.get()
, за исключением того, что он не Future.get()
ни одного проверенного исключения. ,
Сравнивая это с другими API
Другие API, такие как Scala’s Slick , реализовали аналогичные вещи через «стандартный API», такие как вызовы flatMap()
. В настоящее время мы не собираемся имитировать такие API-интерфейсы, поскольку считаем, что новые API-интерфейсы Java 8 станут гораздо более идиоматичными для носителей языка Java. В частности, при выполнении SQL очень важно правильно настроить пул соединений и транзакции. Семантика асинхронно связанных цепей выполнения и их связь с транзакциями очень тонки. Если вы хотите, чтобы транзакция охватывала более одного такого блока, вам придется кодировать ее самостоятельно через Configuration
jOOQ и содержащийся в ней ConnectionProvider
.
Блокировка JDBC
Очевидно, что всегда будет один блокирующий барьер для таких решений, и это сам JDBC, который очень трудно превратить в асинхронный API. Фактически, немногие базы данных действительно поддерживают асинхронное выполнение запросов и курсоры, поскольку чаще всего один сеанс базы данных может использоваться только одним потоком для одного запроса за раз.
Ссылка: | Асинхронное выполнение SQL с помощью jOOQ и Java 8 CompletableFuture от нашего партнера по JCG Лукаса Эдера из блога JAVA, SQL и AND JOOQ . |