当前位置:网站首页>用jOOQ 3.17投射类型安全的嵌套表记录
用jOOQ 3.17投射类型安全的嵌套表记录
2022-07-30 19:33:00 【JAVAQXQ】
一个长期存在的功能请求没有得到jOOQ社区的喜爱,尽管很多人可能想要它。它的标题是: 让 Table<R> 延伸到 SelectField<R> : github.com/jOOQ/jOOQ/i…
这个功能的具体含义是什么?
厉害的PostgreSQL
让我们来看看PostgreSQL的一个非常酷的功能。在PostgreSQL中,可以通过各种方式嵌套记录,包括在SELECT子句中简单地引用(非限定的)表名。使用sakila数据库,这就是有效的PostgreSQL:
SELECT DISTINCT actor, category FROM actor JOIN film_actor USING (actor_id) JOIN film_category USING (film_id) JOIN category USING (category_id) 复制代码
这列出了所有的演员和他们所演的电影类别。这实际上只有一个意思,对吗?看起来好像是这个的语法糖,在所有的数据库产品上都有效:
SELECT DISTINCT actor.*, category.* FROM actor JOIN film_actor USING (actor_id) JOIN film_category USING (film_id) JOIN category USING (category_id) 复制代码
但它有微妙的不同。结果看起来像这样,在psql中:
actor | category -------------------------------------------------+--------------------------------------- ... | (1,PENELOPE,GUINESS,"2006-02-15 04:34:33") | (12,Music,"2006-02-15 04:46:27") (1,PENELOPE,GUINESS,"2006-02-15 04:34:33") | (13,New,"2006-02-15 04:46:27") (1,PENELOPE,GUINESS,"2006-02-15 04:34:33") | (14,Sci-Fi,"2006-02-15 04:46:27") (1,PENELOPE,GUINESS,"2006-02-15 04:34:33") | (15,Sports,"2006-02-15 04:46:27") (2,NICK,WAHLBERG,"2006-02-15 04:34:33") | (1,Action,"2006-02-15 04:46:27") (2,NICK,WAHLBERG,"2006-02-15 04:34:33") | (2,Animation,"2006-02-15 04:46:27") ... | 复制代码
如果你用DBeaver 来显示结果,你会看到一个类似的嵌套结构:
[

这里发生的情况是,PostgreSQL简单地将两个表嵌套为输出中的嵌套记录。这种表示方法与投射星号(*)有点不同,但在逻辑上是一样的(有一些细微的差别)。这不是很酷吗?你们中的一些人可能习惯于像这样使用ROW构造函数(其中 ROW 关键字是可选的):
SELECT DISTINCT ROW(actor_id, first_name, last_name) AS actor, ROW(category_id, name) AS category FROM actor JOIN film_actor USING (actor_id) JOIN film_category USING (film_id) JOIN category USING (category_id) 复制代码
这也会产生嵌套记录,尽管这次没有记录类型,来自psql:
actor | category ---------------------------+----------------- ... | (1,PENELOPE,GUINESS) | (12,Music) (1,PENELOPE,GUINESS) | (13,New) (1,PENELOPE,GUINESS) | (14,Sci-Fi) (1,PENELOPE,GUINESS) | (15,Sports) (2,NICK,WAHLBERG) | (1,Action) (2,NICK,WAHLBERG) | (2,Animation) (2,NICK,WAHLBERG) | (3,Children) (2,NICK,WAHLBERG) | (4,Classics) 复制代码
或者,从DBeaver:
[

这可以在jOOQ中使用吗?
虽然Oracle/PostgreSQL的UDTs一直可用,但从jOOQ 3.15开始,这种从 SELECT 子句中预测的临时嵌套记录表达式就可以在jOOQ中使用。就像 伟大的 MULTISET 操作符 一样,它们是访问更强大的嵌套集合映射的关键。
但是从jOOQ 3.17开始,表表达式版本现在终于也可以访问了。在jOOQ中,以前来自PostgreSQL的SQL查询将转化为这个:
// Projecting table expressions
Result<Record2<ActorRecord, CategoryRecord>> result1 =
ctx.selectDistinct(ACTOR, CATEGORY)
.from(ACTOR)
.join(FILM_ACTOR).using(FILM_ACTOR.ACTOR_ID)
.join(FILM_CATEGORY).using(FILM_CATEGORY.FILM_ID)
.join(CATEGORY).using(CATEGORY.CATEGORY_ID)
.fetch();
// Projecting ad-hoc ROW expressions
Result<Record2<
Record3<Long, String, String>, // actor
Record2<Long, String> // category
>> result2 =
ctx.selectDistinct(
row(
ACTOR.ACTOR_ID,
ACTOR.FIRST_NAME,
ACTOR.LAST_NAME
).as("actor"),
row(CATEGORY.CATEGORY_ID, CATEGORY.NAME).as("category")
)
.from(ACTOR)
.join(FILM_ACTOR).using(FILM_ACTOR.ACTOR_ID)
.join(FILM_CATEGORY).using(FILM_CATEGORY.FILM_ID)
.join(CATEGORY).using(CATEGORY.CATEGORY_ID)
.fetch();
复制代码就像jOOQ 3.15一样,你也可以通过特设的转换器将jOOQ生成的记录转换为对你的目标消费者更有用的东西,例如Java 16 record 类型。
与隐式连接相结合
jOOQ的一个非常强大的功能是隐式连接 ,它在jOOQ 3.11中被加入。也许,你觉得一直写显式连接语法不是很顺手?为什么不这样写呢:
Result<Record2<CustomerRecord, CountryRecord>> result =
ctx.select(
CUSTOMER,
CUSTOMER.address().city().country()
)
.from(CUSTOMER)
.fetch();
复制代码请注意,我们并没有投射 CUSTOMER 或 COUNTRY 表的任何单独的列,我们只是投射整个表,就像在PostgreSQL中一样,而且所有的类型都是安全的,在结果记录上有getters和setters。
注意事项
像往常一样,要知道你在做什么,以及为什么要这样做。在PostgreSQL和jOOQ中,投射 CUSTOMER 表大多只是投射 CUSTOMER.* 的糖,也就是说,你可能得到很多你不需要的数据。总会有一个便利/性能的权衡。理想情况下,如果你想经常使用这种方法,在你的数据库中创建视图,并为这些视图生成jOOQ代码。通过jOOQ中的合成外键,你仍然可以从视图的隐式连接语法中获益。
边栏推荐
- How to build FTP server under win2003
- MySQL函数(经典收藏)
- 牛客刷题系列之进阶版(搜索旋转排序数组,链表内指定区间反转)
- MySQL database - views and indexes
- el-input 只能输入整数(包括正数、负数、0)或者只能输入整数(包括正数、负数、0)和小数
- 【科普】无线电波怎样传送信息?
- MySQL performance optimization (hardware, system configuration, table structure, SQL statements)
- 阿里面试这些微服务还不会?那还是别去了,基本等通知
- The technology is very powerful, do you still need to "manage up"?
- [PyTorchVideo Tutorial 01] Quickly implement video action recognition
猜你喜欢
随机推荐
又一家公司面试的内容
mysql慢查询优化
VBA 连接Access数据库和Excle
MindSpore:数据处理问题
MindSpore: CV.Rescale(rescale,shift)中参数rescale和shift的含义?
Zabbix 5.0 监控教程(一)
Download and installation of the latest version of MySQL 8.0 under Linux (detailed steps)
MindSpore:【JupyterLab】按照新手教程训练时报错
Frog jumping steps (recursive and non-recursive) ------- Xiaolele walks the steps
Start foreground Activity
【私人系列】日常PHP遇到的各种稀奇古怪的问题
VBA批量将Excel数据导入Access数据库
Encapsulates a console file selector based on inquirer
MindSpore:【resnet_thor模型】尝试运行resnet_thor时报Could not convert to
【MindSpore】用coco2017训练Model_zoo上的 yolov4,迭代了两千多batch_size之后报错,大佬们帮忙看看。
Win11如何更改默认下载路径?Win11更改默认下载路径的方法
MySQL数据库之JDBC编程
What is a RESTful API?
PostgreSQL 14.4如何安装使用
Listen to the boot broadcast



![[hbuilder] cannot run some projects, open the terminal and cannot enter commands](/img/fa/63f36683d090558f3fe5f582d86ca0.png)





