当前位置: 首页 > 面试题库 >

可以将MyBatis和QueryDSL / jOOQ结合使用吗?

华君浩
2023-03-14
问题内容

MyBatis提供了映射,本地缓存和开箱即用的功能。
QueryDSL / jOOQ提供了SQL语句的编译时检查和IDE自动完成的结果。
是否可以将它们组合在一起?

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

我已经检查过的内容:

  • 我考虑过使用QueryDSL生成SQL查询字符串,并在MyBatis中使用它的’@SelectProvider’注释,但这似乎是一个死胡同:MyBatis在其SQL字符串中需要“ $ {xxx}”的内容,但是QueryDSL仅生成查询基于实际的Java类型,因此即使是ID也无法使用。
  • MyBatis Generator作为QueryDSL / jOOQ的替代品:替代品相当差,因为它实际上生成了样板代码,您稍后必须维护和扩展
  • MyBatis SQL Builder作为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();

实际上,许多人使用此技术来通过Spring JDBC而不是jOOQ运行查询。之所以这么做,主要是因为他们已经广泛使用了Spring
JDBC,并且他们不想在堆栈上执行两种查询。

但是你为什么要:

您添加到堆栈中的每个API都会增加堆栈行为的复杂性和一组规则。另一方面,您希望通过这些API实现一组功能。让我们确定这些功能:

  1. 输入安全的嵌入式SQL
  2. 快取
  3. 记录中
  4. 将非规范化的SQL结果映射到您的域

1)输入安全的嵌入式SQL

这是显而易见的。您可能不想为此使用MyBatis。该实现(如您所发现的)更多是概念证明。所以您来到了jOOQ的选择

2)缓存

我个人认为这是您太快得出结论的事情。MyBatis有很多东西非常简单的实现,但在高速缓存的情况下,我敢肯定你想实现一个更一般的缓存策略,例如使用新的JSR-107缓存支持,像春天的一个简单因为缓存并不是真的与SQL紧密耦合。

3)记录

例如,jOOQ实现了易于挂入日志记录挂钩的操作,但是您也可以使用JDBC跟踪日志记录库或JDBC驱动程序的功能在JDBC级别上使用日志记录

4)映射

我说过的缓存同样适用于这里。MyBatis为您的映射算法提供了一个简单的默认实现,当您转到更复杂的映射方案时,这可能很快就不够用。jOOQ,btw也是如此,后者还实现了POJO的默认映射,您可以覆盖所需的任何方式。但是,就像缓存一样,映射实际上并不是应该在SQL级别上解决的问题。您将在其中找到用于映射本身的更好的工具-例如Model
Mapper(具有内置的jOOQ支持,btw)。或者,如果您处于Java
8环境中,则可以使用常规的函数式编程技术来映射内容,例如:

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(");");
       }
  );

这是本文底部的示例,它显示了如何在H2中查询INFORMATION_SCHEMA所有表,以及如何将结果映射到CREATE TABLE语句中

结论:

由于它们的非核心“功能”(例如缓存或映射),它们实际上是SQL API的非核心功能,因此许多API往往会吸引您使用它们。使用简单的用例以及pet / cat
/ dog或author /
book应用程序,您将快速启动并运行,但是您将被更复杂的应用程序所困扰。在您的用例中,类型安全的嵌入式SQL功能是您想使用jOOQ之类的原因。您正在寻找的其他功能并不是使用MyBatis的令人信服的理由(其核心功能是外部SQL文件,与嵌入SQL的jOOQ完全相反)。

因此,我对您的建议是:为堆栈中想要的每个功能确定最佳工具,并查看这些工具是否易于组合。在实现jOOQ时,我们非常谨慎,以允许任何第三方应用程序很容易地插入jOOQ(例如,缓存,日志记录,映射),因为这些功能不是jOOQ的核心功能。



 类似资料:
  • 我已经检查的内容: 我曾考虑用QueryDSL生成SQL查询字符串,并在MyBatis中使用它的'@SelectProvider'注释,但这似乎是一个死胡同:MyBatis在它的SQL字符串中需要“${xxx}”的东西,但QueryDSL只生成基于实际Java类型的查询,所以它甚至对ID也不起作用。 作为querydsl/jooq的替代方案的mybatis生成器:相当糟糕的替代方案,因为它实际上生

  • 如果一个前端代码,使用webpack可以 设置路径别名 比如src可以用@代替 使用import 引用 兼容各种文件名 .js .jsx .ts等等 而后端node express的项目就没听说有人用webpack,我知道,以上的东西可以手动在node express项目中进行设置,但是如果有一个类似webpack的工具那就更好了。 请问有类似的工具吗,不想要一个一个找解决方案进行配置啊。就仅仅一

  • 问题内容: 我正在使用Phonegap + React.js和Socket.io开发一个应用程序。但是,随后React-Native发行了,其原生感觉很棒。 我试图让socket.io-client与React Native一起工作,但是不幸的是没有成功。我做了一些研究,发现与此问题中描述的错误完全相同:https : //github.com/facebook/react- native/iss

  • 我有两个查询,它们查看不同的数据库表,并从每个表中的JSONB列中查找格式为[“tag1”、“tag2”、“tag3”]等的项。查询的目的是填充预测性下拉列表,即如果列表包含“dog”且用户类型为“d”,则应返回“dog”。这些查询中的每一个都单独工作,我可以很容易地将它们组合成一个JOOQ查询?

  • 我正在编写一些从第三方库扩展类的JUnit测试。超级类扩展了,所以根据定义,我的子类也扩展了。 在我的子类中,我用前缀编写测试方法,然后执行这些方法。 但是,出于许多原因,我们希望转移到JUnit4(其中一个原因是,我们不希望必须在测试方法前缀) 我尝试过使用JUnit4注释简单地编写新测试,但这些方法没有得到执行。 例如: 不扩展第三方测试类不是一个选项。(值得注意的是,Spring的又扩展了其