[hibernate-dev] Enum mapping in hbm.xml

Steve Ebersole steve at hibernate.org
Sun Jul 19 11:02:37 EDT 2015


I should have mentioned...  There is also this "type" parameter that
EnumType accepts.  I'd also look at that in terms of deciding defaults.  It
accepts JDBC type codes.  EnumType already knows which type codes
constitute ordinal types and named types.  So in psuedo code what I am
proposing is:

if ( useNamed != null ) {
    if ( useNamed == true ) {
        treatAsNamed();
    }
    else {
        treatAsOrdinal();
    }
}
else {
    if ( type != null ) {
        if ( isOrdinal(type) ) {
            treatAsOrdinal();
        }
        else if ( isNamed(type) ) {
            treatAsNamed();
        }
    }
    else {
        // todo : need to decide fallback...
       treatAsNamed();
    }
}
throw new SomePoignantException("blah blah blah");

The other thing to notice is that there is no more "waiting" in this
proposal.  No more deferring until the first nullSafeSet/nullSafeGet call.

On Sun, Jul 19, 2015 at 9:53 AM Steve Ebersole <steve at hibernate.org> wrote:

> This came up in getting the testsuite set up against MySQL.  When an enum
> is defined in hbm.xml we do not inherently know whether to treat it as
> ordinal or named.  We try a few different things to make this
> determination, but ultimately if we do not have enough information up front
> we prefer to defer the decision until later when we have access to some
> form of JDBC metadata (generally nullSafeSet/nullSafeGet) to decide.
>
> It seems there was initially a problem in that deference code that led
> to HHH-8153[1].  However, the fix done for HHH-8153 is not enough.
> Ultimately the problem is that the driver may not have the proper
> information to answer java.sql.ParameterMetaData#getParameterType
> correctly.  HHH-8153 handles the case where the driver flat out does not
> support that call and throws an exception.  However MySQL illustrates
> another case where the driver simply reports VARCHAR as the broadest
> acceptable type.  In other words it is not looking at the underlying
> datatypes in the database.  So even if the parameter is matched to the enum
> column that we defined as numeric, the MySQL driver is still going to
> return ParameterMetaData#getParameterType == VARCHAR.
>
> I cannot say how many drivers implement this correctly.  H2 does this as
> we expect it.  MySQL at least does not.
>
> So the question becomes how we want to support enum types in hbm.xml.  For
> illustration, this can be seen in the org.hibernate.test.enums.EnumTypeTest
> added for HHH-8153.  The mapping is
> https://github.com/hibernate/hibernate-orm/blob/master/hibernate-core/src/test/resources/org/hibernate/test/enums/Person.hbm.xml.
> Neither enum mapping works particularly "correctly", but the test failure
> comes from the HairColor mapping.  We expect that to be an ordinal, we
> create the table with its column being a numeric, but then the driver says
> the parameter type is VARCHAR and we try to treat it as named.
>
> For what it is worth, I had quite a long time ago added the parameter
> needed to properly control this in hbm.xml.  The "proper" way to map these
> would have been to use the "useNamed" type parameter:
>
> <property name="gender" not-null="true">
>     <type name="org.hibernate.type.EnumType">
>         <param name="enumClass">org.hibernate.test.enums.Gender</param>
>         <param name="useNamed">false</param>
>     </type>
> </property>
> <property name="hairColor" not-null="true">
>     <type name="org.hibernate.type.EnumType">
>         <param name="enumClass">org.hibernate.test.enums.HairColor</param>
>         <param name="useNamed">true</param>
>     </type>
> </property>
>
> The rub is that to cater for legacy mappings, I do not "require" this,
> like annotations do.  This would be a non-issue if I could, during
> configuration, say that an enum is ordinal if "useNamed" is not set or is
> set to false and that it is named if useNamed is set to true.  What is
> missing/different is the not-set case.  At them moment that falls back to
> the JDBC metadata approach discussed above.
>
> What I propose is that we change this.  I am kind of torn as to the
> default tbh.  I think JPA's default of ORDINAL is the wrong choice.  I
> think NAMED is the better choice.  Well technically I think an independent
> mapping code it best.  But strictly between ORDINAL/NAMED, I think NAMED is
> better.  So if everyone agrees that we change this to definitively
> determine the enum mapping up front, which style do we choose as the
> default.  Obviously the big argument for choosing ORDINAL is consistency
> with annotations.
>
>
> [1] https://hibernate.atlassian.net/browse/HHH-8153
>


More information about the hibernate-dev mailing list