3

Suppose that I have the following HBM mapping:

<class name="Student" table="student">
    <set name="classes" table="student_classes" cascade="none">
        <key column="studentId" />
        <many-to-many column="classId" class="org.myCompany.myClass" />
    </set>
</class>

In my student POJO, I have the following:

private Set<myClass> classes = new HashSet<myClass>();
public Set<myClass> getClasses() { return classes; }
public void setClasses(Set<myClass> classes) { this.classes = classes; }

I want to run the following HQL query:

select count(*) from Student where classes.className = :myClassName

However, hibernate throws the following exception:

ERROR [service-j2ee-4] PARSER.reportError(33) |  Invalid path: 'classes.className'
ERROR [service-j2ee-4] PARSER.reportError(33) | <AST>:0:0: unexpected end of subtree
ERROR [service-j2ee-4] PARSER.reportError(33) |  left-hand operand of a binary operator was null
org.hibernate.hql.ast.QuerySyntaxException: Invalid path: 'classes.className' [select count(*) from Student where classes.className = :myClassName  and  1=1]

Is it possible to run a hibernate query which returns results based on properties of a Set? In the above example, we might want to query for all students who are taking 'Algebra I' or another course?

Edit: I enabled the appropriate debug mode to get Hibernate to output it's actual SQL query and here is the query that it generates:

select count(*) as col_0_0_ 
from student student0_, student_classes student1_, classes student2_

where student0_.studentId=student1_.studentId and student1_.classId=student2_.classId and student2_.className LIKE 'algebra' and 1=1;
David
  • 299
  • 2
  • 6
  • 16

2 Answers2

3
select count(s.id) from Student s
inner join s.classes clazz
where clazz.className = :myClassName

Here's how I reason about it : classes is a Set, and thus doesn't have a className property. Once you traverse the relationship using a join, you get an alias on the myClass entity, which has a className property.

Note: classes in Java should always begin with an upper-case letter. Rename myClass to MyClass.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Actually HQL doesn't have good inner join support (see http://www.coderanch.com/t/218169/ORM/java/Inner-Join-HQL). My Set contains objects of type myClass which does have a property of className. I want to query based on that className property (not on a property of the set itself). – David May 03 '11 at 14:13
  • Yes it has good support. Have you read the answers to the post you sent. You just don't have to specify the on clause of the join as in SQL, because the mapping already defines how the tables are linked together. Have you tried my query? Read http://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#queryhql-joins – JB Nizet May 03 '11 at 14:24
  • I just tried your query and got the error: "Path expected for join! Invalid path: clazz.className" – David May 03 '11 at 14:36
  • @David: you accepted my answer. Why did you have the "Path expected for join" error? – JB Nizet May 03 '11 at 15:30
0

Is it possible to run a hibernatequery which returns results based on properties of a Set?

Yes!

In the above example

Are we sure org.myCompany.myClass ha a className property? If yes, try something like this select count(*) from Student s inner join Classes c where c.className = :myClassName

bpgergo
  • 15,669
  • 5
  • 44
  • 68
  • When I looked more closely at my actual query, I was missing the "c." alias before className (which was throwing the error). However, I now get 0 results from the query (instead of the expected number of results. – David May 03 '11 at 14:16
  • I was getting zero results because I needed to add LIKE '%string%' to my query – David May 03 '11 at 14:29