在 select 查询 jooq 中使用 java 方法
Using a java method in select query jooq
我有一个 mysql 查询,格式如下
dslContext
.select(
ITEMDATA.ITEMID,
ITEMDATA.COST,
ITEMNAMES.ITEMNAME
)
.from(ITEMDATA)
.join(ITEMNAMES)
.on(ITEMDATA.ITEMID=ITEMNAMES.ITEMID)
.where(conditions);
以上查询在结果中将 ITEMDATA 与 ITEMMAMES table 连接到 select ITEMNAME。我正在内存中缓存 ITEMMAMES table,并希望避免与 ITEMMAMES table 的连接。这将加快查询速度并简化查询,因为实际查询要复杂得多。
我想用它类似于下面的东西。我想在 select 参数列表中调用 itemNamesCache.getItemName,它给出了 ITEMNAME 和 returns select 结果的一部分。 getItemName
应将响应中返回的 ITEMID 作为参数并给出 ITEMNAME。
dslContext.
select(
ITEMDATA.ITEMID,
ITEMDATA.COST,
itemNamesCache.getItemName(valueOfItemId)
)
.from(ITEMDATA)
.where(conditions);
P.S:我可以迭代结果并调用 itemNamesCache.getItemName。但如果可能的话,我想使用查询中嵌入的东西
您不能从 SQL 查询返回到某些 Java 逻辑,即使您正在使用 jOOQ 构建 SQL 查询(因此 Java) 让它看起来可行。
但是,您可以 post 通过使用先前构建的缓存修补记录来处理 jOOQ 结果:
一个Java解决方案
如果您使用的数据库确实无法处理这个简单的连接(并且您已经检查过所有适当的索引和约束都已到位!),那么您可以尝试以下解决方案:
// Assuming this import:
import static org.jooq.impl.DSL.*;
写...
Map<Integer, String> itemNamesCache =
dslContext.selectDistinct(ITEMNAMES.ITEMID, ITEMNAMES.NAME)
.from(ITEMNAMES)
.fetchMap(ITEMNAMES.ITEMID, ITEMNAMES.NAME);
dslContext
.select(
ITEMDATA.ITEMID,
ITEMDATA.COST,
// create an empty column here
inline(null, String.class).as(ITEMNAMES.NAME))
.from(ITEMDATA)
.where(conditions)
// fill the empty column with cached values
.fetch(r -> r.value3(itemNamesCache.get(r.value1())));
基于SQL的解决方案
SQL 的方法是写一个 correlated subquery。
SELECT
itemdata.itemid,
itemdata.cost,
(SELECT itemnames.name FROM itemnames WHERE itemnames.itemid = itemdata.itemid)
FROM
itemdata
WHERE
...
使用 jOOQ
// Assuming this import:
import static org.jooq.impl.DSL.*;
...写:
dslContext
.select(
ITEMDATA.ITEMID,
ITEMDATA.COST,
field(select(ITEMNAMES.NAME)
.from(ITEMNAMES)
.where(ITEMDATA.ITEMID.eq(ITEMNAMES.ITEMID)))
.as(ITEMNAMES.NAME)
)
.from(ITEMDATA)
.where(conditions)
.fetch();
理论上,两个查询应该 运行 以完全相同的速度,因为它们是等价的(如果您在 ITEMDATA.ITEMID
上有外键)。
在实践中,大多数数据库可能对 JOIN
查询有更好的性能,除非它们实现标量子查询缓存(例如像 Oracle),这可以大大加快第二个查询的速度,具体取决于查询的数量distinct ITEMIDs
(越小越好)。
我有一个 mysql 查询,格式如下
dslContext
.select(
ITEMDATA.ITEMID,
ITEMDATA.COST,
ITEMNAMES.ITEMNAME
)
.from(ITEMDATA)
.join(ITEMNAMES)
.on(ITEMDATA.ITEMID=ITEMNAMES.ITEMID)
.where(conditions);
以上查询在结果中将 ITEMDATA 与 ITEMMAMES table 连接到 select ITEMNAME。我正在内存中缓存 ITEMMAMES table,并希望避免与 ITEMMAMES table 的连接。这将加快查询速度并简化查询,因为实际查询要复杂得多。
我想用它类似于下面的东西。我想在 select 参数列表中调用 itemNamesCache.getItemName,它给出了 ITEMNAME 和 returns select 结果的一部分。 getItemName
应将响应中返回的 ITEMID 作为参数并给出 ITEMNAME。
dslContext.
select(
ITEMDATA.ITEMID,
ITEMDATA.COST,
itemNamesCache.getItemName(valueOfItemId)
)
.from(ITEMDATA)
.where(conditions);
P.S:我可以迭代结果并调用 itemNamesCache.getItemName。但如果可能的话,我想使用查询中嵌入的东西
您不能从 SQL 查询返回到某些 Java 逻辑,即使您正在使用 jOOQ 构建 SQL 查询(因此 Java) 让它看起来可行。
但是,您可以 post 通过使用先前构建的缓存修补记录来处理 jOOQ 结果:
一个Java解决方案
如果您使用的数据库确实无法处理这个简单的连接(并且您已经检查过所有适当的索引和约束都已到位!),那么您可以尝试以下解决方案:
// Assuming this import:
import static org.jooq.impl.DSL.*;
写...
Map<Integer, String> itemNamesCache =
dslContext.selectDistinct(ITEMNAMES.ITEMID, ITEMNAMES.NAME)
.from(ITEMNAMES)
.fetchMap(ITEMNAMES.ITEMID, ITEMNAMES.NAME);
dslContext
.select(
ITEMDATA.ITEMID,
ITEMDATA.COST,
// create an empty column here
inline(null, String.class).as(ITEMNAMES.NAME))
.from(ITEMDATA)
.where(conditions)
// fill the empty column with cached values
.fetch(r -> r.value3(itemNamesCache.get(r.value1())));
基于SQL的解决方案
SQL 的方法是写一个 correlated subquery。
SELECT
itemdata.itemid,
itemdata.cost,
(SELECT itemnames.name FROM itemnames WHERE itemnames.itemid = itemdata.itemid)
FROM
itemdata
WHERE
...
使用 jOOQ
// Assuming this import:
import static org.jooq.impl.DSL.*;
...写:
dslContext
.select(
ITEMDATA.ITEMID,
ITEMDATA.COST,
field(select(ITEMNAMES.NAME)
.from(ITEMNAMES)
.where(ITEMDATA.ITEMID.eq(ITEMNAMES.ITEMID)))
.as(ITEMNAMES.NAME)
)
.from(ITEMDATA)
.where(conditions)
.fetch();
理论上,两个查询应该 运行 以完全相同的速度,因为它们是等价的(如果您在 ITEMDATA.ITEMID
上有外键)。
在实践中,大多数数据库可能对 JOIN
查询有更好的性能,除非它们实现标量子查询缓存(例如像 Oracle),这可以大大加快第二个查询的速度,具体取决于查询的数量distinct ITEMIDs
(越小越好)。