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

Abh*_*shi 2 orm entity-framework hibernate jooq

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

Luk*_*der 7

像hibernate和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
Run Code Online (Sandbox Code Playgroud)

如果是这样,那么在我们自己的框架中支持这一点的最佳方法是什么?

你需要:

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

但!

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

上面的LIMIT仿真是jOOQ中更简单的示例之一。这里还有很多可以帮助您决定不做自己的事情的答案,而且答案仍然仅仅是jOOQ在幕后所做的事情的表面。