【问题标题】:JOOQ - Select Distinct with Join - Fetch mapperJOOQ - 使用 Join 选择 Distinct - 获取映射器
【发布时间】:2020-08-17 09:51:43
【问题描述】:

这是我尝试用 JOOQ 创建的 SQL -

select distinct(kmp.*) from office_all_company_kmp kmp
 inner join company_kmp companykmp on kmp.id=companykmp.kmp_id
 where companykmp.company_id=?1

我正在用 Kotlin 编写代码。我这样做有 2 个问题 -

  1. 在 select 子句中,除非我将 .asList() 添加到 fields 数组,否则无法编译它。
  2. 必须手动编码提取映射器。有没有一种方法可以在不编写所有代码的情况下使用它?我可以映射从一个表中取回的记录,而无需编写任何映射。

这就是我要说的:

fun OfficeAllCompanyKmpDao.findByCompany(companyId: UUID): List<OfficeAllCompanyKmp> =
    this.ctx()
        .selectDistinct(OFFICE_ALL_COMPANY_KMP.fields().asList()) // without the asList() it wouldn't compile
        .from(OFFICE_ALL_COMPANY_KMP)
        .join(COMPANY_KMP).on(OFFICE_ALL_COMPANY_KMP.ID.eq(COMPANY_KMP.KMP_ID))
        .where(COMPANY_KMP.COMPANY_ID.eq(companyId))
        .fetch { // how do I write the mapper without manually writing code like the below?
            OfficeAllCompanyKmp(
                id = it[OFFICE_ALL_COMPANY_KMP.ID],
                officeId = it[OFFICE_ALL_COMPANY_KMP.OFFICE_ID],
                din = it[OFFICE_ALL_COMPANY_KMP.DIN],
                pan = it[OFFICE_ALL_COMPANY_KMP.PAN],
                name = it[OFFICE_ALL_COMPANY_KMP.NAME],
                dateOfBirth = it[OFFICE_ALL_COMPANY_KMP.DATE_OF_BIRTH],
                address = it[OFFICE_ALL_COMPANY_KMP.ADDRESS],
                email = it[OFFICE_ALL_COMPANY_KMP.EMAIL],
                kmpDetails = it[OFFICE_ALL_COMPANY_KMP.KMP_DETAILS],
                createdTimestamp = it[OFFICE_ALL_COMPANY_KMP.CREATED_TIMESTAMP],
                updatedTimestamp = it[OFFICE_ALL_COMPANY_KMP.UPDATED_TIMESTAMP],
                versionNo = it[OFFICE_ALL_COMPANY_KMP.VERSION_NO],
                createdUserId = it[OFFICE_ALL_COMPANY_KMP.CREATED_USER_ID],
                updatedUserId = it[OFFICE_ALL_COMPANY_KMP.UPDATED_USER_ID]
            )
        }

【问题讨论】:

  • 1) selectDistinct 与 OFFICE_ALL_COMPANY_KMP.fields() 作品。你得到什么编译器错误? 2)如果 OfficeAllCompanyKmp 有一个包含所有字段的构造函数,那么只需使用 fetchInto

标签: sql kotlin jooq


【解决方案1】:

比内部连接然后再次删除重复项更好的方法是使用 INEXISTS 半连接您的另一个表:

this.ctx()
    .selectFrom(OFFICE_ALL_COMPANY_KMP)
    .where(OFFICE_ALL_COMPANY_KMP.ID.`in`(
         select(COMPANY_KMP.KMP_ID)
        .from(COMPANY_KMP)
        .where(COMPANY_KMP.COMPANY_ID.eq(companyId)))
    .fetchInto(OfficeAllCompanyKmp::class.java)

或者,或者,使用jOOQ的合成LEFT SEMI JOIN syntaxsee also this blog post for an explanation for this syntax,或this one for joins in general,或Wikipedia's nice explanation about semi joins

this.ctx()
    .select()
    .from(OFFICE_ALL_COMPANY_KMP)
    .leftSemiJoin(COMPANY_KMP)
    .on(OFFICE_ALL_COMPANY_KMP.ID.eq(COMPANY_KMP.KMP_ID))
    .and(COMPANY_KMP.COMPANY_ID.eq(companyId))
    .fetchInto(OfficeAllCompanyKmp::class.java)

您的问题 1) 通过使用不同的 jOOQ API 解决了,您不必在 SELECT 中明确列出所有列。您的问题 2) 可以通过调用 fetchInto() 轻松解决。

【讨论】:

    猜你喜欢
    • 2010-12-28
    • 1970-01-01
    • 1970-01-01
    • 2021-12-26
    • 2017-09-30
    • 2017-04-20
    • 2014-01-09
    • 2017-05-26
    • 1970-01-01
    相关资源
    最近更新 更多