ORM谁可以动态生成脚本

时间:2019-04-04 14:53:01

标签: hibernate jpa jdbc orm jooq

因此,基本上,我正在检查休眠状态以及评估过的ORM JOOQ。对于几乎所有基于Java的ORM实现,JPA都是事实上的主要标准。

我并不是说它们不是完美的或不好的,但是我的问题就像我在使用以下这些提供的各种选项时发现了许多问题和难题一样。

  1. 休眠:

    a。现在它淘汰了标准API,因此我们现在必须遵循JPA方式, 在这种情况下,我不能对一个表的几列使用multiselect()或Selection,而我的bean pojo没有特定的构造函数。

例如我的Bean / POJO几乎有80列

在一个地方,我只需要10列,而在另一个地方,我需要Bean / POJO映射到的表的20列。 现在在这种情况下,我必须创建2个包含选择字段的单独DTO,或者必须在我的主映射Bean / POJO中创建两个不同的重载构造函数。

这是按照JPA的规定,没有办法仅使用getter settersof字段初始化Bean / POJO。

其背后的想法是减少类的数量,而这是我们不必要创建的类。

如果假设我遇到这种情况,那么我必须从一个表中获取几乎25种不同的组合,那么就JPA而言,我必须在一个Bean / POJO中创建25个不同的构造函数,或者在25个不同的DTO(WTH)中创建。

b。当我的Bean / Pojo构造函数如下所示时,Hibernate失败

MyBean(String name, String email)

在选择时是否愿意

query.multiselect(new Selection[]{mappingBean.get("email"),mappingBean.get("name")});

它以错误的顺序初始化,这是按照我键入的地狱漏洞。 (当然,开发人员确实有责任,但仍然是错误的)

  1. 搜索条件模式: 无论我们在哪里需要数据,我们都必须立即编写方法,或者为了隐藏SQL而必须编写JPQL,HQL或任何抽象脚本。

现在,如果我在一张桌子上有25种不同脚本的不同组合,那么我必须为这些脚本编写25种不同的方法,因为Hibernate或JPS的标准API都具有较差和复杂的脚本构建系统。

如果JOOQ的所有Java都是在脚本中解释的(WTH)

现在没有满足以下要求的简单API或ORM 我发现,如果您能提供帮助,我会非常满意的。

  1. 我不想使用任何抽象语言的HQL JPQL代替像
  2. 这样的SQL

我创建了很少的代码,这些代码作为对象传递给MY API应该能够做到的方法。

  1. 如果存在联接的情况(我必须说并非所有数据库都经过特殊设计,以防意外更改突然发生),在这种情况下,我们必须对联接有一定的灵活性,每次都不可能维护适当的关系(因为存在管理方面的约束,他们专注于交付而不是可维护的系统)。

  2. 如果要编写SQL,我应该写一些特定的部分,例如where子句的一部分,或者只是选择部分

4。没有人正确地支持复杂的脚本,例如动态的Unions相交。

等列表很长,但是如果您能帮助我至少有一些合适的人可以帮助我...

编辑:

现在编辑JOOQ部分

我还没有研究过JOOQ的内部结构,它也使用AST ok,但是我的问题是它遵循的模式可以check here

如果我发现普通JDBC做错了什么,如果我必须以整数或字符串或单个数据类型的形式从数据库中获取数据,则我的JDBC可以通过任何方式为我提供请注意JDBC中的类型安全,同样,我必须使用JOOQ DSL进行操作。 至少我期望Bean / POJO的结果像Hibernate Criteria API提供或JPA提供一样,不同之处在于它们也存在滞后。 如果我不知道JOOQ,因为正如我所看到的例子一样,在其教程中找到了SQL类型代码。

