当我尝试构建JPQL连接查询时,为什么会出现无效路径?

时间:2014-09-26 15:49:42

标签: hibernate jpa jpa-2.0 inner-join jpql

我正在使用JPA 2.1,Hibernate 4.3.6.Final和MySQL 5.5.37。如何编写进行连接的JPQL查询?我正在尝试下面

    final String jpqlQuery = "SELECT m FROM Message m LEFT JOIN MessageReadDate mr " + 
            " INNER JOIN m.group g " + 
            " LEFT JOIN g.classroom c " + 
            " LEFT JOIN c.ROSTER u WHERE " + 
            " u.USER = :recipient AND " + 
            " u.ENABLED = 1 AND " + 
            " c.ENABLED = 1 AND " + 
            " g.NAME = '' AND " +
            " m.author <> :author";
    Query query = m_entityManager.createQuery(jpqlQuery);

但得到错误“加入的路径! ...路径无效:&#39; g.classroom&#39;“。

org.hibernate.hql.internal.ast.ErrorCounter -  Path expected for join!
 Path expected for join!
        at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromJoinElement(HqlSqlWalker.java:379)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.joinElement(HqlSqlBaseWalker.java:3903)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3689)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3567)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:708)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:564)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:301)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:249)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:278)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:206)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:158)
        at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:126)
        at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:88)
        at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:167)
        at org.hibernate.internal.AbstractSessionImpl.getHQLQueryPlan(AbstractSessionImpl.java:301)
        at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:236)
        at org.hibernate.internal.SessionImpl.createQuery(SessionImpl.java:1800)
        at org.hibernate.jpa.spi.AbstractEntityManagerImpl.createQuery(AbstractEntityManagerImpl.java:328)
        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.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:240)
        at com.sun.proxy.$Proxy68.createQuery(Unknown Source)
        at org.mainco.subco.messaging.repo.MessageDaoImpl.getUnreadClassAnnouncements(MessageDaoImpl.java:161)
        at org.mainco.subco.messaging.repo.MessageDaoImpl.getUnreadMessages(MessageDaoImpl.java:140)
        at org.mainco.subco.messaging.repo.MessageDaoIT.testGetUnreadMessages(MessageDaoIT.java:125)
        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:83)
        at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
        at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
        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:71)
        at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
        at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
        at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
        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)
    [ERROR]: org.hibernate.hql.internal.ast.ErrorCounter -  Invalid path: 'g.classroom'
    [ERROR]: org.hibernate.hql.internal.ast.ErrorCounter -  Invalid path: 'g.classroom'
     Invalid path: 'g.classroom'
        at org.hibernate.hql.internal.ast.util.LiteralProcessor.lookupConstant(LiteralProcessor.java:129)
        at org.hibernate.hql.internal.ast.tree.DotNode.resolve(DotNode.java:225)
        at org.hibernate.hql.internal.ast.tree.FromReferenceNode.resolve(FromReferenceNode.java:126)
        at org.hibernate.hql.internal.ast.HqlSqlWalker.createFromJoinElement(HqlSqlWalker.java:387)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.joinElement(HqlSqlBaseWalker.java:3903)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElement(HqlSqlBaseWalker.java:3689)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromElementList(HqlSqlBaseWalker.java:3567)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.fromClause(HqlSqlBaseWalker.java:708)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.query(HqlSqlBaseWalker.java:564)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.selectStatement(HqlSqlBaseWalker.java:301)
        at org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.statement(HqlSqlBaseWalker.java:249)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.analyze(QueryTranslatorImpl.java:278)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:206)
        at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:158)
    …

我的消息实体如下......

@Entity
@Table(name = "msg")
public class Message
{

    @Id
    @NotNull
    @GeneratedValue(generator = "uuid-strategy")
    @Column(name = "ID")
    private String id;

    @Column(name = "MESSAGE", columnDefinition="LONGTEXT")
    private String message;

    @ManyToOne
    @JoinColumn(name = "GROUP_ID", nullable = false, updatable = true)
    private Group group;

我的团体实体如下......

@Entity
@Table(name = "msg_group")
public class Group
{
    @Id
    @NotNull
    @GeneratedValue(generator = "uuid-strategy")
    @Column(name = "ID")
    private String id;

    @Column(name = "NAME")
    private String name;

    @ManyToOne
    @JoinColumn(name = "CLASSROOM_ID", nullable = true, updatable = true)
    private Classroom classroom;

那为什么我不能引用“课堂”属性呢?

谢谢, - 戴夫

2 个答案:

答案 0 :(得分:3)

如果你想在HQL中使用JOIN,那么你只能在From子句中提到的类的属性上使用它。

这意味着,在这个特定的行中:

SELECT m FROM Message m LEFT JOIN MessageReadDate mr 

hibernate检查MessageReadDate是否被定义为Message类中的属性,该属性在此处被视为路径。由于没有任何名为MessageReadDate的内容,因此会引发异常。

要解决此问题,请在MessageReadDate课程中为Message课程添加所需的媒体资源,让我们说mrd(您可以将您的关系作为一对一或在 - to-many或etc)然后使用这样的查询:

SELECT m FROM Message m LEFT JOIN m.mrd

通过这种方式,我们告诉hibernate如何将消息与其相应的属性连接起来,因此连接的路径对于休眠是明确的。

答案 1 :(得分:2)

Hibernate报告的问题在第一行:

final String jpqlQuery = "SELECT m FROM Message m LEFT JOIN MessageReadDate mr "...
LEFT JOIN语句中的

。在 hql 中,JOIN必须表达关系,例如

LEFT JOIN m.MessageReadDate mr // the m is referencing the MessageReadDate

如果没有参考,我们仍然可以使用它,但使用笛卡尔积

FROM Message m, MessageReadDate mr

在这种情况下,将发布CROSS JOIN

见:

小引用:

  

可以出现多个类,从而产生笛卡尔积或“#34; cross&#34;加入。

from Formula, Parameter
from Formula as form, Parameter as param
  

您还可以使用连接将别名分配给关联实体或值集合的元素。例如:

from Cat as cat
    inner join cat.mate as mate