使用 JOOQ 在多对多关系表中插入值
Insert values in many to many relationship tables with JOOQ
我的数据库中有三个 table,SUBSCRIPTION
、USER_ID
和一个名为 SUBSCRIPTION_USER_ID
的关联 table。
我的策略是使用 JOOQ
批处理三个查询,第一个将一行插入 SUBSCRIPTION
,第二个查询将多行插入 USER_ID
,最后,我需要将关联 ID 插入 SUBSCRIPTION_USER_ID
,因此我执行了以下操作:
InsertValuesStep2 insertUserIds = insertInto(
USER_ID, USER_ID.USER_ID_TYPE, USER_ID.USER_ID_VALUE);
for (String userId : subscriptionDTO.getUserId())
insertUserIds = insertUserIds.values(getValue(0, userId), getValue(1, userId));
InsertReturningStep insertReturningUserIds = insertUserIds.onConflictDoNothing();
InsertResultStep insertReturningSubscription = insertInto(SUBSCRIPTION)
.set(SUBSCRIPTION.CHANNEL_ID, subscriptionDTO.getChannel())
.set(SUBSCRIPTION.SENDER_ID, subscriptionDTO.getSenderId())
.set(SUBSCRIPTION.CATEGORY_ID, subscriptionDTO.getCategory())
.set(SUBSCRIPTION.TOKEN, subscriptionDTO.getToken())
.onConflictDoNothing()
.returningResult(SUBSCRIPTION.ID);
不幸的是,为了将值插入关联 table,我尝试了很多方法但对我没有任何作用,最后,我尝试在 SUBSCRIPTION_USER_ID
using with select 中插入值但是它不起作用:
InsertValuesStep insertValuesSubscriptionUserIds = insertInto(
SUBSCRIPTION_USER_ID,
SUBSCRIPTION_USER_ID.SUBSCRIPTION_ID,
SUBSCRIPTION_USER_ID.USER_ID_ID)
.select(select(SUBSCRIPTION.ID, USER_ID.ID)
.from(SUBSCRIPTION)
.innerJoin(USER_ID)
.on(concat(USER_ID.USER_ID_TYPE,
val(CATEGORY_USER_ID_DELIMITER),
USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId())
.and(SUBSCRIPTION.SENDER_ID.equal(subscriptionDTO.getSenderId()))
.and(SUBSCRIPTION.CHANNEL_ID.equal(subscriptionDTO.getChannel()))
.and(SUBSCRIPTION.CATEGORY.equal(subscriptionDTO.getCategory()))
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getToken()))));
我是不是漏掉了上面的东西?有没有更好的方法使用 JOOQ 插入多对多关系值或使用查询结果作为其他查询的参数?
我假设您发布了整个代码。如果是:
您没有在 USER_ID
插入时调用执行
只需添加
insertUserIds.onConflictDoNothing().execute();
或者,通过调用 returning().fetch()
获取生成的 ID
内部联接
这可能只是一个风格问题,但您似乎在做的是交叉连接。您的 INNER JOIN
过滤器并不是真正的连接谓词。我将它们放在 WHERE
子句中。清晰度可能有助于避免在此类查询中出现更多问题。
具体来说,第一个“连接谓词”非常混乱,包含一个 CONCAT
调用,这不是人们每天在 INNER JOIN
中看到的东西,而且只涉及一个 table,不是两者:
.on(concat(USER_ID.USER_ID_TYPE,
val(CATEGORY_USER_ID_DELIMITER),
USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId())
谓词错误
最后一个谓词似乎是错误的。您正在插入:
.set(SUBSCRIPTION.TOKEN, subscriptionDTO.getToken())
但是你在查询
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getContactId()))));
应该又是subscriptionDTO.getToken()
如上所述,我插入了 SUBSCRIPTION
和 USER_ID
table 的值。并获取关联 table 我需要从上述两个 table 中获取已插入值的 ID,因此为了解决这个问题,我使用此查询插入 SUBSCRIPTION_USER_ID
:
InsertReturningStep insertReturningSubscriptionUserId = insertInto(
SUBSCRIPTION_USER_ID,
SUBSCRIPTION_USER_ID.SUBSCRIPTION_ID,
SUBSCRIPTION_USER_ID.USER_ID_ID)
.select(select(SUBSCRIPTION.ID, USER_ID.ID).from(SUBSCRIPTION
.where(concat(USER_ID.USER_ID_TYPE, val(CATEGORY_USER_ID_DELIMITER), USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId()))
.and(SUBSCRIPTION.SENDER_ID.equal(subscriptionDTO.getSenderId()))
.and(SUBSCRIPTION.CHANNEL_ID.equal(subscriptionDTO.getChannel()))
.and(SUBSCRIPTION.CATEGORY.equal(subscriptionDTO.getCategory()))
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getToken()))).onConflictDoNothing();
最后,我使用 batch
:
执行了所有查询
using(configuration).batch(insertReturningSubscription,
insertReturningUserIds,
insertReturningSubscriptionUserId).execute()
我的数据库中有三个 table,SUBSCRIPTION
、USER_ID
和一个名为 SUBSCRIPTION_USER_ID
的关联 table。
我的策略是使用 JOOQ
批处理三个查询,第一个将一行插入 SUBSCRIPTION
,第二个查询将多行插入 USER_ID
,最后,我需要将关联 ID 插入 SUBSCRIPTION_USER_ID
,因此我执行了以下操作:
InsertValuesStep2 insertUserIds = insertInto(
USER_ID, USER_ID.USER_ID_TYPE, USER_ID.USER_ID_VALUE);
for (String userId : subscriptionDTO.getUserId())
insertUserIds = insertUserIds.values(getValue(0, userId), getValue(1, userId));
InsertReturningStep insertReturningUserIds = insertUserIds.onConflictDoNothing();
InsertResultStep insertReturningSubscription = insertInto(SUBSCRIPTION)
.set(SUBSCRIPTION.CHANNEL_ID, subscriptionDTO.getChannel())
.set(SUBSCRIPTION.SENDER_ID, subscriptionDTO.getSenderId())
.set(SUBSCRIPTION.CATEGORY_ID, subscriptionDTO.getCategory())
.set(SUBSCRIPTION.TOKEN, subscriptionDTO.getToken())
.onConflictDoNothing()
.returningResult(SUBSCRIPTION.ID);
不幸的是,为了将值插入关联 table,我尝试了很多方法但对我没有任何作用,最后,我尝试在 SUBSCRIPTION_USER_ID
using with select 中插入值但是它不起作用:
InsertValuesStep insertValuesSubscriptionUserIds = insertInto(
SUBSCRIPTION_USER_ID,
SUBSCRIPTION_USER_ID.SUBSCRIPTION_ID,
SUBSCRIPTION_USER_ID.USER_ID_ID)
.select(select(SUBSCRIPTION.ID, USER_ID.ID)
.from(SUBSCRIPTION)
.innerJoin(USER_ID)
.on(concat(USER_ID.USER_ID_TYPE,
val(CATEGORY_USER_ID_DELIMITER),
USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId())
.and(SUBSCRIPTION.SENDER_ID.equal(subscriptionDTO.getSenderId()))
.and(SUBSCRIPTION.CHANNEL_ID.equal(subscriptionDTO.getChannel()))
.and(SUBSCRIPTION.CATEGORY.equal(subscriptionDTO.getCategory()))
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getToken()))));
我是不是漏掉了上面的东西?有没有更好的方法使用 JOOQ 插入多对多关系值或使用查询结果作为其他查询的参数?
我假设您发布了整个代码。如果是:
您没有在 USER_ID
插入时调用执行
只需添加
insertUserIds.onConflictDoNothing().execute();
或者,通过调用 returning().fetch()
内部联接
这可能只是一个风格问题,但您似乎在做的是交叉连接。您的 INNER JOIN
过滤器并不是真正的连接谓词。我将它们放在 WHERE
子句中。清晰度可能有助于避免在此类查询中出现更多问题。
具体来说,第一个“连接谓词”非常混乱,包含一个 CONCAT
调用,这不是人们每天在 INNER JOIN
中看到的东西,而且只涉及一个 table,不是两者:
.on(concat(USER_ID.USER_ID_TYPE,
val(CATEGORY_USER_ID_DELIMITER),
USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId())
谓词错误
最后一个谓词似乎是错误的。您正在插入:
.set(SUBSCRIPTION.TOKEN, subscriptionDTO.getToken())
但是你在查询
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getContactId()))));
应该又是subscriptionDTO.getToken()
如上所述,我插入了 SUBSCRIPTION
和 USER_ID
table 的值。并获取关联 table 我需要从上述两个 table 中获取已插入值的 ID,因此为了解决这个问题,我使用此查询插入 SUBSCRIPTION_USER_ID
:
InsertReturningStep insertReturningSubscriptionUserId = insertInto(
SUBSCRIPTION_USER_ID,
SUBSCRIPTION_USER_ID.SUBSCRIPTION_ID,
SUBSCRIPTION_USER_ID.USER_ID_ID)
.select(select(SUBSCRIPTION.ID, USER_ID.ID).from(SUBSCRIPTION
.where(concat(USER_ID.USER_ID_TYPE, val(CATEGORY_USER_ID_DELIMITER), USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId()))
.and(SUBSCRIPTION.SENDER_ID.equal(subscriptionDTO.getSenderId()))
.and(SUBSCRIPTION.CHANNEL_ID.equal(subscriptionDTO.getChannel()))
.and(SUBSCRIPTION.CATEGORY.equal(subscriptionDTO.getCategory()))
.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getToken()))).onConflictDoNothing();
最后,我使用 batch
:
using(configuration).batch(insertReturningSubscription,
insertReturningUserIds,
insertReturningSubscriptionUserId).execute()