-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 
Author Message
 Post subject: Nhibernate generating "=" in place of "is nul
PostPosted: Tue Mar 14, 2006 7:34 pm 
Beginner
Beginner

Joined: Wed Jun 08, 2005 4:59 pm
Posts: 27
I have a SQL Server table containing hierarchial categories, TipCategories. It has an Id field and a ParentId field which may be null. There is also an int field named DisplayRank that is used to affect the sort of categories for display. So the abridged table schema looks like:

Code:
TABLE TipCategories (
Id uniqueidentifier not null,
ParentId uniqueidentifier null,
DisplayRank int not null)


The mapping is:

Code:
<?xml version="1.0" encoding="utf-8" ?>

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.0" assembly="Core" namespace="Core">
   <class name="TipCategory" table="TipCategories">
      <id name="Id" type="Guid" unsaved-value="00000000-0000-0000-0000-000000000000">
         <generator class="guid" />
      </id>
      <many-to-one name="ParentCategory" column="ParentId" class="TipCategory" />
      <property name="DisplayRank" />
   </class>
</hibernate-mapping>


I create the following query:
Code:
select max(category.DisplayRank) from TipCategory category where category.ParentCategory = :parentCategory


And pass null in as a parameters, qualifying it as a TipCategory type. NHibernate produces the following SQL:
Code:
select max(tipcategor0_.DisplayRank) as x0_0_
from TipCategories tipcategor0_
where (tipcategor0_.ParentId = @p0)


It binds null to @p0, and the result of this query is NULL. However, if it had been using the "is null" clause, I would get the numeric result I expected.

Is this a bug or am I doing something wrong?

-mt


Top
 Profile  
 
 Post subject:
PostPosted: Tue Mar 14, 2006 11:12 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
Hibernate isn't going to edit your queries for you. Change your query:
Code:
select max(category.DisplayRank)
from TipCategory category
where (:parentCategory is null and category.ParentCategory is null)
    or (:parentCategory is not null and category.ParentCategory = :parentCategory)


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 15, 2006 1:19 pm 
Beginner
Beginner

Joined: Wed Jun 08, 2005 4:59 pm
Posts: 27
Hmm... so much for abstracting away from SQL. Perhaps I am missing something fundamental. Why was the "is null" clause carried over from SQL into HQL (i.e. what about it felt different from "= null" to warrant additional syntax)?

-mt


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 15, 2006 1:53 pm 
Beginner
Beginner

Joined: Wed Jun 08, 2005 4:59 pm
Posts: 27
Saga continues. I took tenwit's avice and modified my query, however, NH is doing something REALLY odd now.

The SQL it generates is:
Code:
select max(tipcategor0_.DisplayRank) as x0_0_ from TipCategories tipcategor0_ where ((@p0 is null)and(tipcategor0_.ParentId is null))or((@p1 is not null)and(tipcategor0_.ParentId=@p2))


So I'm not sure why it converted one variable used three times into three variables (don't we lose some efficiency here?!?), but the worst part is not that.

The worst part is that while NH correctly understood that it should be comparing on ParentId, in reality it tries to bind the byte array serialized representation of the entire object to each of the three sql query parameters.

Now clearly I can rewrite the HQL query to explicitly use the Id field, but having to do that would be a sign of another leaky abstraction.

So is this me or NH? Is something wrong with my mapping?

-mt


Top
 Profile  
 
 Post subject:
PostPosted: Wed Mar 15, 2006 5:44 pm 
Expert
Expert

Joined: Thu Dec 23, 2004 9:08 pm
Posts: 2008
No, that's all correct. Hibernate will bind the same java variable to the three different SQL variables. That's just how SQL works, it's not an issue with hibernate.

Hibernate can't do much with the "is null" thing. I suppose that it could expand out your original short version into the longer multi-check thing, but that will fall over if the thing you're comparing to has side effects (e.g. is a subselect into a temporary table).

Ultimately, the problem boils down the fact that null isn't a "value" in SQL, it's a state, meaning "unset". Java just doesn't have that concept (thankfully: it's hopeless outmoded and really doesn't belong even in SQL, imo). In SQL, null = null is false: nothing equals null, not even null. That's why there's a separate "is null" expression.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 5 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.