[
https://hibernate.onjira.com/browse/HHH-5396?page=com.atlassian.jira.plug...
]
Yannick Lazzari commented on HHH-5396:
--------------------------------------
Any update on the progress of that one? As of version 4.1.2.Final, nothing has changed.
Using the keyword in upper case (e.g. 'KEY(t)') just passes through to the SQL
statement and obviously the RDBMS complains (Oracle in my case). When using the keyword
in lower case, I get the following stacktrace. In the meantime, the only solution I found
to query the relations properly is to refrain from using Map relations, simply use other
collections and add utility methods to manipulate the collections as Maps when needed.
Works, but the Map collection is elegant and useful sometimes, especially for
multi-lingual patterns (exactly the one described in the bug report).
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node:
[from Order t inner join t.details t2 where key(t2) = 'EN' order by t2.title]
at
org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:54)
~[hibernate-core-4.1.2.Final.jar:4.1.2.Final]
at
org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:47)
~[hibernate-core-4.1.2.Final.jar:4.1.2.Final]
at org.hibernate.hql.internal.ast.ErrorCounter.throwQueryException(ErrorCounter.java:79)
~[hibernate-core-4.1.2.Final.jar:4.1.2.Final]
at
org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:255)
~[hibernate-core-4.1.2.Final.jar:4.1.2.Final]
at
org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:183)
~[hibernate-core-4.1.2.Final.jar:4.1.2.Final]
at
org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:136)
~[hibernate-core-4.1.2.Final.jar:4.1.2.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:105)
~[hibernate-core-4.1.2.Final.jar:4.1.2.Final]
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:80)
~[hibernate-core-4.1.2.Final.jar:4.1.2.Final]
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:168)
~[hibernate-core-4.1.2.Final.jar:4.1.2.Final]
at
org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:216)
~[hibernate-core-4.1.2.Final.jar:4.1.2.Final]
at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:194)
~[hibernate-core-4.1.2.Final.jar:4.1.2.Final]
at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1703)
~[hibernate-core-4.1.2.Final.jar:4.1.2.Final]
at
org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:286)
~[hibernate-entitymanager-4.1.2.Final.jar:4.1.2.Final]
JPQL KEY() and VALUE() not implemented
--------------------------------------
Key: HHH-5396
URL:
https://hibernate.onjira.com/browse/HHH-5396
Project: Hibernate ORM
Issue Type: Bug
Affects Versions: 3.5.3
Environment: Hibernate 3.5.3, PostgreSQL 8.4.3
Reporter: Harald Wellmann
The KEY() and VALUE() operators for persistent maps do not seem to be implemented in
Hibernate.
E.g. consider the query
{code}
select m.text from MultilingualString s join s.map m where key(m) = 'de'
{code}
given the following classes and mappings.
{code:java}
@Embeddable
public class LocalizedString {
private String language;
@Column(name = "_text")
private String text;
}
@Entity
@Table(schema = "jpa", name = "multilingual_string")
public class MultilingualString {
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Column(name = "string_id")
private long id;
@ElementCollection(fetch=FetchType.EAGER)
@MapKeyColumn(name = "language_key", insertable = false, updatable =
false)
@CollectionTable(schema = "jpa", name =
"multilingual_string_map", joinColumns = @JoinColumn(name =
"string_id"))
private Map<String, LocalizedString> map = new HashMap<String,
LocalizedString>();
}
{code}
(Note that these mappings are similar to but slightly different from the ones I used in
HHH-5393. This time the map key column has a different name, creating a redundant column I
would have liked to avoid. That way, Hibernate is at least happy about the mapping.)
Running the query, I get the following exception:
java.lang.IllegalArgumentException: org.hibernate.hql.ast.QuerySyntaxException:
unexpected AST node: [select m.text from de.myjourney.model.media.MultilingualString s
join s.map m where key(m) = 'de']
at
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1222)
at
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168)
at
org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:292)
at
de.myjourney.model.test.MultilingualStringTest.createGerman(MultilingualStringTest.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.hibernate.hql.ast.QuerySyntaxException: unexpected AST node: [select
m.text from de.myjourney.model.media.MultilingualString s join s.map m where key(m) =
'de']
at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:54)
at org.hibernate.hql.ast.QuerySyntaxException.convert(QuerySyntaxException.java:47)
at org.hibernate.hql.ast.ErrorCounter.throwQueryException(ErrorCounter.java:82)
at org.hibernate.hql.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:261)
at org.hibernate.hql.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:185)
at org.hibernate.hql.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:136)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:101)
at org.hibernate.engine.query.HQLQueryPlan.<init>(HQLQueryPlan.java:80)
at org.hibernate.engine.query.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:98)
at org.hibernate.impl.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:156)
at org.hibernate.impl.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:135)
at org.hibernate.impl.SessionImpl.createQuery(SessionImpl.java:1760)
at
org.hibernate.ejb.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:277)
... 23 more
Using upper-case 'KEY(m)', the exception is different:
javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException:
could not execute query
at
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1235)
at
org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1168)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:250)
at
de.myjourney.model.test.MultilingualStringTest.createGerman(MultilingualStringTest.java:36)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at
org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:46)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at
org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: org.hibernate.exception.SQLGrammarException: could not execute query
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:92)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
at org.hibernate.loader.Loader.doList(Loader.java:2297)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2172)
at org.hibernate.loader.Loader.list(Loader.java:2167)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:448)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1258)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:241)
... 23 more
Caused by: org.postgresql.util.PSQLException: FEHLER: Funktion key(bigint) existiert
nicht
Hint: Keine Funktion stimmt mit dem angegebenen Namen und den Argumenttypen überein.
Sie müssen möglicherweise ausdrückliche Typumwandlungen hinzufügen.
Position: 161
at
org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2062)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1795)
at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:257)
at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:479)
at
org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:367)
at
org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:271)
at org.hibernate.jdbc.AbstractBatcher.getResultSet(AbstractBatcher.java:208)
at org.hibernate.loader.Loader.getResultSet(Loader.java:1849)
at org.hibernate.loader.Loader.doQuery(Loader.java:718)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
at org.hibernate.loader.Loader.doList(Loader.java:2294)
... 31 more
(The message from PostgreSQL means "Function key(bigint) does not exist".)
I had a look at the ANTLR grammar for the query parser a while ago (which may have been
before 3.5.3), and as far as I could make out, key() and value() are only recognized as
lower case keywords, and while the parser accepts the syntax, it fails to generate any
appropriate actions.
The stack traces are up-to-date though, I just ran my test cases on Hibernate 3.5.3.
--
This message is automatically generated by JIRA.
For more information on JIRA, see:
http://www.atlassian.com/software/jira