R2DBC
很多用户一直在等待:jOOQ 3.15是反应式的,这要归功于新的本地R2DBC集成。最近的版本已经实现了反应式流Publisher SPI,但现在我们不再作弊了。我们不再阻塞了。只要把你的R2DBC ConnectionFactory配置的jOOQ查询包在Flux(或你选择的任何反应式流API)中,看看会发生什么。
Flux.from(ctx.select(BOOK.TITLE).from(BOOK));
阻塞(通过JDBC)和非阻塞(通过R2DBC)都可以并肩工作,允许用户在两种执行模式之间快速查询,而无需对查询构建逻辑进行任何改变。
投射ROW类型、ROW类型的ARRAY和MULTISETS
在jOOQ 3.14中实现了对标准SQL/XML和SQL/JSON的支持后,将SQL提升到新水平的另一个重要里程碑现在可以作为一个实验性功能使用。使用标准的SQL MULTISET操作符对集合进行嵌套。
该操作符目前是用SQL/XML或SQL/JSON来模拟的。当从JDBC中获取文件时,会再次解析这些文件。未来的版本还将提供本地支持(Informix、Oracle),以及使用ARRAY(各种方言,包括PostgreSQL)的模拟。
想象一下这个针对Sakila数据库的查询(https://www.jooq.org/sakila)。
var result =
ctx.select(
FILM.TITLE,
multiset(
select(ACTOR.FIRST_NAME, ACTOR.LAST_NAME)
.from(ACTOR)
.join(FILM_ACTOR).using(ACTOR.ACTOR_ID)
.where(FILM_ACTOR.FILM_ID.eq(FILM.FILM_ID))
).as("actors"),
multiset(
select(CATEGORY.NAME)
.from(CATEGORY)
.join(FILM_CATEGORY).using(CATEGORY.CATEGORY_ID)
.where(FILM_CATEGORY.FILM_ID.eq(FILM.FILM_ID))
).as("films")
)
.from(FILM)
.orderBy(FILM.TITLE)
.fetch();
对于这些目的,你真的会喜欢Java 10的var关键字。结果的类型是什么?正是如此:
Result<Record3<
String,
Result<Record2<String, String>>,
Result<Record1<String>>
>>
它包含:
+---------------------------+--------------------------------------------------+---------------+
|title |actors |films |
+---------------------------+--------------------------------------------------+---------------+
|ACADEMY DINOSAUR |[(PENELOPE, GUINESS), (CHRISTIAN, GABLE), (LUCI...|[(Documentary)]|
|ACE GOLDFINGER |[(BOB, FAWCETT), (MINNIE, ZELLWEGER), (SEAN, GU...|[(Horror)] |
|ADAPTATION HOLES |[(NICK, WAHLBERG), (BOB, FAWCETT), (CAMERON, ST...|[(Documentary)]|
...
两个集合被嵌套在一个查询中,没有产生任何不需要的笛卡尔产品和重复的数据。请继续关注,我们已经添加了更多的好东西!请看这篇文章:如何以类型安全的方式将上述结构类型映射到你的名义类型(如Java 16记录),而无需反射
更多信息在这里:
新方言
我们增加了对 5 种(!)新的 SQLDialect 的支持。这在以前的小版本中是史无前例的。这些新的方言是
- BIGQUERY
- EXASOL
- IGNITE
- JAVA
- SNOWFLAKE
是的,有一种实验性的 "JAVA "方言。如果你想用www.jooq.org/translate,把你的本地SQL查询翻译成jOOQ,它主要是有用的,而且不能被执行。在不久的将来,我们可能还会增加SCALA和KOTLIN,这取决于需求。
BigQuery和Snowflake在大众投票中早就该支持了。加急的EXASOL支持是由一个客户赞助的,这是一个很好的提醒,这永远是一个选择。你需要更快速的东西?我们可以让它发生,即使该功能在路线图上不是很受欢迎。
许多其他方言已经被更新了,包括REDSHIFT、HANA、VERTICA,还有两个已经被废弃了。INGRES和ORACLE10G,因为它们越来越不流行了。
企业版放弃对Java 6/7的支持,OSS版要求使用Java 11
我们正在清理对旧的依赖性和功能的支持。从jOOQ 3.12开始,我们只向jOOQ企业版客户提供Java 6和7的支持。随着jOOQ 3.15的推出,这种支持现在已经被移除,Java 8是商业版的新基线,Java 11是jOOQ开源版的新基线,这意味着OSS版现在终于模块化了,我们可以获得像Flow API(见R2DBC)和@Deprecate(forRemoval,自)这样的小东西。
升级到Java 8后,我们可以对内部进行令人兴奋的新改进,因为我们终于可以使用默认方法、lambdas、通用的目标类型推理、有效的final、钻石操作符、try-with-resources、字符串开关,等等。完善我们的代码库导致了狗粮,而这又为你带来了新的功能。例如,我们非常强调ResultQuery.collect(),重构了内部结构:https://blog.jooq.org/2021/05/17/use-resultquery-collect-to-implement-powerful-mappings/
有新的辅助类型,如org.jooq.Rows和org.jooq.Records,以获得更多的功能转换便利。更多的函数意味着更少的循环,同时也意味着更少的ArrayList分配。
同时,我们已经开始为商业版本建立一个Java 17准备好的发行版,它可以解锁更好的记录类型支持。
重构ResultQuery,使其与DML一起工作
有了以上所有与Java 8相关的好处,以及jOOQ更多的功能使用,我们也终于重构了我们的DML语句类型层次(INSERT,UPDATE,DELETE),让它们各自的RETURNING子句返回一个实际的ResultQuery。这意味着你现在可以在你的DML语句中使用stream()、collect()、fetchMap()和subscribe()(通过R2DBC),甚至可以把它们放在WITH子句中(在PostgreSQL中)。
对分析器/翻译器用例的大规模改进
jOOQ的次要价值主张是使用它的解析器和翻译器,而不是DSL API,后者也可以在我们的网站上免费获得 :https://www.jooq.org/translate
随着对这一产品的需求不断增加,我们已经大大改善了这一体验:
- ParsingConnection不再是实验性的了
- 现在可以进行批处理了
- 我们为输入/输出的SQL字符串对增加了一个缓存,以大大加快整合速度
- 我们现在推迟了绑定变量类型的推断,以使用实际的PreparedStatement信息。这产生了更准确的结果,特别是当数据类型不为解析器所知时。
- 一个新的ParseListener SPI允许钩住解析器并通过对列、表和谓词表达式的自定义语法支持来扩展它。
CREATE PROCEDURE, FUNCTION, TRIGGER和更多程序性指令
在最近的版本中,我们已经开始为商业发行版进行过程性语言的扩展工作。除了创建匿名块,我们现在还支持程序、函数和触发器的所有生命周期管理DDL,它们可以包含过程性语言逻辑。
如果你支持多个RDBMS,并希望以一种与厂商无关的方式将更多的数据处理逻辑转移到服务器端,这就是一个好消息。
明确的JDBC驱动依赖,避免反射
为了做好AOP的准备,我们正在慢慢地取消内部反射的使用,这意味着我们正在试验明确的JDBC驱动构建时的依赖性。目前这影响到了
- Oracle
- PostgreSQL
- SQL Server
到目前为止,只有Maven Central提供的驱动被添加为依赖项。