org.hibernate.MappingException: No Dialect mapping for JDBC type: -9
Folgendes Setup: Play 1.2.5.3, also Hibernate 3.6.10. Damit eine native Query auf einen MS SQL Server.
Folgender Fehler:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
javax.persistence.PersistenceException: org.hibernate.MappingException: No Dialect mapping for JDBC type: -9 at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1389) at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1317) at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:255) [...snip...] Caused by: org.hibernate.MappingException: No Dialect mapping for JDBC type: -9 at org.hibernate.dialect.TypeNames.get(TypeNames.java:77) at org.hibernate.dialect.TypeNames.get(TypeNames.java:100) at org.hibernate.dialect.Dialect.getHibernateTypeName(Dialect.java:378) at org.hibernate.loader.custom.CustomLoader$Metadata.getHibernateType(CustomLoader.java:590) at org.hibernate.loader.custom.CustomLoader$ScalarResultColumnProcessor.performDiscovery(CustomLoader.java:516) at org.hibernate.loader.custom.CustomLoader.autoDiscoverTypes(CustomLoader.java:532) at org.hibernate.loader.Loader.getResultSet(Loader.java:1962) at org.hibernate.loader.Loader.doQuery(Loader.java:802) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274) at org.hibernate.loader.Loader.doList(Loader.java:2542) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2276) at org.hibernate.loader.Loader.list(Loader.java:2271) at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:316) at org.hibernate.impl.SessionImpl.listCustomQuery(SessionImpl.java:1842) at org.hibernate.impl.AbstractSessionImpl.list(AbstractSessionImpl.java:165) at org.hibernate.impl.SQLQueryImpl.list(SQLQueryImpl.java:157) at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:246) ... 24 more |
WTF? Die Query ist da übrigens nicht erst seit gestern drin, den Fehler gibt es aber erst seit Neuestem.
stackoverflow sagt nun zuerst mal:
The type -9 is
java.sql.Types.NVARCHAR
und weiterhin (das liest man auch an anderer Stelle, der Fairness halber), die Lösung wäre:
1 |
CAST(myField AS varchar) |
Kurze Prüfung: Das fragliche Feld ist sowieso ein varchar
. Außerdem hat es natürlich normalerweise einen Grund, nvarchar
zu benutzen – nvarchar
ist ein varchar
, das Unicode unterstützt. Das will man nicht zurück casten. Macht also doppelt keinen Sinn. Vielleicht kommt der Fehler initial daher, dass das Feld seit Kurzem mit einem per String.toUpperCase() transformiertem String befüllt wird, vielleicht hilft hier ein String.toUpperCase(Locale), damit nicht implizit ein Unicode-String daraus wird. Klingt irgendwie auch merkwürdig, aber hey: Es ist ein MS SQL-Server! 🙂
Wie auch immer, wir haben durchaus nvarchar
-Felder, und wollen die auch nutzen. stackoverflow sagt nun weiterhin, man müsse den nvarchar
-Typ explizit bekannt machen, wenn er das im aktuell von Hibernate verwendeten SQL-Dialekt (und das ist hier SQLServer2008Dialect) nicht ist (ist er zwar, aber wenn’s der Sache dient…):
1 2 3 4 5 6 7 8 |
public class SQLServer2008DialectWithNvarchar extends SQLServer2008Dialect { public SQLServer2008DialectWithNvarchar () { registerColumnType( Types.NCLOB, "nvarchar(MAX)" ); registerColumnType( Types.LONGNVARCHAR, "nvarchar(MAX)" ); registerColumnType( Types.NVARCHAR, "nvarchar(MAX)" ); registerColumnType( Types.NVARCHAR, 4000, "nvarchar($1)" ); } } |
Ausprobiert, geht nicht. Nun gibt es neben registerColumnType
auch registerHibernateType
(Quelle), und damit geht’s:
1 2 3 4 5 |
public class SQLServer2008DialectWithNvarchar extends SQLServer2008Dialect { public SQLServer2008DialectWithNvarchar() { registerHibernateType(Types.NVARCHAR, StandardBasicTypes.STRING.getName()); } } |
Fast vergessen: Das ganze wird dann natürlich auch nicht per XML, sondern per application.conf
konfiguriert:
1 2 |
# not jpa.dialect! hibernate.dialect=config.SQLServer2008DialectWithNvarchar |
HTH