jooq_使用jOOQ DSL

jooq

本文是我们学院课程“ jOOQ –类型安全数据库查询”的一部分 。

在SQL和特定关系数据库很重要的Java应用程序中,jOOQ是一个不错的选择。 当JPA / Hibernate抽象过多而JDBC过于抽象时,这是一种替代方法。 它显示了一种现代的领域特定语言如何可以极大地提高开发人员的生产率,从而将SQL内部化为Java。

在本课程中,我们将看到如何使用jOOQ有效地查询数据库。 在这里查看 !

目录

1. jOOQ DSL的思想 2.运行第一个查询 3.其他语句类型
3.1。 插 3.2。 更新 3.4。 删除
4.谓词
4.1。 日常谓词 4.2。 更高级的谓词 4.3。 比较谓词
5.列表达式
5.1。 在SQL中: 5.2。 使用jOOQ ::
6.有关jOOQ DSL的更多信息

也可以从org.jooq.academy.section1包中获得本节中显示的示例 。

1. jOOQ DSL的思想

jOOQ是一种DSL(领域特定语言),它模仿Java API中的标准和特定于供应商SQL语法。 该API背后的思想很容易理解:

  • 作为内部 DSL,Java编译器可以验证您SQL查询的语法正确性(例如,SQL关键字的正确顺序)
  • 将表和列作为生成的Java对象,编译器还可以验证元数据的正确性(例如,正确的列名和类型)

换句话说,当您想要表达这样SQL查询时:

SELECT   author.first_name, author.last_name
FROM     author
ORDER BY author.id

…然后您可以立即使用jOOQ编写相同的查询

select  (AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
.from   (AUTHOR)
.orderBy(AUTHOR.ID);

它是如何工作的,jOOQ和您的Java编译器如何知道“ select ”的含义,或“ AUTHOR.FIRST_NAME ”的含义?

2.运行第一个查询

在上面的示例中,进行了两个简单的假设,并将在整个过程中进行以下假设:

  • 每当您看到独立SQL关键字时,它就可能是从org.jooq.impl.DSL静态导入的。
  • 每当您看到独立的表引用时,都可能是从生成的Tables类中静态导入的

换句话说,理想情况下,在每个使用jOOQ的类中,只需添加以下两个import语句:

import static org.jooq.example.db.h2.Tables.*;
import static org.jooq.impl.DSL.*;

这将使上面的代码编译。 但是,这样的Select语句并没有做什么用,它只是放在那儿,可以打印到控制台上:

System.out.println(select  (AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME).from   (AUTHOR).orderBy(AUTHOR.ID)
);

上面将打印:

select "PUBLIC"."AUTHOR"."FIRST_NAME", "PUBLIC"."AUTHOR"."LAST_NAME" from "PUBLIC"."AUTHOR" order by "PUBLIC"."AUTHOR"."ID" asc

执行这样的查询非常简单。 我们需要做的就是为其提供JDBC Connection ,然后在其上调用fetch()

DSL.using(connection).select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME).from(AUTHOR).orderBy(AUTHOR.ID).fetch();

注意,当然,您也可以将对象分配给局部变量,或者使用Spring或您喜欢的配置框架来配置它,而不是一直重复DSL.using(...)

DSLContext dsl = DSL.using(connection);dsl.select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME).from(AUTHOR).orderBy(AUTHOR.ID).fetch();

jOOQ将在内部创建一个新的JDBC PreparedStatement ,执行它,使用JDBC ResultSet ,并急切地关闭它创建的所有资源。 结果对象是Result ,它也实现了一个非常有用的toString()方法:

System.out.println(dsl.select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME).from(AUTHOR).orderBy(AUTHOR.ID).fetch()
);

以上将产生:

+----------+---------+
|FIRST_NAME|LAST_NAME|
+----------+---------+
|George    |Orwell   |
|Paulo     |Coelho   |
+----------+---------+

3.其他语句类型

jOOQ本机支持每个DML SQL语句(以及一些DDL SQL语句),包括SELECTUPDATEINSERTDELETEMERGE 。 如果要创建,更新,删除新的AUTHOR记录,可以编写以下SQL语句:

dsl.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME).values(3, "Alfred", "Hitchcock").execute();

请注意,我们现在将调用execute()而不是fetch() execute() ,它返回受影响的行数。

上面查询的一个有趣的方面是jOOQ使用了大量Java泛型来确保查询中的类型安全。 例如,以下两个查询将产生编译错误:

