首页 > 解决方案 > jooq中的Case When或iif语法表达式

问题描述

我正在尝试在 jooq 中重现这个 MySQL 查询。

messageTable1、messageTable2 相同的列

select 
msg.index as index,
left(msg.message, if(msg.type = 1, 10, msg.maxLength)) as message
from
messageTable1 as msg

select 
msg.index as index,
left(msg.message, if(msg.type = 1, 10, msg.maxLength)) as message
from
messageTable2 as msg

制作函数java

public Message getMessageTest(String tableName) {
    return roDslContext.select(
           DSL.field("msg.index").as("index"),
           left(DSL.field( "{0}", String.class, "msg.message"), 
              when(DSL.field("msg.type").eq(1), 10, DSL.field( "{0}", String.class, "msg.maxLength").as("message)
           .from(tableName)
           .fetchOneInto(Message.class);
}

但....

when(DSL.field("msg.type").eq(1), 10, DSL.field( "{0}", String.class, "msg.maxLength").as("message)

jooq 是字段 msg.maxLength ...不接受

也如此

情况如何,何时,iif 插入字段列数据?

标签: javamysqljooq

解决方案


使用代码生成器

我假设您在此示例中没有使用代码生成器,因为您希望根据表名使列引用动态化。

有可能在您的表上生成通用接口,这将对两种表类型进行抽象。此外,Table.rename(String)在这些表上生成了一些方法,这些方法允许重命名表MESSAGE_TABLE_1.rename("message_table_2")。因此,您的查询将如下所示:

public Message getMessageTest(String tableName) {
    MessageTable1 msg = MESSAGE_TABLE_1.rename(tableName);

    return roDslContext
        .select(
            msg.INDEX,
            left(msg.MESSAGE, if_(msg.TYPE.eq(1), val(10), msg.MAX_LENGTH))
        )
        .from(msg)
        .fetchOneInto(Message.class);
}

与往常一样,这是假设以下静态导入:

import static org.jooq.impl.DSL.*;

实际问题

您似乎正在尝试使用普通 SQL 模板构造字段引用。msg.index您为via做的正确DSL.field("msg.index"),但不知何故绊倒了msg.message. 这没有意义:

field("{0}", String.class, "msg.message");

使用模板时,占位符{0}需要替换为QueryPart实例。您不能只传递 a String(这将被解释为绑定值)。您在这里要做的是以下任何一项:

// If you really need templating, though here, you don't:
field("{0}", String.class, name("msg", "message"));

// Instead, just do this, if you want quoted names:
field(name("msg", "message"), String.class);

// Or this, if you don't care about quoting the name
field("msg.message", String.class);

推荐阅读