使用 JOOQ 在多对多关系表中插入值

Insert values in many to many relationship tables with JOOQ

我的数据库中有三个 table,SUBSCRIPTIONUSER_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_IDusing 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()

如上所述,我插入了 SUBSCRIPTIONUSER_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()