dsl.insertInto(AUTHOR, AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME).values(3, "Alfred")
// ^^^^^^^ values() expects three arguments (for ID, FIRST_NAME, LAST_NAME),
//                  but only two were provided!.execute()

这非常强大,因为您将永远不会忘记根据INTO子句的要求向VALUES子句添加相等数量的值。 这也扩展到类型不匹配。 如果您决定对INTO子句中的列进行重新排序,但忘了改写VALUES子句,则您的Java编译器可能会再次抱怨。 以下内容无法编译:

dsl.insertInto(AUTHOR, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, AUTHOR.ID).values(4, "Alfred", "Hitchcock")
// ^^^^^^^ values() expects arguments of type (String, String, Integer),but (Integer, String, String) was provided!.execute()

更新

UPDATE语句与前面的语句一样简单:

dsl.update(AUTHOR).set(AUTHOR.DATE_OF_BIRTH, Date.valueOf("1899-08-13")).where(AUTHOR.ID.eq(3)).execute()

到目前为止,选择ID = 3的作者将产生完整的AUTHOR记录:

dsl.select().from(AUTHOR).where(AUTHOR.ID.eq(3)).fetch()

……屈服

+----+----------+---------+-------------+
|  ID|FIRST_NAME|LAST_NAME|DATE_OF_BIRTH|
+----+----------+---------+-------------+
|   3|Alfred    |Hitchcock|1899-08-13   |
+----+----------+---------+-------------+

删除

最后但并非最不重要的一点是, DELETE语句如下:

dsl.delete(AUTHOR).where(AUTHOR.ID.eq(3)).execute()

4.谓词

谓词是SQL(尤其是动态SQL)的重要方面。 SQL知道各种谓词,例如:

日常谓词

  • 比较谓词
  • NULL谓词
  • 像谓词
  • IN谓词
  • 存在谓词

更高级的谓词

  • 量化比较谓词
  • DISTINCT谓词
  • 谓词之间
  • 重叠谓词

同样,在SQL中,可以使用ANDOR轻松组合谓词。 jOOQ以一种流利的方式直接在列类型上反映了所有这些谓词。 最好用示例说明:

比较谓词

// A filtering predicate
AUTHOR.ID.eq(3);// A join predicate
AUTHOR.ID.eq(BOOK.AUTHOR_ID);

这些谓词中的大多数也是安全类型,例如,您不能将数字与字符串进行比较。

AUTHOR.ID.eq("abc");
//        ^^ Compilation error. An expression of type Integer is expected
//           (or Field<Integer>, or Select<? extends Record1<Integer>>)

IN谓词是类型安全的一个有趣案例,它需要一个值列表或一个在IN关键字右侧仅包含一列的子查询:

// IN list
AUTHOR.ID.in(1, 2, 3);// IN with subquery
AUTHOR.ID.in(select(BOOK.AUTHOR_ID).from(BOOK))

第二个示例在AUTHORBOOK表之间执行半AUTHOR ,仅返回至少写过一本书的作者。 由于使用Java泛型,因此以下查询将无法编译:

// IN list with wrong types
AUTHOR.ID.in("a", "b", "c");
//           ^^^^^^^^^^^^^ This in() method expects an Integer... argument// IN with subquery returning wrong type
AUTHOR.ID.in(select(BOOK.TITLE).from(BOOK))
//           ^^^^^^^^^^^^^^^^^^ This in() method expects a   Select<? extends Record1<Integer>>
//

此外,Java编译器将拒绝以下(无效)语句:

AUTHOR.ID.in(select(BOOK.AUTHOR_ID, BOOK.TITLE).from(BOOK))
//        ^^ This in() method expects a   Select<? extends Record1<Integer>>,
//           but instead, an incompatible Select<Record2<Integer, String>> was provided

5.列表达式

在SQL中,可以通过对列表达式应用函数或操作来创建新型的列表达式。 例如,您可以串联作者的名字和姓氏:

在SQL中:

SELECT   author.first_name || ' ' || author.last_name
FROM     author
ORDER BY author.id

使用jOOQ ::

dsl.select(concat(AUTHOR.FIRST_NAME, val(" "), AUTHOR.LAST_NAME)).from(AUTHOR).orderBy(AUTHOR.ID).fetch()

请记住,我们是从DSL静态导入所有内容,包括DSL.concat()DSL.val()

