我将从高层次回答——所以我不会深入研究 QueryDSL 和 jOOQ 之间的实际区别,在讨论的这一点上,它们“只是”都在 Java 中提供了类型安全的嵌入式 SQL。不过,我会从 jOOQ 的角度给出答案,因为我知道那个 API 要好得多。
免责声明:我是从为 jOOQ 背后的公司工作的人的角度给出这个答案的。
是的,你可以:
是的,您可以将 jOOQ 与 MyBatis 结合使用。例如,您可以像这样从 jOOQ 查询中提取查询字符串:
Select<?> query =
DSL.using(configuration)
.select(TABLE.A, TABLE.B)
.from(TABLE)
.where(TABLE.C.eq(1));
String sql = query.getSQL();
List<Object> bindvalues = query.getBindValues();
许多人实际上使用这种技术然后使用 Spring JDBC 而不是 jOOQ 运行查询。他们这样做的主要原因是他们已经广泛使用 Spring JDBC,并且他们不希望在他们的堆栈上执行两种类型的查询。
但你为什么会:
您添加到堆栈中的每个 API 也会增加堆栈行为方式的复杂性和一组规则。另一方面,您有一组想要通过这些 API 实现的功能。让我们确定这些特征:
- 类型安全的嵌入式 SQL
- 缓存
- 日志记录
- 将非规范化 SQL 结果映射到您的域
1) 类型安全的嵌入式 SQL
这很简单。你可能不想为此使用 MyBatis。该实现(如您所见)更像是概念证明。所以你来到了jOOQ的选择
2) 缓存
我个人认为您过早下结论。 MyBatis 有很多非常简单的实现,但是在缓存的情况下,我很确定你想要实现更通用的缓存策略,例如使用新的 JSR-107 caching support, like the one from Spring 仅仅是因为缓存与 SQL 的耦合并不是那么紧密。
3) 日志记录
jOOQ for instance implements easy to hook into logging hooks,但您也可以在 JDBC 级别使用日志记录 using a JDBC trace logging library or your JDBC drivers' capabilities
4) 映射
我所说的缓存在这里也是如此。 MyBatis 为您的映射算法提供了一个简单的默认实现,当您转向更复杂的映射场景时,这可能很快就不够了。 jOOQ 也是如此,顺便说一句,它也实现了default mapping for POJOs、which you can override any way you want。但就像缓存一样,映射并不是真正应该在 SQL 级别上解决的问题。您会发现更好的工具用于映射本身 - 例如Model Mapper(有built-in jOOQ support,顺便说一句)。或者,如果您在 Java 8 环境中,您可以使用 regular functional programming techniques to map stuff,例如像这样:
DSL.using(configuration)
.select(
COLUMNS.TABLE_NAME,
COLUMNS.COLUMN_NAME,
COLUMNS.TYPE_NAME
)
.from(COLUMNS)
.orderBy(
COLUMNS.TABLE_CATALOG,
COLUMNS.TABLE_SCHEMA,
COLUMNS.TABLE_NAME,
COLUMNS.ORDINAL_POSITION
)
.fetch()
上图:jOOQ 代码。下图:Java 8 映射代码
.stream()
.collect(groupingBy(
r -> r.getValue(COLUMNS.TABLE_NAME),
LinkedHashMap::new,
mapping(
r -> new Column(
r.getValue(COLUMNS.COLUMN_NAME),
r.getValue(COLUMNS.TYPE_NAME)
),
toList()
)
))
.forEach(
(table, columns) -> {
System.out.println(
"CREATE TABLE " + table + " (");
System.out.println(
columns.stream()
.map(col -> " " + col.name +
" " + col.type)
.collect(Collectors.joining(",\n"))
);
System.out.println(");");
}
);
这是this article底部的示例,它显示了如何查询H2 INFORMATION_SCHEMA的所有表,并将结果映射到CREATE TABLE语句
结论:
许多 API 倾向于诱使您使用它们,因为它们的非核心“功能”,例如缓存或映射,这些对于 SQL API 来说确实是非核心功能。您将使用简单的用例和宠物/猫/狗或作者/书籍应用程序快速启动并运行,但您会被更复杂的应用程序卡住。在您的用例中,类型安全的嵌入式 SQL 功能是您想要使用类似 jOOQ 的原因。您正在寻找的其他功能都不是使用 MyBatis 的非常有说服力的理由(其核心功能是外部 SQL 文件,这与嵌入 SQL 的 jOOQ 完全相反)。
因此,我对您的建议是:为您希望堆栈中的每个功能确定最佳工具,并查看这些工具是否易于组合。我们在实现 jOOQ 时非常小心,允许任何第三方应用程序非常容易地插入到 jOOQ 中(例如缓存、日志记录、映射),因为这些功能不是 jOOQ 的核心功能。