jOOQ 和桥接表
jOOQ and bridge tables
我正在想象如何将 jOOQ 与 bridge tables 一起使用。
假设你有
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 映射此模式时,将有三个记录 类、TableARecord
、TableBRecord
和 TableBridgeRecord
。
如果我想通过为 TableA 插入一条记录来持久化,我是否应该先创建并持久化 TableB 记录,然后为 TableB 持久化行,然后手动添加 TableBridge 行?有没有办法自动保存桥中的行table?
有几种方法可以解决这类问题:
1。使用 "single" 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:[=17 来解决 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 APIs 会有改进。
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();
我正在想象如何将 jOOQ 与 bridge tables 一起使用。 假设你有
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 映射此模式时,将有三个记录 类、TableARecord
、TableBRecord
和 TableBridgeRecord
。
如果我想通过为 TableA 插入一条记录来持久化,我是否应该先创建并持久化 TableB 记录,然后为 TableB 持久化行,然后手动添加 TableBridge 行?有没有办法自动保存桥中的行table?
有几种方法可以解决这类问题:
1。使用 "single" 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:[=17 来解决 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 APIs 会有改进。
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();