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:

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:

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…):

Ausprobiert, geht nicht. Nun gibt es neben registerColumnType auch registerHibernateType (Quelle), und damit geht’s:

Fast vergessen: Das ganze wird dann natürlich auch nicht per XML, sondern per application.conf konfiguriert:

HTH

Hibernate Envers Timestamp

Ein Envers Timestamp sieht in der Datenbank bsplw so aus: 1441090155727 (und ist ein Bigint). Das wäre der 30.04.47636, 06:02:07, und ich bezweifel, dass der Datenbankeintrag aus der Zukunft kommt. Die Lösung ist so naheliegend wie einfach: Die letzten drei Stellen stehen für die Millisekunden, der “korrekte” Timestamp lautet 1441090155, und das ist der 01.09.2015, 08:49:15.

Hibernate Interceptor mit Play 1.2.x

Update: Man beachte das PS!

Neulich wollte ich (möglichst generisch) wissen, welches Feld von einer Entity modifiziert wurde. Internet sagt, das ginge mit einem Interceptor:

Leider ist für Play nicht offensichtlich, wie man einen solchen einbindet… zumindest nicht für 1.2.x. Es gibt hibernate.ejb.interceptor, das ist es aber nicht. Tatsächlich gibt es “parallel” (“This property can not be combined with hibernate.ejb.interceptor”) noch hibernate.ejb.interceptor.session_scoped – und der geht:

Good to know: Man kann die Entity als solche hier nicht mehr ändern! Man kann aber das zu ändernde Property in currentState suchen und setzen (oder ergänzen) 🙂 Dann sollte man true zurückgeben, statt super.onFlushDirty(...). Quelle.

<Update>Interceptors haben noch einige andere nette Methoden, so kann man beispielsweise zentral checken, welche Entitäten geändert, inserted oder deleted worden sind.</Update>

PS: Internet sagt außerdem, dass Play schon einen eigenen Interceptor nutzen würde… klang für mich ein wenig so, als würde es Probleme geben, wenn man den “überschreibt” – ich konnte aber keine feststellen und das ist leider auch der Fall: im play.db.jpa.JPAPlugin wird ein eigener Interceptor verwendet, der dafür sorgt, dass Entitäten nicht automatisch gespeichert werden (Hibernate Standard?). Das bloße Verwenden eines eigenen Interceptors hebelt dies aus!

PPS: tgorres hat einen Workaround gefunden, siehe Kommentare. Vielen Dank dafür!