1

我试图想象如何将 jOOQ 与桥接表一起使用。假设你有

CREATE TABLE TableA (
  id BIGSERIAL PRIMARY KEY
)

CREATE TABLE TableB (
  id BIGSERIAL PRIMARY KEY
)

CREATE TABLE TableBridge (
  id BIGSERIAL,
  table_a_id INTEGER NOT NULL,
  table_b_id INTEGER NOT NULL,
  CONSTRAINT tablea_pk_id PRIMARY KEY (table_a_id)
   REFERENCES TableA (id) MATCH SIMPLE,
  CONSTRAINT tableb_pk_id PRIMARY KEY (table_b_id)
   REFERENCES TableB (id) MATCH SIMPLE
)

使用 jOOQ 映射此模式时,将有三个记录类TableARecordTableBRecordTableBridgeRecord

如果我想通过为 TableA 插入记录来持久化,我是否应该首先创建并持久化 TableB 记录,然后为 TableB 保留行,然后手动添加 TableBridge 行?没有任何方法可以自动保存桥表中的行吗?

4

1 回答 1

1

有几种方法可以解决此类问题:

1. 使用“单个”jOOQ 语句(运行三个 SQL 语句)

使用标准 jOOQ 解决此类问题的最惯用方法是编写一条 SQL 语句,一次性处理所有三个插入:

ctx.insertInto(TABLE_BRIDGE)
   .columns(TABLE_BRIDGE.TABLE_A_ID, TABLE_BRIDGE.TABLE_B_ID)
   .values(
        ctx.insertInto(TABLE_A)
           .columns(TABLE_A.VAL)
           .values(aVal)
           .returning(TABLE_A.ID)
           .fetchOne()
           .get(TABLE_A.ID),
        ctx.insertInto(TABLE_B)
           .columns(TABLE_B.VAL)
           .values(bVal)
           .returning(TABLE_B.ID)
           .fetchOne()
           .get(TABLE_B.ID)
   )
   .execute();

以上适用于 jOOQ 3.8。很可能,未来的版本将删除一些关于returning() .. fetchOne() .. get().

2. 用一条 SQL 语句完成

我假设您从BIGSERIAL数据类型使用中使用 PostgreSQL,因此以下 SQL 语句也可能是您的选择:

WITH
  new_a(id) AS (INSERT INTO table_a (val) VALUES (:aVal) RETURNING id),
  new_b(id) AS (INSERT INTO table_b (val) VALUES (:bVal) RETURNING id)
INSERT INTO table_bridge (table_a_id, table_b_id)
SELECT new_a.id, new_b.id
FROM new_a, new_b

上述查询目前不完全通过 jOOQ 3.8 API 支持,但您可以通过使用一些普通 SQL 来解决 jOOQ API 的限制:

ctx.execute(
  "WITH "
+ "  new_a(id) AS ({0}), "
+ "  new_b(id) AS ({1}) "
+ "{2}",

  // {0}
  insertInto(TABLE_A)
  .columns(TABLE_A.VAL)
  .values(aVal)
  .returning(TABLE_A.ID),

  // {1}
  insertInto(TABLE_B)
  .columns(TABLE_B.VAL)
  .values(bVal)
  .returning(TABLE_B.ID),

  // {2}
  insertInto(TABLE_BRIDGE)
  .columns(TABLE_BRIDGE.TABLE_A_ID, TABLE_BRIDGE.TABLE_B_ID)
  .select(
      select(field("new_a.id", Long.class), field("new_b.id", Long.class))
      .from("new_a, new_b")
   )
);

很明显,未来的 jOOQ API 也会有所改进。

3. 这样做UpdatableRecords

在这个特别简单的情况下,您只需调用以下命令即可逃脱:

TableARecord a = ctx.newRecord(TABLE_A);
a.setVal(aVal);
a.store();

TableBRecord b = ctx.newRecord(TABLE_B);
b.setVal(bVal);
b.store();

TableBridgeRecord bridge = ctx.newRecord(TABLE_BRIDGE);
bridge.setTableAId(a.getId());
bridge.setTableBId(b.getId());
bridge.store();
于 2016-12-01T14:01:42.900 回答