银川住房和城乡建设局网站,网站个人中心wordpress,2022世界500强企业排名,图书建设网站jooqjOOQ是内部特定于域的语言#xff08;DSL#xff09; #xff0c;它以Java#xff08;宿主语言#xff09;建模SQL语言#xff08;外部DSL#xff09;。 这篇热门文章描述了jOOQ API的主要机制#xff1a; Java Fluent API设计器速成课程 。 任何人都可以根据该文… jooq jOOQ是内部特定于域的语言DSL 它以Java宿主语言建模SQL语言外部DSL。 这篇热门文章描述了jOOQ API的主要机制 Java Fluent API设计器速成课程 。 任何人都可以根据该文章中的规则以Java或大多数其他宿主语言实现内部DSL。 SQL语言功能示例BOOLEANs 但是关于SQL语言的BOOLEAN是BOOLEAN类型该类型在SQL1999以后才引入到该语言中。 当然没有布尔值您可以通过1和0建模TRUE和FALSE值并使用CASE将谓词转换为值 CASE WHEN A B THEN 1 ELSE 0 END 但是有了真正的BOOLEAN支持您可以进行出色的查询例如针对Sakila数据库运行的以下PostgreSQL查询 SELECTf.title, string_agg(a.first_name, , ) AS actors
FROM film AS f
JOIN film_actor AS fa USING (film_id)
JOIN actor AS a USING (actor_id)
GROUP BY film_id
HAVING every(a.first_name LIKE %A%) 以上收益 TITLE ACTORS
-----------------------------------------------------
AMISTAD MIDSUMMER CARY, DARYL, SCARLETT, SALMA
ANNIE IDENTITY CATE, ADAM, GRETA
ANTHEM LUKE MILLA, OPRAH
ARSENIC INDEPENDENCE RITA, CUBA, OPRAH
BIRD INDEPENDENCE FAY, JAYNE
... 换句话说我们正在寻找所有电影其中在电影中扮演过的所有演员的名字中都包含字母“ A”。 这是通过布尔表达式/谓词first_name LIKE %A%上的聚合来完成first_name LIKE %A% HAVING every(a.first_name LIKE %A%) 现在按照jOOQ API的术语这意味着我们必须提供having()不同参数类型的hading having()方法的重载例如 // These accept classic predicates
having(Condition... conditions);
having(Collection? extends Condition conditions);// These accept a BOOLEAN type
having(FieldBoolean condition); 当然这些重载可用于任何接受谓词/布尔值的API方法而不仅仅是HAVING子句。 如前所述从SQL1999开始jOOQ的Condition和FieldBoolean确实是同一回事。 jOOQ允许通过显式API在两者之间进行转换 Condition condition1 FIRST_NAME.like(%A%);
FieldBoolean field field(condition1);
Condition condition2 condition(field); …和重载使转换更方便地隐式进行。 所以有什么问题 问题在于我们认为最好再添加一个方便的重载即having(Boolean)方法为了方便起见可以在查询中引入常量可为空的BOOLEAN值这在构建动态SQL时非常有用。 或注释掉某些谓词 DSL.using(configuration).select().from(TABLE).where(true)
// .and(predicate1).and(predicate2)
// .and(predicate3).fetch(); 这个想法是无论您要临时删除哪个谓词都不会将WHERE关键字注释掉。 不幸的是添加此重载给使用IDE自动完成功能的开发人员带来了麻烦。 考虑以下两个方法调用 // Using jOOQ API
Condition condition1 FIRST_NAME.eq (ADAM);
Condition condition2 FIRST_NAME.equal(ADAM);// Using Object.equals (accident)
boolean FIRST_NAME.equals(ADAM); 通过偶然地在equal()方法中添加字母“ s” equal()主要是由于IDE自动完成功能整个谓词表达式从可用于生成SQL的jOOQ表达式树元素到“普通”布尔值都大大改变了语义。值显然总是产生false 。 在添加最后一个重载之前这不是问题。 equals()方法的用法无法编译因为没有适用的重载采用Java boolean类型。 // These accept classic predicates
having(Condition condition);
having(Condition... conditions);
having(Collection? extends Condition conditions);// These accept a BOOLEAN type
having(FieldBoolean condition);// This method didnt exist prior to jOOQ 3.7
// having(Boolean condition); 在jOOQ 3.7之后由于编译器不再抱怨导致错误SQL这种事故开始在用户代码中引起注意。 您继承了宿主语言的“缺陷” Java是“有缺陷的”因为可以保证每种类型都继承自java.lang.Object及其方法 getClass() clone() finalize() equals() hashCode() toString() notify() notifyAll()和wait() 。 在大多数API中这实际上并不是什么大问题。 您实际上并不需要重用上述任何方法名请不要 。 但是在设计内部DSL时这些Object方法名称就像language关键字一样限制了您的设计空间。 在equal(s)的情况下这一点尤其明显。 我们已经学习并且已经弃用并且将移除having(Boolean)重载 并再次移除所有类似的重载。 翻译自: https://www.javacodegeeks.com/2016/01/curious-incidence-jooq-api-design-flaw.htmljooq