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 _______________________________________________ hibernate-dev mailing list hibernate-dev@lists.jboss.org https://lists.jboss.org/mailman/listinfo/hibernate-dev