Domanda

Ho un problema con Hibernate che genera SQL non valido.Nello specifico, mescolare e abbinare join impliciti ed espliciti.Questo sembra essere un bug aperto.

Tuttavia, non ne sono sicuro Perché questo è un SQL non valido.Ho creato un piccolo esempio di giocattolo che genera la stessa eccezione di sintassi.

Schema

CREATE TABLE Employee (
    employeeID INT,
    name VARCHAR(255),
    managerEmployeeID INT   
)

Dati

INSERT INTO Employee (employeeID, name) VALUES (1, 'Gary')
INSERT INTO Employee (employeeID, name, managerEmployeeID) VALUES (2, 'Bob', 1)

SQL funzionante

Entrambe queste query funzionano.Mi rendo conto che esiste un prodotto cartesiano;è intenzionale.

ISCRIVITI esplicito:

SELECT e1.name,
       e2.name,
       e1Manager.name
  FROM Employee e1
 CROSS JOIN Employee e2
 INNER JOIN Employee e1Manager
    ON e1.managerEmployeeID = e1Manager.employeeID

ISCRIVITI implicitamente:

SELECT e1.name,
       e2.name,
       e1Manager.name
  FROM Employee e1,
       Employee e2,
       Employee e1Manager
 WHERE e1.managerEmployeeID = e1Manager.employeeID

SQL non valido

Questa query NON funziona su MSSQL 2000/2008 o MySQL:

SELECT e1.name, 
       e2.name, 
       e1Manager.name
  FROM Employee e1,
       Employee e2
 INNER JOIN Employee e1Manager 
    ON e1.managerEmployeeID = e1Manager.employeeID

In MS2000, ottengo l'errore:

Il prefisso della colonna 'E1' non corrisponde con un nome di tabella o un nome alias utilizzato nella query.

In MySQL, l'errore è:

Colonna sconosciuta "E1.ManagerEmployeeid" in "On Clause".

Domande)

  1. Perché questa sintassi non è valida?
  2. Bonus: Esiste un modo per forzare Hibernate a utilizzare solo JOIN espliciti?

È stato utile?

Soluzione

Il risultato è un errore perché, secondo lo standard SQL, il file JOIN la parola chiave ha una precedenza maggiore rispetto alla virgola.Il punto critico è che gli alias di tabella non sono utilizzabili fino a quando Dopo la tabella corrispondente è stata valutata nel FROM clausola.

Quindi quando fai riferimento e1 nel tuo JOIN...ON espressione, e1 non esiste ancora.

Per favore, resta in attesa mentre cerco Hibernate e scopri se riesci a convincerlo a usarlo JOIN in tutti i casi.


Hmm.Tutto su Hibernate.org sembra reindirizzare a jboss.org.Quindi non c'è modo di leggere la documentazione HQL online in questo momento.Sono sicuro che alla fine capiranno il loro nome.

Altri suggerimenti

Questo potrebbe essere un po' fuori tema, perché non riguarda affatto l'ibernazione, ma il commento di Bill Karwin mi ha davvero aperto gli occhi.Invece di scrivere prima l'unione implicita, è necessario eseguire prima l'unione esplicita.Questa sintassi è particolarmente interessante se sono presenti più join impliciti.

Controlla il seguente esempio in MS SQL.Non tutti i contatti hanno un codice paese definito, ma tutti i contatti hanno un attributo val che verrà cercato nella tabella Tbl.Quindi la soluzione intuitiva non funzionerà:

SELECT * FROM 
contacts, Tbl
LEFT OUTER JOIN country ON CtryCod = country.CtryCod 
WHERE val = Tbl.val

Invece potresti preferire utilizzare la seguente sintassi:

SELECT * FROM 
contacts LEFT OUTER JOIN country ON CtryCod = country.CtryCod, 
Tbl
WHERE val = Tbl.val

Anche PostgreSQL dà un errore:

ERROR:  invalid reference to FROM-clause entry for table "e1"
LINE 7:     ON e1.managerEmployeeID = e1Manager.employeeID;
               ^
HINT:  There is an entry for table "e1", but it cannot be referenced from this part of the query.

Penso che il problema sia che quando unisci due tabelle aeb (e2 ed e1Manager in questo caso) puoi fare riferimento solo a quelle due tabelle nella clausola "ON".Quindi puoi fare riferimento a e2 ed e1Manager in questa clausola ON, ma non a e1.

Penso che questo si estenda in modo tale che se hai una catena di istruzioni "JOIN", puoi fare riferimento ad altre tabelle nella stessa catena nelle clausole "ON", ma non puoi incrociare un ",".Quindi è consentito qualcosa come "a JOIN b ON a.a_id = b.a_id JOIN c ON c.b_id = b.b_id AND c.a_id = a.a_id".

Qual è l'HQL che stai utilizzando per produrre questo SQL?Qualcosa come "seleziona e1.name, e2.name, e1.manager.name da Employee e1, Employee e2"?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top