您不必使用 jOOQ 的代码生成器来利用 jOOQ 中的大多数功能。手册的介绍部分指出,jOOQ 可以轻松地用作 SQL 构建器,而无需代码生成器提供的额外类型静态安全:
https://www.jooq.org/doc/latest/manual/getting-started/use-cases/jooq-as-a-standalone-sql-builder
代码生成提供的类型安全
代码生成器本质上提供了两种类型的安全元素:
- 对象的名称被硬连接到类名称(表、模式、序列、数据类型、过程等)和属性名称(列、类型属性、过程参数)中。
- 属性类型(列、属性、参数)被硬连接到通用属性定义中。
这些东西肯定有助于开发您的应用程序
jOOQ API 提供的类型安全
...但请注意,代码生成器只是对您的模式的静态快照进行逆向工程。它是类型安全的,因为整个 jOOQ API 都允许这种类型安全。例如,Field<T> 类型有一个泛型类型<T>,它也可以在没有代码生成器的情况下使用,例如通过使用plain SQL APIs:
Field<String> firstName = field(name("USER", "FIRST_NAME"), SQLDataType.VARCHAR(50));
上述 API 用法 (DSL.field(Name, DataType)) 的作用与代码生成器的作用大致相同。它创建一个列引用,并附有列类型信息。您可以像代码生成器生成的列一样使用它:
DSL.using(configuration)
.select(firstName)
.from(name("USER"))
.where(firstName.like("A%")) // Compiles
.and(firstName.eq(1)) // Doesn't compile: firstName must be compared to String
.join(name("ADDRESS")) // Doesn't compile: the SQL syntax is wrong
.fetch();
如您所见,与使用代码生成器相比,唯一改变的是表/列引用。
动态 SQL
但这意味着,如果没有代码生成器,jOOQ 对您来说更加强大。您仍然可以非常轻松地创建动态 SQL 语句。例如:
// Construct your SQL query elements dynamically, and type safely
Condition condition = hasFirstNameFilter()
? firstName.like("A%")
: DSL.trueCondition();
DSL.using(configuration)
.select(firstName)
.from(name("USER"))
.where(condition) // Use dynamically constructed element here
.fetch();
您也可以通过“功能性方式”执行此操作:
DSL.using(configuration)
.select(firstName)
.from(name("USER"))
.where(condition()) // Call a function to create the condition here
.fetch();
甚至更好
public static Select<Record1<String>> firstNames(
Function<? super Field<String>, ? extends Condition> condition
) {
return
DSL.using(configuration)
.select(firstName)
.from(name("USER"))
.where(condition.apply(firstName)); // Lazy evaluate the predicate here
}
// Use it like this:
firstNames(col -> col.like("A%")).fetch();
或者甚至更好,把上面的函数做成高阶函数:
public static Function<
? super Function<? super Field<String>, ? extends Condition>,
? extends Select<Record1<String>>
> firstNames() {
// Lazy construct query here
return f -> DSL.using(configuration)
.select(firstName)
.from(name("USER"))
.where(f.apply(firstName)); // Lazy evaluate the predicate here
}
// Use it like this:
firstNames().apply(col -> col.like("A%")).fetch();
更多细节在这里:
https://www.jooq.org/doc/latest/manual/sql-building/dynamic-sql
结论:
如您所见,虽然代码生成器确实为静态模式添加了很多价值,但 jOOQ API 中并没有真正静态的东西。 jOOQ 是一个用于动态 SQL 查询构造的 API,恰好也适用于静态查询。