首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

  • 24-12-05 23:25
  • 3932
  • 6984
juejin.cn

学会这款 全新技术的 Java 脚手架 ,从此面试不再怕!

Trump-mjga-logo.png

前言

JOOQ 就是 SQL,当你在使用 JOOQ 的时候,你就是在使用 SQL;一切你能够在 SQL 标准下实现的操作,几乎都能在 JOOQ 以相同的方式实现。记住这句话,你就理解了整个JOOQ 的设计思想。

Offset & Limit

SQL

sql
代码解读
复制代码
SELECT username FROM user LIMIT 2 OFFSET 1;

JOOQ

java
代码解读
复制代码
List users = dsl.select(USER.USERNAME).from(USER).limit(2).offset(1).fetchInto(User.class);

OrderBy

SQL

sql
代码解读
复制代码
SELECT username FROM user ORDER BY id DESC LIMIT 3 OFFSET 1;

JOOQ

java
代码解读
复制代码
List users = dsl.select(USER.USERNAME) .from(USER) .orderBy(USER.ID.desc()) .limit(3) .offset(1) .fetchInto(User.class);

上面的都很简单,下面是一个复杂点的例子。

Ties

user 表中有5行数据,其最后三行的 password 值是相同的;我们的需求是按 password asc 排序查询出前三条结果。

idusernamepassword
1testUserAa
2testUserBb
3testUserCc
4testUserDc
5testUserEc

这个需求满足起来很容易,使用传统的 order by & limit offset 就可以满足需求。

java
代码解读
复制代码
List users = dsl.select(USER.USERNAME) .from(USER) .orderBy(USER.PASSWORD.asc()) .limit(3) .offset(0) .fetchInto(User.class);

但问题是记录中有 3 行数据的 password 是相同的,在业务上 testUserC testUserD testUserE 实际拥有相同的优先级。如果我们不想遗漏这些相同优先级的数据应该怎么办呢?这就到了 withTies 上场的时候了:它会返回查询结果集中和最后一条数据优先级相同的数据(如果他们存在的话)

java
代码解读
复制代码
@Test @Sql( statements = { "INSERT INTO mjga.user (id, username, password) VALUES (1, 'testUserA','a')", "INSERT INTO mjga.user (id, username, password) VALUES (2, 'testUserB','b')", "INSERT INTO mjga.user (id, username, password) VALUES (3, 'testUserC','c')", "INSERT INTO mjga.user (id, username, password) VALUES (4, 'testUserD','c')", "INSERT INTO mjga.user (id, username, password) VALUES (5, 'testUserE','c')" }) void fetchAndTiesQuery() { List users = dsl.select(USER.USERNAME) .from(USER) .orderBy(USER.PASSWORD.asc()) .limit(3) .withTies() .offset(0) .fetchInto(User.class); assertThat(users.size()).isEqualTo(5); assertThat(users.get(0).getUsername()).isEqualTo("testUserA"); assertThat(users.get(4).getUsername()).isEqualTo("testUserE"); }

上例我们指定了 limit 3 offset 0 但却查询出了 5 条结果,原因就是 testUserD 和 testUserE 和 testUserC 形成了绑定(withTies)关系。

这是什么 JOOQ 的神奇魔法吗?不是,这是 SQL 的标准功能,但是 Mysql 却不支持它;而诸如 mybatis 之类的库又没有在应用层面模拟这个行为,所以你没有用过。

Window Function

再来个更高级点的例子。很多时候分页查询都需要我们额外统计一个「总数」。无论你用什么库或插件,其原理都是通过再运行一个 SELECT COUNT(*) AS total_count 之类的聚合查询来满足这个需求,这会导致你和 DB 多交互一次。

所以能不能只和 DB 交互一次,就同时获取查询结果集和统计总数呢?当然可以,窗口函数可以把结果集视为一个窗口,为这个结果集的每一行计算一个聚合值,而不改变结果集的行数。

SQL

sql
代码解读
复制代码
SELECT *, COUNT(*) OVER () AS total_user FROM user ORDER BY id ASC LIMIT 4 OFFSET 0;

JOOQ

不要被 Result 吓到,这就是一个自定义的 List 结构。

java
代码解读
复制代码
Result resultWithWindow = dsl.select(asterisk(), DSL.count().over().as("total_user")) .from(USER) .orderBy(USER.ID.asc()) .limit(4) .offset(0) .fetch();

Result

idusernametotal_user
1Alice5
2Bob5
3Charlie5
4David5

这是什么 JOOQ 的神奇魔法吗?不是,这是 SQL 的标准功能,但是 Mysql 8 以下的版本却不支持它;如果你长期使用 mybatis-plus 等相关插件,这也会导致你错过窗口函数,因为 它们都没有提供对这些常见 SQL 标准的支持。

最后

使用 JOOQ,通过其对 SQL 标准的全面支持,外加将 SQL 运行时异常提前到编译时的 「类型安全的 QueryDSL 语法」, 将会帮你重新拿起 SQL 这个超级武器横扫一切需求。

以上所有代码都可以在 Github仓库 中找到。如果你觉得教程有帮助,求顺手给一个 Star,万分感谢。

注:本文转载自juejin.cn的Chuck1sn的文章"https://juejin.cn/post/7444562741468217353"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

103
后端
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top