Java 可以将MyBatis和QueryDSL/jOOQ结合起来吗?

Java 可以将MyBatis和QueryDSL/jOOQ结合起来吗?,java,spring-data,mybatis,querydsl,jooq,Java,Spring Data,Mybatis,Querydsl,Jooq,MyBatis提供映射、本地缓存和即时登录 QueryDSL/jOOQ提供了SQL语句的编译时检查,结果是IDE自动完成 是否可以将它们组合起来? 换句话说,我想用QueryDSL或jOOQ创建一个查询,然后用MyBatis的一些粘合代码/适配器执行它 我已经检查的内容: 我曾考虑过使用QueryDSL生成SQL查询字符串,并在MyBatis中使用它的“@SelectProvider”注释,但这似乎是一条死胡同:MyBatis在其SQL字符串中需要“${xxx}”内容,但QueryDSL只根据

MyBatis提供映射、本地缓存和即时登录
QueryDSL/jOOQ提供了SQL语句的编译时检查,结果是IDE自动完成
是否可以将它们组合起来?

换句话说,我想用QueryDSL或jOOQ创建一个查询,然后用MyBatis的一些粘合代码/适配器执行它

我已经检查的内容:

  • 我曾考虑过使用QueryDSL生成SQL查询字符串,并在MyBatis中使用它的“@SelectProvider”注释,但这似乎是一条死胡同:MyBatis在其SQL字符串中需要“${xxx}”内容,但QueryDSL只根据实际的Java类型生成查询,因此它甚至不能用于ID
  • 作为QueryDSL/jOOQ的替代方案:非常糟糕的替代方案,因为它实际上生成了一个样板代码,您以后将不得不维护和扩展它
  • 作为QueryDSL/jOOQ的替代:比QueryDSL或jOOQ弱得多,例如,它不提供列名的编译时检查,它更麻烦,并且依赖于“@SelectProvider”,这使代码复杂化

我将从一个较高的层次进行回答-因此我不会深入探讨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();
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代码。下面:Java8映射代码

   .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(");");
       }
  );
这是的底部的示例,它显示了如何查询所有表的H2
信息\u模式
,并将结果映射到
创建表
语句中

结论: 许多API倾向于诱使您使用它们,因为它们的非核心“特性”,例如缓存或映射,它们实际上是SQL API的非核心特性。您将快速启动并运行简单的用例和pet/cat/dog或author/book应用程序,但您将遇到更复杂的应用程序。在您的用例中,类型安全的嵌入式SQL特性是您希望使用类似于jOOQ的东西的原因。您正在寻找的其他特性都不是使用MyBatis(其核心特性是外部SQL文件,这与嵌入SQL的jOOQ完全相反)的有力理由


所以,我给你的建议是:为你想要的每一个特性在你的堆栈中找到最好的工具,看看这些工具是否容易组合。我们在实现jOOQ时非常小心,以允许任何第三方应用程序非常容易地插入jOOQ(例如缓存、日志记录、映射),因为这些功能不是jOOQ的核心功能。

就像给Lukas一个非常完整的答案一样

从我的基准测试来看,MyBatis在映射上有一些严重的性能问题,Jooq是一条更好的性能曲线。这是地图上的Jooq


还将SimpleFlatMapper作为querydsl和spring数据的集成点。我不知道您可以将自己的映射与Jooq集成,并将其添加到待办事项列表中。

“我不知道您可以将自己的映射与Jooq集成,并将其添加到待办事项列表中。”-这将非常有趣!感谢这个基准测试#user3996996:good stuff,但对我来说,它缺乏对可以覆盖列名的注释的支持。我确实有一个用例,我的对象必须从CSV文件中读取并转储到DB中,但CSV中的列名与DB中的列名不匹配。在我看来,使用元信息(只生成一次)添加“映射上下文”的概念将大大增加使用SimpleFlatMapPerf的选项。现在处理不匹配名称的方法是使用别名。我一直在拖延时间。我仍然认为别名在这方面比注释更好。用元信息映射上下文是什么意思?用例是什么?我还进行了第一次尝试,尝试实现RecordFieldMapperFactory 9.15。有一些性能问题链接到转换过程,应该很快得到修复。我应该在周末完成这一切。MyBatis也支持类型安全DSL。您可以在XML或注释中使用它来代替旧的普通SQL。