Reputation: 2553
Considering the following enum in Java:
public enum Color {
RED,
GREEN
}
The definition in the JPA Entity
@Column(name = "COLOR")
private Color color;
and the MySQL DDL:
`COLOR` tinyint(1) NOT NULL
Why does Hibernate 3.5 seem to always map the tinyint(1) to a java.lang.Boolean, leading to the following exception:
java.lang.ClassCastException: java.lang.Boolean cannot be cast to java.lang.String
at org.hibernate.type.EnumType.nullSafeGet(EnumType.java:119)
at org.hibernate.type.CustomType.nullSafeGet(CustomType.java:132)
at org.hibernate.type.AbstractType.hydrate(AbstractType.java:105)
at org.hibernate.persister.entity.AbstractEntityPersister.hydrate(AbstractEntityPersister.java:2267)
at org.hibernate.loader.Loader.loadFromResultSet(Loader.java:1423)
at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1351)
at org.hibernate.loader.Loader.getRow(Loader.java:1251)
at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:619)
at org.hibernate.loader.Loader.doQuery(Loader.java:745)
at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:270)
at org.hibernate.loader.Loader.doList(Loader.java:2294)
at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2172)
at org.hibernate.loader.Loader.list(Loader.java:2167)
at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:448)
at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:363)
at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196)
at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1258)
at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102)
at org.hibernate.ejb.QueryImpl.getSingleResult(QueryImpl.java:264)
This seems to be fixed easily by changing the DDL to tinyint(2). However, I was wondering if this is intended and why hibernate maps to a Boolean, even though it should know that this should be mapped as an enum.
Upvotes: 1
Views: 4030
Reputation: 344
It's possible to write a custom UserType to tell hibernate to map the tinyint(1) to an enum
class EnumUserType<T extends Enum<T>> implements UserType { ... }
You just need to implement the nullSafeSet
and nullSafeGet
methods to map your enumeration to the integer from the result set.
Then add the Type annotation to your Entity column
@org.hibernate.annotations.Type(type = "com.myco.EnumUserType")
Of course you could tell mysql to NOT map the tinyint(1) to a bit by setting the tinyInt1isBit
JDBC connection property to false, but this will affect all your tinyint(1)s.
Upvotes: 1
Reputation: 34657
According to the mysql jdbc type mapping, not only is this intended behaviour, it's documented. Strictly speaking, Hibernate isn't doing the mapping, the jdbc driver is. You could file a bug against mysql and make a case if you think this behaviour should be changed, though.
Upvotes: 4