-->
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.  [ 7 posts ] 
Author Message
 Post subject: org.hibernate.type.EnumType class cast exception
PostPosted: Fri Jul 24, 2009 1:42 pm 
Newbie

Joined: Fri Nov 14, 2008 10:45 am
Posts: 6
Hi

I have a class with an enum field persisted as STRING

Code:

class SomeEntity {

Long id;
@Enumerated(EnumType.STRING)
Color color;
String name;

/* constructor */
public SomeEntity(Long id, Color color, String name){
...
}

}

enum Color { GRAY, BLACK, WHITE; }


I'm getting a Class Cast Exception when using this kind of query:

Code:
select new SomeEntity(s.id, s.color, s.name) from SomeEntity s


Exception:

Code:
javax.ejb.EJBException: EJB Exception: : java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Enum
   at org.hibernate.type.EnumType.nullSafeSet(EnumType.java:134)
   at org.hibernate.type.CustomType.nullSafeSet(CustomType.java:179)
   at org.hibernate.param.NamedParameterSpecification.bind(NamedParameterSpecification.java:67)
   at org.hibernate.loader.hql.QueryLoader.bindParameterValues(QueryLoader.java:514)
   at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1593)
   at org.hibernate.loader.Loader.doQuery(Loader.java:696)
   at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259)
   at org.hibernate.loader.Loader.doList(Loader.java:2232)
   at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2129)
   at org.hibernate.loader.Loader.list(Loader.java:2124)
   at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:401)



Looking at the source code
Code:
                         boolean isOrdinal = isOrdinal( sqlType );
         if ( isOrdinal ) {
            int ordinal = ( (Enum) value ).ordinal();
            if ( IS_VALUE_TRACING_ENABLED ) {
               log().debug( "Binding '{}' to parameter: {}", ordinal, index );
            }
            st.setObject( index, Integer.valueOf( ordinal ), sqlType );
         }
         else {
            [b] String enumString = ( (Enum) value ).name(); [/b]
            if ( IS_VALUE_TRACING_ENABLED ) {
               log().debug( "Binding '{}' to parameter: {}", enumString, index );
            }
            st.setObject( index, enumString, sqlType );
         }

the line String enumString = ( (Enum) value ).name();
I see the cast without a check to see if VALUE is a String

with normal queries (select a from A a), things go very well in respect to enums

Is this a bug or am I doing something wrong?

thanks in advance

Junico


Top
 Profile  
 
 Post subject: Re: org.hibernate.type.EnumType class cast exception
PostPosted: Fri Jul 24, 2009 1:49 pm 
Newbie

Joined: Fri Nov 14, 2008 10:45 am
Posts: 6
Just more info

I changed EnumType to this:
Code:
String enumString = null
            if(value instanceof String)
               enumstring = value;
            else
               enumstring = ( (Enum) value ).name();
            if ( IS_VALUE_TRACING_ENABLED ) {
               log().debug( "Binding '{}' to parameter: {}", enumString, index );
            }
            st.setObject( index, enumString, sqlType );


it works...

but I still don't know if this is good or not

thanks in advance

Junico


Top
 Profile  
 
 Post subject: Re: org.hibernate.type.EnumType class cast exception
PostPosted: Fri Jul 24, 2009 6:56 pm 
Regular
Regular

Joined: Thu Apr 14, 2005 10:39 am
Posts: 115
Obviously value is a String (as annotated) and the rest is just unreachable code. So you just avoiding your Exception by not executing your else clause.

If you select single attributes, you will get them. Hibernate only replacing them with the enum type, if the whole entity is loaded.

Greetings Michael


Top
 Profile  
 
 Post subject: Re: org.hibernate.type.EnumType class cast exception
PostPosted: Sat Jul 25, 2009 6:18 am 
Newbie

Joined: Fri Nov 14, 2008 10:45 am
Posts: 6
Thanks for the answer Michael

If I understood your explanation, It is correct the enum value coming as a String, but even if I have a constructor like that

Code:
public SomeEntity(Long id, String color, String name){
    this.color =  Enum.valueOf(color);
    this.bla = bla;
}



the exception still occurs.

In debug I don't know what is happening, but even my setter nor the constructor is called before the exception being thrown.

How can I execute this kind of query?

Thank You very much Michael

Junico


Top
 Profile  
 
 Post subject: Re: org.hibernate.type.EnumType class cast exception
PostPosted: Sat Jul 25, 2009 5:48 pm 
Regular
Regular

Joined: Thu Apr 14, 2005 10:39 am
Posts: 115
Hi, don't try to fetch the attirbutes by hand!

Normally hibernate uses the empty constructor and uses the setter/getter-methods or direct access (which you have chosen by your annotations on the attributes!) to the attributes to rebuild the object.

So your parametrized constructor and getter/setters won't be called at all.

A Query like this, should be enough:
Quote:
s.createQuery("from SomeEntity");

Coded it by hand, so it may not be correct.
The result of this Query will be a list of Objects of the type you need. (Cast is required) Use where clause to limit the results. See Dokumentation for further details.

Quote:
new SomeEntity(s.id, s.color, s.name)

You don't have to use such an expression in your queries and it is not allowed. Should be rejected.

Use HQL or Criteria not SQL directly!

Greetings Michael


Top
 Profile  
 
 Post subject: Re: org.hibernate.type.EnumType class cast exception
PostPosted: Mon Jul 27, 2009 4:55 am 
Newbie

Joined: Fri Nov 14, 2008 10:45 am
Posts: 6
thank You urmech for your explanations!

I will show You why I am using this query:

Code:
class Product{
   String name;// this is not needed at all, it is here to create the constructor
   Color color;
   BigDecimal price;
   List<ProductTranslated> translations;

   public Product(String name, Color color, price){this.bla = bla}
}

class ProductTranslated{

    Product product;
    String translatedName;
    String locale;
}



As my app is i18n'd I need to show the products with the name in the current user Locale;

So what I do is

Code:
SELECT new Product(ptran.translatedName, p.color, p.price)
           from Product p, ProductTranslated ptran
              where ptran.product = p.id
                 and ptran.locale = 'userLocaleHere'
                 and ptran.name like 'blablablabla%'



I need this new Product(....) because the NAME value will come from the ProductTranslated, not from the Product

Is this the right way to do that?

thanks in advance

Junico


Top
 Profile  
 
 Post subject: Re: org.hibernate.type.EnumType class cast exception
PostPosted: Mon Jul 27, 2009 5:26 am 
Regular
Regular

Joined: Thu Apr 14, 2005 10:39 am
Posts: 115
Hi, how about declaring name @Transient and to resolve the current translation in your getter- or toString-Method ?

Same in your enum Color. (By the way @Transient isn't required there.)

Cause you can be sure that the string will be empty unless you have initialized it with the current language, so you have to do this only once.

If you want to change it, while your app is running and the products were already loaded, I would use the Observer/Observable-Pattern (see java.uitl).
So you can notify the products to update their describing. (Similar to Event-listeners)

By the way, you can do it by hand (not recommended). with your
Code:
public Product(String name, Color color, price){this.bla = bla}
}


But then you can't use Color as enum, you have to pass it as String and use
Quote:
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name)

to resolve it. (Or use the valueOf-Method before you call the constructor, then you can keep your method signature unchanged.)

By the way, I wouldn't store the locale as attribute of PrroductXYZ.
It's a global variable, so place in an singleton class, so it is common to all objects. (If don't know what a singelton is, refer to "Effective Java" from Josuha Bloch.)

You surely don't want to display product1 in English and product 2 in German.

Greetings Michael


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