JPA : MapPath containsKey not working for hibernate

Bug #656199 reported by bouil
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
Querydsl
Fix Released
Medium
Unassigned

Bug Description

If have a Transaction class :

@Entity
public class Transaction implements Identifiable {

    private static final long serialVersionUID = 5732269201608146506L;

    @Id
    @GeneratedValue
    private int id;

    @Column
    private Date date;

    @Column
    private String description;

    @CollectionOfElements(fetch = FetchType.EAGER)
    @JoinTable(name = "moves", joinColumns = @JoinColumn(name = "transactionID"))
    @Cascade(value = org.hibernate.annotations.CascadeType.DELETE_ORPHAN)
    @org.hibernate.annotations.MapKey(columns = { @Column(name = "accountId") })
    @Column(name = "amount")
    private Map<Account, BigDecimal> moves = new HashMap<Account, BigDecimal>();

   ....

}

and an Account class :

@Entity
public class Account implements Identifiable {

    private static final long serialVersionUID = 2862850054100616066L;

    @Column
    @Id
    @GeneratedValue
    private int id;

    ....
}

I'm trying to do the following query :

public BigDecimal getBalance(Account bankAccount) {
        QTransaction transaction = QTransaction.transaction;
        JPQLQuery q = new HibernateQuery(getHibernateTemplate().getSessionFactory()
                .getCurrentSession()).from(transaction);
        List<Transaction> transactions = q.from(transaction)
                .where(transaction.moves.containsKey(bankAccount))
                .list(transaction);

        return computeSum(bankAccount, transactions);
    }

and i got the following stack trace :

org.hibernate.hql.ast.QuerySyntaxException: unexpected AST node: ( near line 3, column 18 [select transaction
from myapp.comptes.b.Transaction transaction
where containsKey(transaction.moves,:a1)]
 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 com.mysema.query.jpa.hibernate.DefaultSessionHolder.createQuery(DefaultSessionHolder.java:30)
 at com.mysema.query.jpa.hibernate.AbstractHibernateQuery.createQuery(AbstractHibernateQuery.java:126)
 at com.mysema.query.jpa.hibernate.AbstractHibernateQuery.createQuery(AbstractHibernateQuery.java:93)
 at com.mysema.query.jpa.hibernate.AbstractHibernateQuery.list(AbstractHibernateQuery.java:207)
 at myapp.comptes.b.AccountManagerQDSLImpl.getBalance(AccountManagerQDSLImpl.java:56)
 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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
 at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
 at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
 at $Proxy25.getBalance(Unknown Source)
 at myapp.comptes.web.AppTest.testEnterTransactionAndBalanceIsCorrect(AppTest.java:116)
 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.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
 at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:82)
 at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:240)
 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.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
 at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
 at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:180)
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
 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)

When using plain HQL query, i used the index() HQL method, and not the containsKey method it seems QueryDSL wants to use.

    public BigDecimal getBalance(Account bankAccount) {
        List<Transaction> transactions = getHibernateTemplate()
                .find("select t from Transaction t join t.moves m where index(m) = ?",
                        bankAccount);
        return computeSum(bankAccount, transactions);
    }

Revision history for this message
bouil (bouil) wrote :

FYI, i just tested with Hibernate as an JPA provider, and i got the same error (my previous test was using hibernate api)

Revision history for this message
Timo Westkämper (timo-westkamper) wrote :

Thanks for the bug report. I just added support for containsKey and containsValue for Hibernate. It was missing before, since JPQL doesn't seem to support it directly

The serialization patterns are

  CONTAINS_KEY -> RHS in indices(LHS)
  CONTAINS_VALUE -> RHS in elements(LHS)

Changed in querydsl:
status: New → Fix Committed
importance: Undecided → Medium
Revision history for this message
bouil (bouil) wrote :

Very fast fix, nice !

Revision history for this message
bouil (bouil) wrote :

I was about to build from source, but somethings seems to be strange in the pom. xml files

The current stable version is 2.0.1, and the pom has 2.0.1-SNAPSHOT. Shouldn't be 2.0.2-SNAPSHOT ?

Revision history for this message
Timo Westkämper (timo-westkamper) wrote :

When going from the release to snapshot mode in the version we keep the base version, since we are not always sure how to name the next version.

Revision history for this message
Timo Westkämper (timo-westkamper) wrote :

I am aware that this is not standard practice, but Maven doesn't mandate any naming scheme for versions.

Revision history for this message
bouil (bouil) wrote :

Ok, it's not a big deal. I was just surprised at first look.
Thanks

summary: - MapPath containsKey not working for hibernate
+ JPA : MapPath containsKey not working for hibernate
Revision history for this message
Timo Westkämper (timo-westkamper) wrote :

Released in 2.0.2

Changed in querydsl:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.