2016-06-06 6 views
1

Meine Frage zum Schreiben von Abfrage in jooq dsl.JOOQ: Typklasse org.jooq.impl.SelectImpl wird in Dialekt nicht unterstützt DEFAULT

Ich habe eine Liste von Client-Attributen in einer Oracle-Datenbank gespeichert.

Tabellenstruktur folgt:

  • CLIENT_ATTRIBUTE_DICT (ID, CODE, DEFAULT_VALUE) - Liste aller möglichen Attribute
  • CLIENT_ATTRIBUTE (attribute_id, CLIENT_ID, Wert) - Attribute Werte für verschiedene Clients

Ich versuche, Werte aller vorhandenen Attribute (in dict) für einen bestimmten Client auszuwählen:

Wenn vorhanden Zeile in CLIENT_ATTRIBUTE mit bestimmten clientId als Attributwert = CLIENT_ATTRIBUTE.VALUE sonst CLIENT_ATTRIBUTE_DICT.DEFAULT_VALUE

Meine Abfrage in SQL (funktioniert):

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; 

Meine Anfrage in 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); 

Wenn jOOQ Abfrage läuft es schlägt mit Fehlermeldung:

verursacht durch: Typ Klasse org.jooq.i mpl.SelectImpl ist nicht im Dialekt STANDARD unterstützt

bei org.jooq.impl.DefaultDataType.getDataType (DefaultDataType.java:757) ~ [na: na]
bei org.jooq.impl.DefaultDataType.getDataType (DefaultDataType.java:704) ~ [na: na]
bei org.jooq.impl.DSL.getDataType (DSL.java:14378) ~ [na: na]
bei org.jooq.impl.DSL.val (DSL.java:12766) ~ [na: na]
bei org.jooq.impl.Utils.field (Utils.java:802) ~ [na: na]
bei org.jooq.impl.DSL.nvl (DSL.java:8403) ~ [na: na]

Was mache ich falsch?

UPD jOOQ Version 3.7.2

+0

können Sie den vollständigen Stack-Trace (oder zumindest die relevanten Teile) Paste fixiert werden, um zu sehen, wo die Ausnahme ausgelöst wird? Auch: Welche jOOQ-Version verwendest du? –

+0

Hallo, Lukas! Ich habe meine Frage aktualisiert. –

Antwort

0

Der Fehler ist zweifach.

  1. Ihre API-Nutzung wird derzeit nicht unterstützt (jOOQ derzeit nicht akzeptiert Select Typen in der nvl()-Funktion). Schreiben Sie stattdessen:

    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 (oder besser gesagt, der Java-Compiler) kann diese API misusage nicht erkennen, da die nvl() API in einer Art und Weise überlastet ist, die immer kompiliert. Dies ist Ausgabe https://github.com/jOOQ/jOOQ/issues/5340 und wird in einer zukünftigen Version (wahrscheinlich jOOQ 3,9)

+0

Danke für die Hilfe, es funktioniert gut! –

0

ich Abhilfe gefunden.

Erste rewrited I SQL-Abfrage:

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; 

als ich meine Abfrage in jOOQ dsl ausdrücken:

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); 

In logs fand ich ein wenig SQL-Abfrage durch jook erzeugt geändert:

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; 

Irgendwelche Ideen, wie ich meine Workaround verbessern kann, werden geschätzt.