现在让我们来看另一个例子(到目前为止,我们已经进行了深入探索,您可以帮助我弄清楚我尝试通过其社区提出的Hibernate可以解决的一些问题,请查看herehere(因为您已经感谢并引用了这些API作为灵感),

例如JOOQ [![来自JOOQ的示例] [1]] [1]

的示例

现在,如果我们观察一下,我必须编写1个sql或仅编写一组列选择,然后最终使用它,但是想像一下我必须在N个地方使用同一个表且列组不同,那么我必须不写N个JOOQ DSL的脚本(这里的代码是可互换的JOOQ SCRIPT check图像,我的意思是,您的SQL和代码看起来互相模仿),

所以我在以下几点进行了分析:

  1. 如果我必须编写N个不同选择的内容,那么我要么编写一个类,将所有选择都包装在N个不同的方法中,并且在任何需要的地方,我只需要在业务逻辑层调用这些方法即可获取数据(这是我看到的HQL,JPQL和JOOQ DSL(按图像)的缺陷。)

在这里,我将通过创建N个方法来制造混乱,因为我必须弄清楚哦,我必须使用方法X的4列,而我必须使用方法Y的5列,这在拥有团队时会更加糟糕100位开发人员,因为每个人可能都不在努力寻找正确的方法,而是他/她在那里创建了自己,这将创建冗余和重复的代码。

同样,我确定您不希望在业务逻辑层中调用类似DSL之类的脚本,因为您只需要基于“为什么和从哪里”是ORM及其盟友的任务和依据的内容(此处我指的是使用DAO调用作为盟友或ORM的DAO和用于数据提取的Factory方法。

  1. 现在,另一种方式是我将有一组独立的标准类,这些标准类与完全与ORM分离的Bean / POJO松散耦合,它将仅遵循ORM的一些标准规则,因此它可以利用搜索标准来查询数据库中的数据并向我返回Bean / POJO列表。

因此在这里,对于任何选择,我只需要编写一种方法即可。我们称其为工厂类中的List findData(SearchCriteria sc) (M之所以称其为工厂,是因为它将具有DAO的方法和对象,并使用DAO来提供Bean列表,因此它成为使用ORM从数据库生成的对象生成器类。)

现在,此方法有责任根据标准为我提供所需的输出,在这种情况下,无论何时在我的业务层中,我需要一组特定的数据,我都可以创建搜索条件并将其传递给该方法,这将给我列出Bean / POJO。

因此,这样我就可以根据需求在业务逻辑层的不同部分创建搜索条件,无论是否有N次获取数据,但至少我可以肯定,获取数据的责任只是我的一种方法工厂类是我的业务层和我的ORM API之间的一种分隔符(例如,您可以进门),工厂问题将由ORM处理,而不是由用户处理,或者由开发人员自己处理。

希望你明白我的意思。

这些休眠或JPA问题已经解决了一些,但并没有完全解决,因为它们的术语也与您在任何需要使用条件构建器的地方都相同,这不是在良好的代码结构中在业务层内部进行条件查询。

编辑2:

卢卡斯,我的意思是我要指出的重点

  1. 检查以下JOOQ代码:
public static ResultQuery<Record2<String, String>> actors(
    Function<Actor, Condition> where
) {
    return ctx.select(ACTOR.FIRST_NAME, ACTOR.LAST_NAME)
              .from(ACTOR)
              .where(where.apply(ACTOR)));
}

此处的ACTOR看起来像是实际的表名,而FIRST_NAME是它的列, 因此,有什么标准可以遵循某些代码惯例,或者我必须自己设计吗?

例如,像Bean / POJO / DTO一样,UserBean.java可以保存从数据库获取的数据,因为它是表USER的默认映射,我们可以使用

来获取数据
ctx.select( *).from(UserBean.class)  //I m not sure how do * but will figgure out that separately

因此,在那种情况下,例如在上述情况下,最好有一个标准的映射器 UserDAO.java,它将具有静态最终字符串形式的字段,其中包含表和表名的确切列名。

工厂可以使用它来更广泛地调用(这只是适当的代码结构的想法)

那么JOOQ是否列出任何实践或模式建议? 我只是给出了自己的解释。

  1. 对于第2点,我没有考虑设计良好的数据库,因为我的数据库不在那些建立良好的关系和约束维持模式之内,

它有很多表,这些表具有包含包含两个表之间适当关系的公共数据的列,但是没有在数据库级别应用任何外键关系。

现在,在这种情况下,休眠状态下的Join变得太困难了,我们必须借助包含交叉表数据映射和HQL或纯SQL的DTO进行处理。

我的想法是,如果我必须彼此连接两个在数据库级别没有任何适当关系的实体,那么,JOOQ是否具有以下安排?

如果存在UserBean和BankAccountBean,其中一个用户可以拥有多个银行帐户,

因此对于以下脚本

Select A.USER_ID, A.USER_NAME, B.BANK_NAME, B.BANK_ACCT_TYPE, B.BANK_ACCT_NUMBER 
FROM USER A LEFT JOIN USER_BANK_ACCOUNT B On A.USER_ID = B.USER_ID

现在,在这种情况下,理想情况下不是创建单独的完整新Bean,我的想法是,必须有UserBankAcctJoinBean应该能够处理此数据提取(此处必须考虑动态选择)

现在,如果我们谈论UserBankAcctJoinBean,它应该扩展UserBean(因为在我的联接中主表是User),因此默认情况下,它将继承Users的所有属性,并且应包含一个引用变量 UserBankAccountBean,因此应通过反射在此引用上初始化属于USER_BANK_ACCOUNT的选择部分

此处与Hibernate不同,因为它确实允许具有辅助表的列表对象,但这不是基本概念,因为其中hibernate在架构中的表之间包含适当的已建立关系。

JOOQ是否具有这种或类似方式?

  1. 如果JOOQ遵循JPA模式,那么在动态选择的情况下它是如何内部工作的,因为正如我在动态选择的情况下探讨JPA一样,其规范说要使用特定的构造函数直接初始化对象,这是最大的挑战,因为如果我想使用4-5种不同方式处理多个不同的列,然后必须使用4-5种不同的重载构造函数或创建4-5种不同的Bean / POJO / DTO(这在我先前的编辑中已经存在)

另外,在休眠源代码的情况下,它首先将数据从ResultSet加载到Object [],然后使用字段的setter方法初始化Bean / POJO / DTO,因此在这里,如果您看到双重滞后,则不是直接初始化对象通过调用field的getter setter,它首先将数据存储到Object数组,然后从该数组加载到bean,最终每次提取行迭代创建两次。

这确实浪费资源,因为对于同一任务,在同一组数据上进行两次迭代不是一种有效的方法,

那么,JOOQ在内部如何工作?它会使用getter设置器直接将数据初始化为DTO还是与Hibernate类似地工作?

1 个答案:

答案 0 :(得分:3)

我将只回答您的jOOQ部分

预编辑2

  

如果我发现普通JDBC做错了什么,如果我必须以整数或字符串或单个数据类型的形式从数据库中获取数据,则我的JDBC可以通过任何方式为我提供请注意JDBC中的类型安全,同样,我必须使用JOOQ DSL进行操作。至少我期望Bean / POJO的结果像Hibernate Criteria API提供或JPA提供一样,不同之处在于它们也存在滞后。如果我不知道JOOQ,因为正如我所看到的例子一样,在其教程中找到了SQL类型代码。

jOOQ可以将元组投影到任意的“ Beans / POJO”中。只需使用DefaultRecordMapper。一个例子:

class DTO {
  int a;
  int b;
  int c;
}

然后

List<DTO> dtos =
ctx.select(T.A, T.B)
   .from(T)
   .fetchInto(DTO.class);
  

如果我必须编写N个不同选择的内容,那么我要么编写一个类,将所有选择都包装在N个不同的方法中,并且在任何需要的地方,我只需要在我的业务逻辑层调用这些方法即可获取数据(这是我看到的HQL,JPQL和JOOQ DSL(按图像)的缺陷。)

您没有发布任何图像,但是根据我对您的问题的理解,在上面的示例中,我重用了DTO来获取两列而不是3。无需为每个查询创建一个DTO。当然,您可以按以下方式使用无类型的记录:

Result<Record> result =
ctx.select(T.A, T.B)
   .from(T)
   .fetch();

然后

for (Record record : result)
    System.out.println(record.get(T.A) + ":" + record.get(T.B));
  

在这里,我将通过创建N个方法来制造混乱,因为我必须弄清楚哦,我必须使用方法X的4列,而我必须使用方法Y的5列,这在拥有团队时会更加糟糕100位开发人员,因为每个人可能都不在努力寻找正确的方法,而是他/她在那里创建了自己,这将创建冗余和重复的代码。

仅仅是因为许多jOOQ示例使用简单的准静态SQL语法并不意味着您不能编写动态SQL。实际上,每个 jOOQ语句都是动态SQL语句。例如:

List<Field<?>> select = new ArrayList<>();
if (something)
    select.add(T.A);
if (somethingElse)
    select.add(T.B);
Result<?> result = ctx.select(select).from(T).fetch();

在此处进一步阅读:https://blog.jooq.org/2017/01/16/a-functional-programming-approach-to-dynamic-sql-with-jooq

  

因此在这里,对于任何选择,我只需要编写一种方法即可。我们将其称为工厂类内的List findData(SearchCriteria sc)(M之所以称为工厂,是因为它将具有DAO的方法和对象,使用DAO它将提供Bean的List,因此它成为使用ORM从数据库变为对象生成器的类)

您是否正在寻找Spring Data?

  

希望你明白我的意思。

并非如此,但我希望你成为我的:)

