views:

109

answers:

2

I try to generate a HQL query that include user with a empty appoinment collections(mapped by OneToMany):

SELECT u FROM User u JOIN u.appointments uas WHERE u.status = 1 AND (uas.time.end < :date OR size(uas) = 0)

I tries it on several manners (NOT EXIST ELEMENT(), IS NULL) also see: http://stackoverflow.com/questions/1105011/how-to-check-if-the-collection-is-empty-in-nhibernate-hql/1105057#1105057 (This doesn't work for me)

but still not the result I want to see or some error in HQL or SQL SERVER

Note:

the query without the JOIN works:

"FROM User u WHERE u.status = 1 AND size(u.appointments) = 0"

Solved

Another JOIN solved the problem:

SELECT u FROM User u LEFT JOIN u.appointments pas1 LEFT JOIN pas1.slot t WHERE u.status = 1 AND t.end <= :date1 OR t.end IS NULL ORDER BY u.name asc
+1  A: 

Using IS EMPTY should work (I would favor a JPQL syntax):

SELECT u FROM User u WHERE u.status = 1 AND u.appointments IS EMPTY

If it doesn't, please show the generated SQL.

References

  • Hibernate Core Reference Guide
  • JPA 1.0 specification
    • Section 4.6.11 "Empty Collection Comparison Expressions"
Pascal Thivent
unfortunately ' "FROM User u JOIN u.appointments uas WHERE u.status = 1 AND uas is empty" ' doesn't work. It gives me no users. And there are a lot of users without appointments
michel
@michel That's not the query I suggest (was still editing).
Pascal Thivent
mm your suggestion works but i needed that JOIN. I'm looking for the method to use the size or is empty in combination with the Join, Thx for your support
michel
@michel Why do you need the join? Your query with the JOIN will only return users with matching values in the join condition (i.e. users *with* appointments).
Pascal Thivent
@PascalI need it because I need all users with appointments not older than 10 days for example and with no appointments
michel
@michel You might need a LEFT JOIN then, not an INNER JOIN. Your current query (without the condition on the appointments size) is not doing what you want.
Pascal Thivent
@Pascalsomething like this:--> SELECT u FROM User u LEFT JOIN u.appointments uas WHERE u.status = 1 AND (uas.slot.end <= :date1 OR size(u.appointments) = 0 ) ORDER BY u.name asc <-- This gives me only the users with appointments and --> SELECT u FROM User u LEFT JOIN u.appointments uas WHERE u.status = 1 AND (uas.slot.end <= :date1 OR size(uas) = 0 ) ORDER BY u.name asc <-- gives me the error: "java.lang.StringIndexOutOfBoundsException: String index out of range: -5" BTW: when using "IS EMPTY" no STringIndexOutOfBoundsException but only 2 users instead of thousands
michel
@michel It's hard to discuss this in a comment box but do you agree that `SELECT u FROM User u JOIN u.appointments uas WHERE u.status = 1` won't return any record without appointments (and is thus not what you want?)
Pascal Thivent
`BTW: when using "IS EMPTY" no STringIndexOutOfBoundsException but only 2 users instead of thousands` Show the generated SQL.
Pascal Thivent
@Pascal I double agree with you, difficult to discus the problem here and the SELECT with the INNER JOIN doesn't give the correct result, But how can I solve this? Do I need an IN query?
michel
@michel It might help to see the generated SQL for analysis. But somehow, this is a different question. Maybe opening another question for this purpose would be better.
Pascal Thivent
I Solved the problem. I need another JOIN in my HQL query: SELECT u FROM User u LEFT JOIN u.appointments pas1 LEFT JOIN pas1.slot t WHERE u.status = 1 AND t.end <= :date1 OR t.end IS NULL ORDER BY u.name asc Thanks for helping with the Solution. The suggestion LEFT JOIN helps me a lot. THX
michel
@michel Well, glad this little discussion helped to find the solution. Well done.
Pascal Thivent
A: 

Have you taken a look at your generated SQL? Your method works fine here:

// Hibernate query:
const string hql = "from User u where u.Id = 101 and size(u.Appointments) = 0";


// Generates this working SQL:
select user0_.Id    as Id20_,
       user0_.Name as Name2_20_
from   User user0_
where  user0_.Id = 101
       and (select count(appointment1_.Id_Solicitud)
            from   Appointment appointment1_
            where  user0_.Id = appointment1_.Id_User) = 0
Rafael Belliard