-->
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.  [ 2 posts ] 
Author Message
 Post subject: UserType's in HQL where-clause
PostPosted: Mon Mar 27, 2006 3:10 pm 
Beginner
Beginner

Joined: Wed Jul 13, 2005 2:18 pm
Posts: 44
A forum search shows that this has been discussed before, but the relevant posts I found only seemed to mention CompositeUserType, which I don't believe is appropriate in my case. My Hibernate version is 3.0.5. The following below is a simplification of my actual setup, which I have not actually compiled. Apologies if there are syntax errors.

I want to represent an enumeration of possible states which an entity might have, so I define the following class:
Code:
public class State {
  public static final STATE_ONE = new State("one");
  public static final STATE_TWO = new State("two");

  private String code;
 
  private State(String code) {
    this.code = code;
  }

  public String getCode() {
    return code;
  }


In order to make it possible to map properties of type State to the database, I write an implementation of UserType named StateUserType:
Code:
public class StateUserType implements UserType {
  public int[] sqlTypes() { return new int[] {Types.VARCHAR}; }

  public Class returnedClass() { return State.class; }

  public boolean equals(Object x, Object y) throws HibernateException {
    return x == y;
  }

  public int hashCode(Object x) throws HibernateException {
    return x.hashCode();
  }

  public Object nullSafeGet(ResultSet rs, String[] names, Object owner) {
    String code = rs.getString(names[0]);
    if (code == null) return null;
    else if (code.equals(State.STATE_ONE.getCode())) return STATE_ONE;
    else if (code.equals(State.STATE_TWO.getCode())) return STATE_TWO;
    else return null;
  }

  public void nullSafeSet(PreparedSatatement ps, Object value, int index) {
    State s = (State)value;
    if (s == null) {
      ps.setString(index, null);
    } else {
      ps.setString(index, s.getCode());
    }
  }

   public Object deepCopy(Object value) throws HibernateException {
      return value;
   }

   public boolean isMutable() {
      return false;
   }

   public Serializable disassemble(Object value) throws HibernateException {
      return (Serializable)value;
   }

   public Object assemble(Serializable cached, Object owner)
         throws HibernateException {
      return cached;
   }

   public Object replace(Object original, Object target, Object owner)
         throws HibernateException {
      return original;
   }

}


Here's the problem: when I try to execute the following HQL statement:
Code:
from SomeEntity e where e.state = ?

and I have supplied State.STATE_ONE as the query parameter, Hibernate serializes the entire STATE_ONE instance and sends it down the wire. If I supply State.STATE_ONE.getCode() as the query parameter, things work correctly. This doesn't feel right to me - my query shouldn't need to know that State is saved by dumping the code to a column. So, what did I botch? I had thought maybe changing the implementation of disassemble() might be the answer, but from my debug output it does not appear disassemble() gets called when the query executes.

In case it's important, I am running my HQL queries through a spring HibernateTemplate using find(), rather than directly through the HibernateSession.

_________________
- Matt


Top
 Profile  
 
 Post subject: RE: UserType's in HQL where-clause
PostPosted: Mon Mar 27, 2006 3:54 pm 
Beginner
Beginner

Joined: Wed Jul 13, 2005 2:18 pm
Posts: 44
In the process of moving some queries from HQL to the Criterion interface to make refactoring a little less scary, I noticed that Criterion queries behave like I want them to. For the example in my initial post, doing:
Code:
DetachedCriteria dc = DetachedCriteria.forClass(SomeEntity.class, "e").add(Property.forName("state").eq(State.STATE_ONE));

and running that works just fine.

Out of curiousity, why does the HQL version not work this way?

_________________
- Matt


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 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.