dsl.select(AUTHOR.FIRST_NAME.concat(" ").concat(AUTHOR.LAST_NAME)).from(AUTHOR).orderBy(AUTHOR.ID).fetch()

当然,由于Java不允许运算符重载(或符号方法名),因此我们必须处理常规方法名,在这种情况下,应使用concat 。 通常是由您决定要对功能使用前缀表示法,还是对运算符使用前缀表示法。

6.有关jOOQ DSL的更多信息

jOOQ DSL具有非常丰富的功能。 列出本课程中的所有功能将重复参考手册。 请考虑手册中有关SQL构建的部分,以了解有关jOOQ DSL的更多信息。

翻译自: https://www.javacodegeeks.com/2015/09/work-with-the-jooq-dsl.html

jooq

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/337354.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

什么镜头最适合拍风景_为什么您的风景摄影套件中应始终装有远摄镜头

当您考虑风景摄影镜头时&#xff0c;许多摄影师只考虑广角镜头。14-24mm f / 2.8或24-70mm f / 2.8等经典镜头是用于风景的流行光学元件。它们是绝佳的选择但是&#xff0c;也值得在风景摄影套件中使用长焦镜头。为什么要使用长镜头进行风景摄影&#xff1f;您在网上或浏览Inst…

C++ STL详解(3)

点击蓝字关注我们简介set 是 关联容器 的一种&#xff0c;是排序好的集合&#xff08;元素已经进行了排序&#xff09;。set 和 multiset 类似&#xff0c;它和 multiset 的差别在于 set 中不能有重复的元素。multiset 的成员函数 set 中也都有。使用 set 必须包含 #include<…

【lua学习】8.协程

1 数据结构和宏1.1 协程的状态码1.2 协程的执行状态码1.3 lua_State 协程结构体2 C API2.1 lua_newthread 新建一个协程&#xff0c;压栈&#xff0c;返回这个新协程2.2 luaE_freethread 释放一个协程L12.3 lua_status 获取协程的错误码2.4 lua_resume 唤醒一个协程&#xff0c…

检测到基于堆栈的缓冲区溢出_检测到堆栈粉碎

检测到基于堆栈的缓冲区溢出我敢打赌&#xff0c;每个Java开发人员在他们的职业生涯开始时第一次遇到Java代码的本机方法时都会感到惊讶。 我还可以肯定&#xff0c;多年来随着了解JVM如何通过JNI处理对本机实现的调用而使惊奇消失了。 这篇文章是关于本机方法的最新经验。 更…

探讨 C++ 虚函数 virtual

点击蓝字关注我们来源于网络&#xff0c;侵删有无虚函数的对比C 中的虚函数用于解决动态多态问题&#xff0c;虚函数的作用是允许在派生类中重新定义与积累同名的函数&#xff0c;并且可以通过基类指针或引用来访问基类和派生类中的同名函数。首先写两个简单的类&#xff0c;类…

python上一行的代码打错了怎么办_写Python代码过程中碰到各种错误异常要怎么样去处理?...

错误异常即便Python程序的语法是正确的&#xff0c;在程序运行的过程中&#xff0c;也可能发生错误。运行期检测到的错误被称为异常。如果发生了错误&#xff0c;可以事先约定返回一个错误代码&#xff0c;这样&#xff0c;就可以知道是否有错&#xff0c;以及出错的原因。所以…

双重for_测试双重图案

双重for前段时间&#xff0c;我写了一篇有关使用Test Double的后果的文章&#xff0c;但是与Test Double Patterns无关&#xff0c;仅是一个简单的清单。 今天&#xff0c;我想对其进行更改&#xff0c;并解释这些模式之间的差异。 正如我在提到的文章中写道&#xff1a; Tes…

C++ STL详解(4)

点击蓝字关注我们来源于网络&#xff0c;侵删unordered_set / unordered_multiset这两个容器的方法与上一篇 C STL简介&#xff08;3&#xff09; 提到的 set / multiset 基本一样。但是要注意的是&#xff1a;这两个是无序的&#xff0c;基于哈希表实现的&#xff0c;增删改查…

js压缩图片_Web 性能优化: 图片优化让网站大小减少 62%

图像是web上提供的最基本的内容类型之一。他们说一张图片胜过千言万语。但是如果你不小心的话&#xff0c;图片大小有时高达几十兆。因此&#xff0c;虽然网络图像需要清晰明快&#xff0c;但它们尺寸可以缩小压缩的&#xff0c;使用加载时间保持在可接受的水平。在我的网站上&…

