当前位置: 首页 > 知识库问答 >
问题:

具有一对多关系的Jooq单个查询

益楷
2023-03-14

我有一个桌子实验和一个桌子标签。一个实验可能有许多标签。架构:

--------                  --------
|Table1|  1           n   |Table2|
|      | <--------------> |      |
|      |                  |      |
--------                  --------
(experiment)              (tags)

是否可以使用返回实验和相应标签列表的jooq创建查询?

类似Result之类的东西

我也有一个只返回一个结果的查询,有什么方便的吗?

编辑:java8,最新的jooq。


共有2个答案

昌和悦
2023-03-14

您现在可以使用SimpleFlatMapper将结果映射到Tuple2

1-创建映射器,指定键列,假设它是id

JdbcMapper mapper = 
    JdbcMapperFactory
     .newInstance()
     .addKeys(EXPERIMENT.ID.getName())
     .newMapper(new TypeReference<Tuple2<ExperimentRecord, List<TagRecord>>>() {});

2-在查询的结果集上使用映射器

try (ResultSet rs = DSL.using(configuration)
   .select()
   .from(EXPERIMENT)
   .join(TAGS)
   .on(...)
   .fetchResultSet()) {
    Stream<Tuple2<ExperimentRecord, List<TagRecord>>> stream = mapper.stream(rs);
    ....
}

请参阅此处了解更多详细信息

锺离珂
2023-03-14
匿名用户

有许多方法可以使用SQL和/或jOOQ实现嵌套集合。我只是讲了其中的一些:

如果您没有深度嵌套这些集合,那么使用连接对结果进行非规范化(展平)可能会帮到您,而不会在复制数据时增加太多开销。基本上,你会写:

Map<ExperimentRecord, Result<Record>> map =
DSL.using(configuration)
   .select()
   .from(EXPERIMENT)
   .join(TAGS)
   .on(...)
   .fetchGroups(EXPERIMENT);

上面的映射包含作为键的实验记录,以及包含所有标签作为值的嵌套集合。

如果您想将复杂的对象图具体化,那么使用连接可能不再是最佳选择。相反,您可能希望从两个不同的查询中收集客户端中的数据:

Result<ExperimentRecord> experiments = 
DSL.using(configuration)
   .selectFrom(EXPERIMENT)
   .fetch();

Result<TagsRecord> tags =
DSL.using(configuration)
   .selectFrom(TAGS)
   .where(... restrict to the previous experiments ...)
   .fetch();
 

现在,将两个结果合并到客户端的内存中,例如。

experiments.stream()
           .map(e -> new ExperimentWithTags(
                e, 
                tags.stream()
                    .filter(t -> e.getId().equals(t.getExperimentId()))
                    .collect(Collectors.toList())
           ));

这个问题不需要它,但是其他人可能会在寻找与jOOQ嵌套多关系的方法时找到这个问题。我在这里提供了一个答案。从jOOQ 3.14开始,您可以使用RDBMS的SQL /XML或SQL /JSON功能,然后使用Jackson、Gson或JAXB嵌套集合,如下所示:

List<Experiment> experiments =
ctx.select(
      EXPERIMENT.asterisk(),
      field(
        select(jsonArrayAgg(jsonObject(TAGS.fields())))
        .from(TAGS)
        .where(TAGS.EXPERIMENT_ID.eq(EXPERIMENT.ID))
      ).as("tags")
    )
   .from(EXPERIMENT)
   .fetchInto(Experiment.class);

其中,实验是这样一个自定义Java类:

class Experiment {
  long id;
  String name;
  List<Tag> tags;
}

class Tag {
  long id;
  String name;
}

甚至比上述更好的是,您可以使用SQL/XML或SQL/JSON隐藏在jOOQ 3.15新的MULTISET运算符支持后面。假设上述Java类是Java 16记录(或任何其他不可变类),您甚至可以将嵌套集合类型安全地映射到DTO中:

List<Experiment> experiments =
ctx.select(
      EXPERIMENT.ID,
      EXPERIMENT.NAME,
      multiset(
        select(TAGS.ID, TAGS.NAME)
        .from(TAGS)
        .where(TAGS.EXPERIMENT_ID.eq(EXPERIMENT.ID))
      ).as("tags").convertFrom(r -> r.map(Records.mapping(Tag::new)))
    )
   .from(EXPERIMENT)
   .fetch(Records.mapping(Experiment::new));

其中,实验是这样一个自定义Java类:

record Experiment(long id, String name, List<Tag> tags) {}
record Tag(long id, String name) {}

有关更多信息,请参阅此博客文章。

 类似资料:
  • 我正在努力理解如何处理与JOOQ的一对多和多对多关系的Pojo。 我存储玩家创建的位置(一对多关系)。一个位置可以容纳多个可能访问它的其他玩家(多对多)。数据库布局可归结为以下内容: 在我的java应用程序中,所有这些信息都存储在一个pojo中。请注意,玩家和受邀玩家列表可以从应用程序中更新,也需要在数据库中更新: 我可以使用JOOQ的pojo映射将这三个记录映射到单个pojo吗?我可以使用这个p

  • 问题内容: 有三个表:,并且,医院能提供的医疗服务和语言服务。因此,存在两个多对多关系。 简单ERD 现在,我想使用和搜索医院数据。 DaoImpl: 而且,如果我想从三个表中按邮政编码,医疗类型和语言进行搜索,那么如何编写一个jsql。 警告: 错误:org.hibernate.hql.internal.ast.ErrorCounter- 预期加入的路径!希望加入的路径!在org.hiberna

  • 我是新来laravel的,所以原谅我可能的愚蠢问题。此外,我确实研究了所有其他“类似”的问题,但要么它们没有重现正确的解决方案,要么我真的很难理解。 情景: 我有一个帖子模型和一个主题模型。这就是他们现在的样子。 在岗位上。php 在主题上。php 现在,我需要实现的是: 如果将查询参数传递给请求(即q=Food),我只想返回在主题关系中包含主题食物的帖子,而不返回其他帖子。如果什么都没有通过,那

  • 实现了一对多的关系,它运行良好。 我的问题是当我运行下面的查询时,如果表有100个员工行,每个员工有两个部门。数据库查询被调用了101次,因为对每个员工都是调用部门查询,要完成调用全部100行需要很长时间,有没有人可以提出替代的解决方案? 输出XML:

  • 问题内容: 我在Hibernate中具有以下一对一关系(可能为null): 我正在尝试使用HQL选择所有具有非空详细信息的实体: 但这会返回所有实体,无论详细信息是否为空。 那么正确的HQL是什么? 问题答案: 好的,我找到了解决方案:

  • 问题内容: 因此,我有以下实体: 因此,没有对的引用,这意味着我们具有单向一对多关系。我需要寻找一个by 和。也就是说,找到具有指定posId的供应商,然后在供应商的pos列表中找到一个pos。如何为此编写条件查询? 我尝试使用子查询。我的想法是创建一个子查询,该子查询将获取具有给定条件的a的所有内容。然后,主查询将那些中搜索的一个给定。 问题是我无法编写查询来获取s的s列表。显然,您不能编写以下