-->
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: BooleanTypeDescriptor throws StringIndexOutOfBoundsException
PostPosted: Thu Aug 27, 2015 2:28 pm 
Newbie

Joined: Wed Jul 10, 2013 1:43 pm
Posts: 3
Using Hibernate version 4.1.4 Final, suppose we have a field like so:

Code:
@Column(name="ACTIVE")
@Type(type="yes_no")
private Boolean active;


Hibernate will successfully convert the strings/chars 'Y' and 'N' to Boolean.TRUE and Boolean.FALSE respectively. It is also NULL safe and will result in a NULL Boolean value. However, database fields with empty strings will throw a java.lang.StringIndexOutOfBoundsException like so:

Code:
java.lang.StringIndexOutOfBoundsException: String index out of range: 0
   at java.lang.String.charAt(Unknown Source)
   at org.hibernate.type.descriptor.java.BooleanTypeDescriptor.wrap(BooleanTypeDescriptor.java:115)
   at org.hibernate.type.descriptor.java.BooleanTypeDescriptor.wrap(BooleanTypeDescriptor.java:36)
   at org.hibernate.type.descriptor.sql.VarcharTypeDescriptor$2.doExtract(VarcharTypeDescriptor.java:66)
   at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:65)
   at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:269)
   at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:265)
   at org.hibernate.type.AbstractStandardBasicType.nullSafeGet(AbstractStandardBasicType.java:238)
   at org.hibernate.type.AbstractStandardBasicType.hydrate(AbstractStandardBasicType.java:357)
   at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2704)
   at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1541)
   at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1473)
   at org.hibernate.loader.Loader.getRow(Loader.java:1373)
   at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:640)
   at org.hibernate.loader.Loader.doQuery(Loader.java:850)
   at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:289)
   at org.hibernate.loader.Loader.doList(Loader.java:2438)
   at org.hibernate.loader.Loader.doList(Loader.java:2424)
   at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2254)
   at org.hibernate.loader.Loader.list(Loader.java:2249)
   at org.hibernate.loader.criteria.CriteriaLoader.list(CriteriaLoader.java:122)
   at org.hibernate.internal.SessionImpl.list(SessionImpl.java:1622)
   at org.hibernate.internal.CriteriaImpl.list(CriteriaImpl.java:374)
   and so on...


Hibernate's BooleanTypeDescriptor.class has the following section for converting database values to Boolean values:

Code:
@SuppressWarnings({ "UnnecessaryUnboxing" })
   public <X> Boolean wrap(X value, WrapperOptions options) {
      if ( value == null ) {
         return null;
      }
      if ( Boolean.class.isInstance( value ) ) {
         return (Boolean) value;
      }
      if ( Number.class.isInstance( value ) ) {
         final int intValue = ( (Number) value ).intValue();
         return intValue == 0 ? FALSE : TRUE;
      }
      if ( Character.class.isInstance( value ) ) {
         return isTrue( ( (Character) value ).charValue() ) ? TRUE : FALSE;
      }
      if ( String.class.isInstance( value ) ) {
         return isTrue( ( (String) value ).charAt( 0 ) ) ? TRUE : FALSE;
      }
      throw unknownWrap( value.getClass() );
   }


The problem is the block of code that deals with Strings. The charAt(0) method will cause an exception for empty strings. That line should instead read:

Code:
return ( !( (String) value).equals("") ) && isTrue( ( (String) value ).charAt( 0 ) ) ) ? TRUE : FALSE;


While it is completely fine to have a CHAR(1) or VARCHAR(1) column and deal with NULL and empty character/string in special ways, if you are using @Type(type="whatever"), you are mapping a Boolean field to the database and as such, a Boolean object cannot have a value of empty string. I believe Hibernate should handle the conversion and return either FALSE or NULL. In my case, FALSE would be preferable as anything other than 'Y' is considered false.

On a side note, why is there no option to default NULL to Boolean.FALSE for the @Type annotation? Then you could map to a primitive, non-nullable boolean field and not have to do NULL checks or Boolean.TRUE.equals(field).


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.