春春幼儿园堆积木大赛_春云边车

春春幼儿园堆积木大赛我有一个部署到基于NetflixOSS的云的应用程序&#xff0c;该应用程序具有以下结构&#xff1a; 本质上是一种将信息持久保存到Cassandra集群的服务。 所有应用程序都已注册到Eureka –因此&#xff0c;在本例中&#xff0c;该服务以及Cassandra节点都已在…

C++ 标准输入的行加速

点击蓝字关注我们来源于网络&#xff0c;侵删一、前言c/c 的标准输入函数&#xff0c;在输入一行数据&#xff0c;当数据量比较大的时候&#xff0c; cin 的效率是非常低的&#xff0c;为了加快读入的效率&#xff0c;可以改用 scanf&#xff0c;当然&#xff0c;还有一种利用 …

如何用python 开发web_如何用python开发web

Django是一个Web框架——一套用于帮助开发交互式网站的工具。Django能够响应网页请求&#xff0c;还能让你更轻松地读写数据库、管理用户等。建立Django项目建立Django项目首先需要确保我们按照好了Django&#xff0c;我们在Pycharm中打开虚拟环境的终端&#xff0c;然后输入&a…

redis安装_Redis安装

redis安装本文是我们学院课程的一部分&#xff0c;标题为Redis NoSQL键值存储 。 这是Redis的速成课程。 您将学习如何安装Redis和启动服务器。 此外&#xff0c;您还会在Redis命令行上乱七八糟。 接下来是更高级的主题&#xff0c;例如复制&#xff0c;分片和集群&#xff0c…

C++ 自动锁

点击蓝字关注我们来源于网络&#xff0c;侵删一、锁1.锁 是 多线程编程 中一个很常用的概念&#xff0c;这里不多加介绍其原理&#xff0c;有兴趣可以参考 临界区 进行更多的了解&#xff1b;2.锁 一般会提供三个接口&#xff1a;加锁&#xff08;Lock&#xff09;、解锁&#…

python快速编程入门黑马程序员pdf_Python快速编程入门 传智播客 黑马程序员 python编程从入门到实践基础视频教程核心编程爬虫数据分析程序设计机器学习简明书籍...

传智播客就业系列从入门到就业JAVA从入门到精通 套装5本&#xffe5;148javaweb从入门到精通套装3本&#xffe5;88Python从入门到实践套装8本&#xffe5;280php教程全套7本&#xffe5;227PHP套装5本&#xffe5;165php全套5本&#xffe5;149android开发从入门到精通 共3本&…

叉叉框架_叉/连接框架

叉叉框架本文是我们名为Java Concurrency Essentials的学院课程的一部分。 在本课程中&#xff0c;您将深入探讨并发的魔力。 将向您介绍并发和并发代码的基础知识&#xff0c;并学习诸如原子性&#xff0c;同步和线程安全性的概念。 在这里查看 &#xff01; 目录 1.简介 2…

C++ 浮点数精度判定

点击蓝字关注我们来源于网络&#xff0c;侵删一、引例看下下面这段代码&#xff0c;会输出什么结果呢&#xff1f;double x 0;for (int i 0; i < 10; i) {x 0.1;}printf("%d\n", x 1);输出如下&#xff1a;0引起这种反差的原因就是浮点误差&#xff0c;浮点数…

字节流和字符流哪个不刷新_不喜欢节流吗?

字节流和字符流哪个不刷新您别无选择–底层系统&#xff08;此处的JVM将为您完成选择&#xff09;。 我仍然记得2013年夏天&#xff0c;当时我正在运行一个项目&#xff0c;整个应用程序中只有1个URL使服务器瘫痪。 问题很简单-机器人决定以很高的速率索引我们的网站&#xff…

C/C++动态内存管理—(new与malloc)

点击蓝字关注我们来源于网络&#xff0c;侵删1.C/C内存分布虚拟地址空间分布&#xff1a;由C/C编译的程序占用的内存分为以下几个部分&#xff1a;栈区&#xff08;stack&#xff09;— 由编译器自动分配释放 &#xff0c;存放为运行函数而分配的局部变量、函数参数、返回数据、…

python实现简单小游戏_python实现简单井字棋小游戏

#Tic-Tac-Toe 井字棋游戏#全局常量X"X"O"O"EMPTY" "#询问是否继续def ask_yes_no(question):responseNone;while response not in("y","n"):responseinput(question).lower()return response#输入位置数字def ask_number(qu…