JOOQ:方言DEFAULT中不支持类型类org.joq.impl.SelectImpl



我关于在jooq-dsl中编写查询的问题。

我在Oracle数据库中存储了一些客户端属性列表。

表格结构如下:

  • CLIENT_ATTRIBUTE_DICT(ID、CODE、DEFAULT_VALUE)-所有可能属性的列表
  • CLIENT_ATTRIBUTE(ATTRIBUTE_ID、CLIENT_ID、VALUE)-不同客户端的属性值

我正在尝试为给定客户端选择所有现有属性的值(在dict中):

如果CLIENT_ATTRIBUTE中存在具有给定clientId的行,则属性值=CLIENT_ATTRIBUTE.VALUEelseCLIENT_ATTRIBUTE_DICT.DEFAULT_VALUE

我在SQL中的查询(运行良好):

SELECT d.code,
NVL 
(
(
SELECT value
FROM CLIENT_ATTRIBUTE a
WHERE a.ATTRIBUTE_ID = d.id
AND a.CLIENT_ID      = 1 
),
( 
SELECT DEFAULT_VALUE 
FROM CLIENT_ATTRIBUTE_DICT dd 
WHERE dd.id=d.id
) 
) value
FROM CLIENT_ATTRIBUTE_DICT d;

我在Jooq dsl:中的查询

ClientAttributeDictTable dict = CLIENT_ATTRIBUTE_DICT.as("d");
Map<String, String> attributes = 
dsl.select(
dict.CODE,
DSL.nvl(
dsl.select(CLIENT_ATTRIBUTE.VALUE)
.from(CLIENT_ATTRIBUTE)
.where(
CLIENT_ATTRIBUTE.ATTRIBUTE_ID.eq(dict.ID),
CLIENT_ATTRIBUTE.CLIENT_ID.eq(clientId)
),
dsl.select(CLIENT_ATTRIBUTE_DICT.DEFAULT_VALUE)
.from(CLIENT_ATTRIBUTE_DICT)
.where(CLIENT_ATTRIBUTE_DICT.ID.eq(dict.ID))
).as("value")
).from(dict)
.fetchMap(String.class, String.class);

当jooq查询运行时失败,并显示错误消息:

由以下原因引起:方言DEFAULT 中不支持Type类org.jooq.impl.SelectImpl

在org.jooq.impl.DefaultDataType.getDataType(DefaultDataType.java:757)~[na:na]
在org.joo.impl.DefaultDataType.get-DataType(DefaultDataType.java:704.Utils.field(Utils.java:802)~[na:na]
在org.jooq.impl.DSL.nvl(DSL.java:8403)~[na:na]

我做错了什么?

UPDJOOQ版本3.7.2

错误有两个方面。

  1. 当前不支持您使用API(jOOQ当前不接受nvl()函数中的Select类型)。改为写这个:

    DSL.nvl(
    DSL.field(dsl.select(CLIENT_ATTRIBUTE.VALUE)
    //  ^^^^^^^^^ explicitly wrap the Select in a Field 
    .from(CLIENT_ATTRIBUTE)
    .where(
    CLIENT_ATTRIBUTE.ATTRIBUTE_ID.eq(dict.ID),
    CLIENT_ATTRIBUTE.CLIENT_ID.eq(clientId))),
    DSL.field(dsl.select(CLIENT_ATTRIBUTE_DICT.DEFAULT_VALUE)
    //  ^^^^^^^^^ explicitly wrap the Select in a Field
    .from(CLIENT_ATTRIBUTE_DICT)
    .where(CLIENT_ATTRIBUTE_DICT.ID.eq(dict.ID)))
    ).as("value")
    
  2. jOOQ(或者更确切地说,Java编译器)无法检测到这种API误用,因为nvl()API总是以编译的方式过载。这是个问题https://github.com/jOOQ/jOOQ/issues/5340并将在未来的版本(可能是jOOQ 3.9)中进行修复

我找到了解决方法。

首先我重写了SQL查询:

SELECT D.CODE, NVL(S.VALUE, D.DEFAULT_VALUE) ATTRIBUTE_VALUE
FROM CLIENT_ATTRIBUTE_DICT D
LEFT JOIN
(SELECT DD.ID,
A.VALUE
FROM CLIENT_ATTRIBUTE_DICT DD
JOIN CLIENT_ATTRIBUTE A
ON A.ATTRIBUTE_ID = DD.ID
WHERE A.CLIENT_ID = 1
) S ON S.ID       = D.ID;

然后我在JOOQ dsl:中表达我的疑问

String ID_FIELD_NAME    = "ID";
String VALUE_FIELD_NAME = "VALUE"
ClientAttributeDictTable DICT_ATTRIBUTES = CLIENT_ATTRIBUTE_DICT.as("D");
Table<Record2<Long, String>> EXISTING_ATTRIBUTES =
dsl.select(CLIENT_ATTRIBUTE_DICT.ID, CLIENT_ATTRIBUTE.VALUE)
.from(CLIENT_ATTRIBUTE_DICT)
.join(CLIENT_ATTRIBUTE)
.on(CLIENT_ATTRIBUTE.ATTRIBUTE_ID.eq(CLIENT_ATTRIBUTE_DICT.ID))
.where(CLIENT_ATTRIBUTE.CLIENT_ID.eq(clientId))
.asTable("S", ID_FIELD_NAME, VALUE_FIELD_NAME);
Field<String> ATTRIBUTE_VALUE_FIELD = 
nvl(
EXISTING_ATTRIBUTES.field(VALUE_FIELD_NAME, String.class),
DICT_ATTRIBUTES.DEFAULT_VALUE
).as("ATTRIBUTE_VALUE");
Map<String,String> attributes = 
dsl.select(DICT_ATTRIBUTES.CODE, ATTRIBUTE_VALUE_FIELD)
.from(DICT_ATTRIBUTES)
.leftJoin(EXISTING_ATTRIBUTES)
.on(DICT_ATTRIBUTES.ID
.eq(EXISTING_ATTRIBUTES.field(ID_FIELD_NAME, Long.class))
)
.fetchMap(DICT_ATTRIBUTES.CODE, ATTRIBUTE_VALUE_FIELD); 

在日志中,我发现JOOK生成的SQL查询有一点变化:

SELECT D.CODE,
NVL(S.VALUE, D.DEFAULT_VALUE) ATTRIBUTE_VALUE
FROM CLIENT_ATTRIBUTE_DICT D
LEFT OUTER JOIN (
(SELECT NULL ID, NULL VALUE FROM dual WHERE 1 = 0
)
UNION ALL
(SELECT CLIENT_ATTRIBUTE_DICT.ID,
CLIENT_ATTRIBUTE.VALUE
FROM CLIENT_ATTRIBUTE_DICT
JOIN CLIENT_ATTRIBUTE
ON CLIENT_ATTRIBUTE.ATTRIBUTE_ID = CLIENT_ATTRIBUTE_DICT.ID
WHERE CLIENT_ATTRIBUTE.CLIENT_ID = 141
)
) S ON D.ID = S.ID;

任何关于如何改进我的变通方法的想法都将不胜感激。

相关内容

最新更新