-->
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.  [ 1 post ] 
Author Message
 Post subject: Different load behavior: Session's "get" and HQL
PostPosted: Wed Mar 19, 2008 2:58 pm 
Newbie

Joined: Wed May 02, 2007 5:59 pm
Posts: 6
Hibernate version: 3.2.5ga

Mapping documents:

User.hbm.xml

Code:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//END" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="model.dom.User" table="user" >
        <id name="id" column="userName" type="string" unsaved-value="null" />
        <property name="email" />
        <property name="fullName" />
        <property name="password" />
    </class>
</hibernate-mapping>


Code between sessionFactory.openSession() and session.close():

Using HQL:

Code:
        User user = (User) getHibernateTemplate().execute(new HibernateCallback()
        {
            /* (non-Javadoc)
             * @see org.springframework.orm.hibernate3.HibernateCallback#doInHibernate(org.hibernate.Session)
             */
            public Object doInHibernate(Session session) throws HibernateException, SQLException
            {
                return session.createQuery("from User where id = :username").setString("username", id).uniqueResult();
            }
        });

        return user;


Using Spring's HibernateTemplate:

Code:
return (User) org.springframework.orm.hibernate3.support.HibernateDAOSupport.getHibernateTemplate().get(User.class, id);


Spring's HibernateTemplate ends up delegating to org.hibernate.Session.get(Object, Serializeable)

Name and version of the database you are using: MySQL 5.0

I'll preface this by saying that I'm using a case-insensitive collation (utf8_unicode_ci) for a PK column in my User table which is probably not a good idea. That said, I'm running into what I believe to be somewhat of an inconsistency in Hibernate.

The two above methods for finding a User by its primary key seem to be equivalent: HQL Query and a Session.get(). However, I'm finding that if I have a User with username "admin" in my database and I pass "Admin" for the input id, I get slightly different results.

In both case, the record is found because as I said the column is using a case insensitive collation. However, when using the HibernateTemplate.get() call I see that the "id" property of the found User object is "Admin" instead of "admin" as it is in the database. When using HQL the returned object has an id of "admin" as it is in the database.

I believe I have traced this down to org.hibernate.loader.Loader#getKeyFromResultSet():

Code:
   /**
    * Read a row of <tt>Key</tt>s from the <tt>ResultSet</tt> into the given array.
    * Warning: this method is side-effecty.
    * <p/>
    * If an <tt>id</tt> is given, don't bother going to the <tt>ResultSet</tt>.
    */
   private EntityKey getKeyFromResultSet(
           final int i,
           final Loadable persister,
           final Serializable id,
           final ResultSet rs,
           final SessionImplementor session) throws HibernateException, SQLException {

      Serializable resultId;

      // if we know there is exactly 1 row, we can skip.
      // it would be great if we could _always_ skip this;
      // it is a problem for <key-many-to-one>

      if ( isSingleRowLoader() && id != null ) {
         resultId = id;
      }
      else {
         
         Type idType = persister.getIdentifierType();
         resultId = (Serializable) idType.nullSafeGet(
               rs,
               getEntityAliases()[i].getSuffixedKeyAliases(),
               session,
               null //problematic for <key-many-to-one>!
            );
         
         final boolean idIsResultId = id != null &&
               resultId != null &&
               idType.isEqual( id, resultId, session.getEntityMode(), factory );
         
         if ( idIsResultId ) resultId = id; //use the id passed in
      }

      return resultId == null ?
            null :
            new EntityKey( resultId, persister, session.getEntityMode() );
   }


which simply sets the id of the returned object as the passed in id instead of the one found in the result set.

This is a problem for me because I'm trying to do a Java comparison between the id of the fetched entity and the input id in order to account for the case-insensitive nature of the column.

I have a few questions:


- Why isn't a similar thing being done when I perform the operation using HQL?
- Is there a way to force Session.get() to load the id from the result set instead of using the passed in one?
- Also, what does the method comment mean when it says its: "side-effecty"?


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

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.