英文:
Insert values in many to many relationship tables with JOOQ
问题
我在我的数据库中有三个表,SUBSCRIPTION
,USER_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_ID
using 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
如上所述,我已经为 SUBSCRIPTION
和 USER_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()
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论