SQL方言实际上如何在诸如hibernate和JOOQ之类的框架中内部工作

时间:2019-04-29 19:12:47

标签: entity-framework hibernate orm jooq

正如我们所见,获得数据源之后。我们需要根据我们使用的数据库配置SQL方言。选择特定的方言之后,将如何使用它来进行特定于DB的SQL查询。诸如hibernate和JOOQ之类的框架是否根据所选的方言以字符串形式构造SQL查询?如果是这样,那么在我们自己的框架中支持这一点的最佳方法是什么?

1 个答案:

答案 0 :(得分:7)

  

冬眠和JOOQ之类的框架是否根据所选的方言以字符串形式构造SQL查询

是的。在jOOQ中,有一个内部StringBuilder可以从表达式树中收集SQL片段,这些片段是专门为目标SQL方言生成的。您可以在https://www.jooq.org/translate这个网站上看到它的运作方式。尝试翻译例如以下输入:SELECT * FROM t LIMIT 1(这可能对应于您的jOOQ API使用情况ctx.selectFrom(T).limit(1)。它翻译为:

-- Oracle 12c and more
SELECT * FROM t FETCH NEXT 1 ROWS ONLY

-- Oracle 11g and less
SELECT *
FROM (
  SELECT x.*, rownum rn
  FROM (SELECT * FROM t) x
  WHERE rownum <= 1
)
WHERE rn > 0
  

如果是这样,那将是在我们自己的框架中支持此功能的最佳方法?

您需要:

  1. SQL查询的表达式树表示形式。
  2. (可选)您可以解析一个字符串以构建此表达式树,例如jOOQ's parser(如果您想支持实际的SQL),或者可以像Hibernate那样使用HQL / JPQL来拥有自己的语言抽象
  3. 使用访问者之类的东西遍历该表达式树以收集SQL字符串并绑定变量。

但是!

当您购买现成的产品(如jOOQ)或在较小程度上可以做同样工作的Hibernate时,请不要自行构建。构建这样的通用SQL抽象确实非常困难,并且除非您想实际销售这样的产品(您可能没有提出问题),否则花时间来构建此产品根本不值得。

上面的LIMIT仿真是jOOQ中较为简单的示例之一。 Here's a lot more to help you decide against rolling your own,答案仍然是 ,只是摸清了jOOQ在幕后所做的事情。