st-h
st-h

Reputation: 2553

why does hibernate map tinyint(1) to a java.lang.Boolean?

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

Answers (2)

Kieran
Kieran

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

hd1
hd1

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

Related Questions