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

huangapple go评论67阅读模式
英文:

Insert values in many to many relationship tables with JOOQ

问题

我在我的数据库中有三个表,SUBSCRIPTIONUSER_ID,还有一个关联表叫做SUBSCRIPTION_USER_ID

我的策略是使用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);

然而,要将值插入到关联表中,我尝试了许多方法,但都没有成功,最后,我尝试使用带有选择的方式在SUBSCRIPTION_USER_ID中插入值,但是它不起作用:

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插入多对多关系值或者将查询结果用作其他查询的参数方面,是否有更好的方法?

英文:

I have three tables in my database, SUBSCRIPTION, USER_ID, and an association table called SUBSCRIPTION_USER_ID.

My strategy is to use JOOQ batch with three queries, the first one to insert on row into SUBSCRIPTION, the second query to insert multiple rows into USER_ID, and finally, I need to insert the association IDs into SUBSCRIPTION_USER_ID, so I did the following:

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);

Unfortunately, to insert values into the association table, I tried many ways but nothing works for me, finally, I tried to insert values in SUBSCRIPTION_USER_IDusing with select but It doesn't work:

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()))));

Am I missing something above? Is there a better way using JOOQ to insert many-to-many relationship values or to use queries results as parameters for other queries?

答案1

得分: 0

我假设你已经发布了你的整个代码。如果是这种情况:

你没有调用USER_ID插入上的execute方法

只需添加:

insertUserIds.onConflictDoNothing().execute();

或者,可以通过调用returning().fetch()来获取生成的ID。

内连接

这可能只是一个样式上的问题,但你似乎在做一个交叉连接(cross join)。你的INNER JOIN过滤条件实际上并不是连接谓词。我会将它们放在WHERE子句中。在这种查询中,清晰度可能有助于避免进一步的问题。

具体来说,第一个“连接谓词”非常令人困惑,其中包含一个CONCAT调用,在INNER JOIN中不太常见,而且只涉及一个表,而不是两个:

.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()

英文:

I'm assuming you posted your entire code. In case of which:

You don't call execute on your USER_ID insertion

Simply add

insertUserIds.onConflictDoNothing().execute();

Or alternatively, fetch the generated IDs using a call to returning().fetch()

Inner join

This might just be a stylistic question, but what you seem to be doing is a cross join. Your INNER JOIN filters aren't really join predicates. I'd put them in the WHERE clause. Clarity may help avoid further problems in such a query.

Specifically, that first "join predicate" is very confusing, containing a CONCAT call, which isn't something one would see in an INNER JOIN every day, and only touches one table, not both:

.on(concat(USER_ID.USER_ID_TYPE, 
                val(CATEGORY_USER_ID_DELIMITER), 
                USER_ID.USER_ID_VALUE).in(subscriptionDTO.getUserId())

Wrong predicate

That last predicate seems wrong. You're inserting:

.set(SUBSCRIPTION.TOKEN, subscriptionDTO.getToken())

But you're querying

.and(SUBSCRIPTION.TOKEN.equal(subscriptionDTO.getContactId()))));

That should probably be subscriptionDTO.getToken() again

答案2

得分: 0

如上所述,我已经为 SUBSCRIPTIONUSER_ID 表插入了值。并且为了关联表,我需要从上述两个表中获取已插入值的 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()
英文:

As mentioned above, I have inserted values for SUBSCRIPTION and USER_ID tables. And get for the association table I need to get the IDs of the already inserted values from the above two tables, so to solve the issue I've used this query to insert in 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();

Finally, I have executed all the queries using batch:

using(configuration).batch(insertReturningSubscription,
 insertReturningUserIds,
 insertReturningSubscriptionUserId).execute()

huangapple
  • 本文由 发表于 2020年10月8日 17:40:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/64259796.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定