-->
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: Relationship FK uses '0' instead of null, Take 2
PostPosted: Tue Feb 26, 2008 6:15 am 
Newbie

Joined: Fri Feb 22, 2008 5:28 am
Posts: 2
Good day.

I try to implement mapping of ManyToOne association in a legacy database, such that when there is no association, zero (0) is put into a column, not null.
To do this, I found three-years-old topic on this forum (Relationship foreign key uses '0' instead of null) where solution was proposed.

It is proposed there to use UserType in conjuction with ManyToOne, as
Quote:
ManyToOneType wraps around the identifier Type. So if you wrote a custom type that mapped null->zero and used it as the identifier type of the associated class, then the many-to-one would see that.


I implemented this with a custom UserType and two annotations over the required field, @ManyToOne and @Type(type="my.ZeroedForeignKeyType"), like this:
Code:
   @ManyToOne(optional=true)
   @LazyToOne(LazyToOneOption.PROXY)
   @Type(type="my.ZeroedForeignKeyType")
   @JoinColumn(name="f_ASSOCID")
   private MyAssoc myAssoc;

Code:
package my;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;

import org.hibernate.HibernateException;
import org.hibernate.usertype.UserType;

public class ZeroedForeignKeyType implements UserType {
   
   public ZeroedForeignKeyType() {
   }

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

   public Object deepCopy(Object value) throws HibernateException {
        if (value == null)
            return null;
        return new Long(((Long) value).longValue());
   }

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

   public boolean equals(Object x, Object y) throws HibernateException {
        if (x == null && y == null)
            return true;
        else if (x == null)
            return false;
        return x.equals(y);
   }

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

   public boolean isMutable() {
      return true;
   }

   public Object nullSafeGet(ResultSet rs, String[] names, Object owner)
         throws HibernateException, SQLException {
      long val = rs.getLong(names[0]);
      if (val == 0) {
         return null;
      }
      return val;
   }

   public void nullSafeSet(PreparedStatement st, Object value, int index)
         throws HibernateException, SQLException {
      if (value == null) {
         st.setLong(index, 0);
      } else {
         st.setLong(index, (Long)value);
      }
   }

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

   public Class<?> returnedClass() {
      return Long.class;
   }

    public int[] sqlTypes() {
        return new int[] {Types.INTEGER};
    }
}


Yet my ZeroedForeignKeyType never gets loaded at all!

I placed breakpoints in its every method, constructor included, and it never gets called. I debugged through Hibernate binding code and found that this annotations set leads to the code seemingly avoiding all possible places where @Type is mentioned at all. Yet the guy in the previous topic was pretty positive of the solution working. What do I get wrong?

I use Hibernate 3.2.5, Hibernate Annotations 3.3.0.

Thanks in advance.


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 26, 2008 7:03 am 
Newbie

Joined: Fri Feb 22, 2008 5:28 am
Posts: 2
I found the solution to my problem. I misunderstood the solution proposed in the previous topic. You need to map your custom @Type not onto the foreign key declaration in the base entity, but to the primary key (@Id) declaration in the accociated class. That solves the problem.


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.