在select query jooq中使用java方法

时间:2017-05-29 16:38:33

标签: java mysql jooq

我有一个mysql查询,格式如下

        dslContext
            .select(
                ITEMDATA.ITEMID,
                ITEMDATA.COST,
                ITEMNAMES.ITEMNAME
            )
            .from(ITEMDATA)
            .join(ITEMNAMES)
            .on(ITEMDATA.ITEMID=ITEMNAMES.ITEMID)
            .where(conditions);

上述查询将ITEMDATA与ITEMNAMES表连接,以在结果中选择ITEMNAME。我在内存中缓存ITEMNAMES表,并希望避免与ITEMNAMES表的连接。这将加速查询并简化查询,因为实际查询要复杂得多。

我想用它类似于以下内容。我想在select params列表中调用itemNamesCache.getItemName,它给出ITEMNAME并返回select结果的一部分。 getItemName应将响应中返回的ITEMID作为参数,并提供ITEMNAME。

    dslContext.
        select(
            ITEMDATA.ITEMID,
            ITEMDATA.COST,
            itemNamesCache.getItemName(valueOfItemId)
        )
        .from(ITEMDATA)
        .where(conditions);

P.S:我可以迭代结果并调用itemNamesCache.getItemName。但是如果可能的话,我想使用查询中嵌入的东西

1 个答案:

答案 0 :(得分:1)

您无法从SQL查询回调到某些Java逻辑,即使您使用jOOQ(以及Java)构建SQL查询这一事实使得它看起来可行。

但是,您可以使用以前构建的缓存修补记录来后处理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 {的数量{ {1}}(越小越好)。