发布修改2

因此,您添加了很多其他问题。这是我的答案:

  

这里的ACTOR看起来像是实际的表名,而FIRST_NAME则是它的列,是否有任何标准可用来遵循某些代码惯例,或者我必须自己设计它?

jOOQ使您可以立即使用它提供的功能,也可以花几天时间根据自己的风格定制jOOQ。如果您不知道此处的答案,请使用jOOQ的默认值。他们是精心挑选的。

  

//我不确定该怎么做,*会另行说明

您可以将select()列表留空,或致电selectFrom(),或使用DSL.asterisk()

  

那么JOOQ是否列出任何实践或模式建议?

再说一次,jOOQ不会根据您自己的风格来判断您,而是让您无需打扰就可以随心所欲。但是jOOQ具有“明显”的默认值

  

现在,在这种情况下,理想情况下不是创建单独的完整新Bean,我的想法是,必须有UserBankAcctJoinBean应该能够处理此数据提取(此处必须考虑动态选择)

如果您认为这是一个很好的可扩展的主意,那就去做。您可以编写自己的bean。或者只是使用jOOQ的记录,这与元组没有什么不同。

  

如果JOOQ遵循JPA模式

我不知道这是什么意思,也不知道为什么您认为jOOQ会这样做。

  

因为如果我想使用4-5种不同方式处理多个不同的列,那么我必须使用4-5种不同的重载构造函数或创建4-5种不同的Bean / POJO / DTO(这一点已经存在于我的以前的修改)

如果您对此感到担心,请不要使用不可变的POJO,将可变的POJO与JavaBeans样式设置器和getter一起使用,并且jOOQ将仅调用结果集中存在匹配列的那些。