当前位置:网站首页>用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中的合成外键,你仍然可以从视图的隐式连接语法中获益。
边栏推荐
- NXP IMX8QXP replacement DDR model operation process
- 青蛙跳台阶(递归和非递归)-------小乐乐走台阶
- The 17th "Revitalization Cup" National Youth Vocational Skills Competition - Computer Programmers (Cloud Computing Platform and Operation and Maintenance) Participation Review and Summary
- VBA batch import Excel data into Access database
- MySQL数据库 ---MySQL表的增删改查(进阶)
- Zabbix 5.0 监控教程(一)
- 阿里面试这些微服务还不会?那还是别去了,基本等通知
- MindSpore:对image作normalize的目的是什么?
- iPhone真是十三香?两代产品完全对比,或许上一代更值得买
- 跨进程启动后台服务
猜你喜欢
牛客刷题系列之进阶版(搜索旋转排序数组,链表内指定区间反转)
MySQL大批量造数据
VBA 连接Access数据库和Excle
数据库索引:索引并不是万能药
centos7安装mysql8
来了!东方甄选为龙江农产品直播带货
VBA connects Access database and Excel
These services can't ali interview?Then don't go to, the basic notification, etc
MindSpore: CV.Rescale(rescale,shift)中参数rescale和shift的含义?
MindSpore:【Resolve node failed】解析节点失败的问题
随机推荐
MySQL数据库之JDBC编程
MySQL sub-database sub-table
What is the difference between a cloud database and an on-premises database?
PostgreSQL 14.4如何安装使用
Linux下载安装mysql5.7版本教程最全详解
Is the iPhone really thirteen incense?The two generations of products are completely compared, perhaps the previous generation is more worth buying
Encapsulates a console file selector based on inquirer
HCIP --- 企业网的三层架构
MySQL database --- Addition, deletion, modification and query of MySQL tables (advanced)
阿里面试这些微服务还不会?那还是别去了,基本等通知
VS Code connects to SQL Server
MySQl数据库————DQL数据查询语言
MindSpore:【JupyterLab】按照新手教程训练时报错
centos7安装mysql8
golang日志库zerolog使用记录
【刷题篇】计算质数
VS Code 连接SQL Server
VBA 运行时错误‘-2147217900(80040e14):自动化(Automation)错误
Mac安装PHP开发环境
谷歌AlphaFold近日宣称预测出地球上几乎所有蛋白质结构