CSS

Thursday, May 30, 2013

How to create a Hibernate UserType for a Boolean that really works

So I am working with a legacy database using JPA/Hibernate.  Our booleans are stored as a VARCHAR(5) with the values of either 'true' or 'false',  This does not lend its self to using the built in Hibernate type or either yes_no or true_false.

I tried using Hibernates org.hibernate.usertype.UserType interface to create a user type.  This almost worked.  I was able to successfully read and write data.  The problem was that if I had a query in which  I want to statically use true or false I had to singe quote the true or false.  See below for what did and did not work.

What I wanted

Select ss from StudentSupportSurvey ss where ss.stopNags = true 

What I had to do

Select ss from StudentSupportSurvey ss where ss.stopNags = 'true' 

UserType that worked

Notice that I did not implement UserType I instead extended AbstractSingleColumnStandardBasicType.  In my opinion it is probably always better to override one of the abstract classes found in org.hibernate.type then to implement UserType.

package org.yfu.util.hibernate;

import java.io.Serializable;

import org.hibernate.dialect.Dialect;
import org.hibernate.type.AbstractSingleColumnStandardBasicType;
import org.hibernate.type.DiscriminatorType;
import org.hibernate.type.PrimitiveType;
import org.hibernate.type.StringType;
import org.hibernate.type.descriptor.java.BooleanTypeDescriptor;
import org.hibernate.type.descriptor.sql.VarcharTypeDescriptor;

public class TrueFalseBooleanUserType extends AbstractSingleColumnStandardBasicType<Boolean>
 implements PrimitiveType<Boolean>, DiscriminatorType<Boolean>{

 private static final long serialVersionUID = -2794554001044861116L;
 
 public TrueFalseBooleanUserType() {
  super(VarcharTypeDescriptor.INSTANCE, BooleanTypeDescriptor.INSTANCE);
 }

 @Override
 public String getName() {
  return "yfu_boolean";
 }
 
 public Class getPrimitiveClass() {
  return boolean.class;
 }

 public Boolean stringToObject(String xml) throws Exception {
  return fromString( xml );
 }

 public Serializable getDefaultValue() {
  return Boolean.FALSE;
 }

 public String objectToSQLString(Boolean value, Dialect dialect) throws Exception {
  return StringType.INSTANCE.objectToSQLString( value.booleanValue() ? "true" : "false", dialect );
 }
}

This allowed me to right my query like this:
Select ss from StudentSupportSurvey ss where ss.stopNags = true 

No comments:

Post a Comment