以编程方式添加“可连接表”的所有字段

问题描述 投票:0回答:1

我有两张桌子:

CREATE TABLE [instrument].[InstrumentType] (
    [InstrumentTypeId] INT           NOT NULL IDENTITY (1, 1),
    [Name]             VARCHAR (255) NOT NULL,
    CONSTRAINT [PK_InstrumentType]   PRIMARY KEY CLUSTERED ([InstrumentTypeId] ASC)
);

CREATE TABLE [instrument].[Instrument] (
    [InstrumentId]     INT            NOT NULL IDENTITY (1, 1),
    [InstrumentTypeId] INT            NOT NULL,
    [Name]             VARCHAR (255)  NOT NULL,
    CONSTRAINT [PK_Instrument]                PRIMARY KEY CLUSTERED ([InstrumentId] ASC),
    CONSTRAINT [FK_Instrument_InstrumentType] FOREIGN KEY ([InstrumentTypeId]) REFERENCES [instrument].[InstrumentType] ([InstrumentTypeId])
);

我可以简单地获取仪器类型,而无需编写连接(很棒的功能):

create.select(INSTRUMENT.INSTRUMENTID, INSTRUMENT.NAME, INSTRUMENT.instrumenttype.NAME)
      .from(INSTRUMENT)
      .fetch()

我有很多与此类似的表,我想以编程方式创建此查询。我尝试使用

INSTRUMENT.references
但查询失败,因为它引用
IDENTIFIERTYPE
表而不是使用
INSTRUMENT.instrumenttype
路径。这是我的
fetch
方法呈现的查询:

select
  [instrument].[Instrument].[InstrumentId],
  [instrument].[Instrument].[Name],
  [instrument].[InstrumentType].[Name]
from [instrument].[Instrument]

这是我到目前为止所拥有的,但我找不到像手动查询一样通过外键路径的正确方法。

val T = INSTRUMENT

fun fetch(dsl: DSLContext): Any {
  return dsl
    .select(fieldList())
    .from(T)
    .fetch()
}

protected open fun fieldList(): Set<Field<*>> {
  val result = mutableSetOf<Field<*>>()
  val tables = fkTableList(T)
  for (t in tables) {
    val fk = t.references.flatMap { it.fields }.toSet()
    val include = t.fields().toSet()

    //Remove INSTRUMENTTYPEID
    val selectedFields = include - fk
    result.addAll(selectedFields)
  }
  return result
}

private fun fkTableList(table: Table<*>): List<Table<*>> {
  val result = mutableListOf(table)
  val fkTables = table.references.map { it.key.table }
  result.addAll(fkTables.flatMap { fkTableList(it) })
  return result
}
jooq
1个回答
0
投票

注意,有一个以编程方式构造

org.jooq.Path
实例的功能请求,您可能对此感兴趣:

截至 jOOQ 3.19 尚未实施。如果不使用

Path
类型,您必须自己显式添加连接树。您不能仅添加投影。一个相对简单的方法是使用
ON KEY
合成连接语法(jOOQ 的
Path
实现也在内部使用):

.from(tableList())

然后:

protected open fun tableList(): Set<Table<*>> {
  var result = T
  for (t in fkTableList(T)) {
    // inner join would be possible in case there's a NOT NULL constraint
    // on the foreign key columns
    result = result.leftJoin(t).onKey()
  }
  return result
}

onKey()
方法本身无法解决歧义,如果您在同一个子表和父表之间有多个外键,因此最好重构递归
fkTableList
函数以返回
ForeignKey
实例,并使用它.

© www.soinside.com 2019 - 2024. All rights reserved.