August 13th, 2005

MySQL, Hibernate und UTF8

Posted by frank in Java, MySQL

Ab der Version 4.1 ist es möglich im MySQL-Server Daten im UTF-8-Format abzulegen. Wichtig dafür ist, dass die Verbindung und auch die Datenbank selbst im UTF-8 arbeiten. Unter Debian oder auch Ubuntu läuft der MySQL-Server standardmäßig mit der Kodierung latin1 und der Collation latin_swedish_ci. Wenn nun von Hibernate Tabellen angelegt werden, so erhalten diese automatisch auch diese Kodierung und die Speicherung von z.B. japanischen Zeichen geht schief.
Jetzt bietet der JDBC-Treiber von MySQL die Möglichkeit mit den Parametern useunicode, connectionCollation und characterSetResults die Kodierung der Kommunikation zu beeinflussen:

jdbc:mysql://localhost/test? useUnicode=true& connectionCollation=utf8_general_ci& characterSetResults=utf8

Jedoch wird damit lediglich die Verbindung gesteuert und nicht die Datenbank. Die Tabellen von Hibernate werden trotzdem noch mit der Collation latin1_swedish_ci angelegt. Abhilfe schafft hier nur die Umstellung der Standardkodierung des Datenbankservers. Dazu einfach folgende Zeilen in die my.cnf unterhalb von [mysqld] eintragen:


default-character-set=utf8
default-collation=utf8_general_ci

Nach einem Neustart ist dann die Kodierung standardmäßig immer UTF8. Wer keinen Zugriff auf die Serverkonfiguration hat, dem bleibt nach dem Anlegen nur die manuelle Umstellung auf UTF8 oder aber die Implementierung eines eigenen Connectionpools, welcher die Verbindung mit Hilfe von MySQL-SQL-Befehlen richtig initialisiert. Der Befehl dazu lautet: SET NAMES 'utf8'

7 Responses to ' MySQL, Hibernate und UTF8 '

Subscribe to comments with RSS or TrackBack to ' MySQL, Hibernate und UTF8 '.


  1. on Januar 11th, 2008 at 4:31 pm

    […] Aber auch das half bei mir nicht. Und auch Tipps wie von frank und golgote halfen nicht. […]

  2. elch said,

    on März 10th, 2008 at 6:09 pm

    Ich hab das selbe problem mit Hibernate 3 und MySQL. Die Connection URL und Datenbankeinstellung sind korrekt. Trotzdem werden Umlaute mit ISO 8859-1 Codierung gespeichert. Im Moment habe ich den Verdacht dass es am Connection Pool liegen könnte.

  3. frank said,

    on März 10th, 2008 at 7:30 pm

    Ich würde jetzt folgendes Prüfen:
    1. Werden die Daten wirklich falsch gespeichert. Hierzu muss man nur mit einem anderen MySQL-Client wie z.B. phpMyAdmin oder auch MySQL Query Browser die Datenbank befragen.
    2. Kommen korrekt gespeicherte Werte bei der Hibernate-Anwendung an, also funktioniert der lesende Zugriff.
    3. Wenn ja, liegen die zu speicherenden Werte im Java-Context korrekt vor? Es kommt oft zu Problemen mit Browsern, dass gar nicht die DB oder die Verbindung zur DB schuld ist, sondern der Client die Kodierung schon vermasselt und die Werte dann im Java-Kontext schon falsch kodiert vorliegen.

  4. elch said,

    on März 10th, 2008 at 7:41 pm

    In der Anwendung verwende ich durchweg UTF-8.

    Die Umlauten sind bis zum Update korrekt, das habe ich durch Debuggen geprüft. Um die Daten in der DB zu prüfen benutze ich die Console, bei der ich unter Linux die Kodierung auswählen kann. Die selektierten Daten werden mit ISO 8859-1 Kodierung korrekt angezeigt, mit UTF-8 kommt nur Salat raus. Die Anwendung bekommt die Daten dann auch falsch kodiert und zeigt den selben Salat an wie in der Konsole mit UTF-8.
    Im Hibernate Forum bin ich auf einen Kommentar von einem Hibernate Senior gestoßen der mich auf eine neue Fährte geführt hat:
    “try changing the mysql driver around a little”
    Ich kann mich auch wage dran erinnern dass das Problem, ein Evergreen, vor ein paar Jahren schonmal auf die Weise behoben wurde. Ein Wechsel der mysql-connector-java.jar von v5.0.5 auf v5.1.6 hat leider noch nichts geändert. Ich habe ein paar Posts gelesen in denen geschrieben wurde dass v3.x funktionieren soll aber so weit zurück will ich definitiv nicht gehen.

  5. elch said,

    on März 11th, 2008 at 2:33 pm

    Ich glaube ich hab´s jetzt gelöst.
    Anscheinend hat das Speichern der Daten doch funktioniert, nur die MySQL Konsole und der Browser haben sie in gleicher Weise falsch dargestellt.

    Bei der Konsole hilft der Parameter –default-character-set=utf8 die Daten richtig anzuzeigen. Browserseitig, bzw. Serverseitig war ein Requestfilter die Lösung der die Kodierung für Request und Response auf UTF8 setzt.

    public class UTF8EncodingRequestFilter implements Filter {

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    throws IOException, ServletException {
    request.setCharacterEncoding(”UTF-8″);
    response.setCharacterEncoding(”UTF-8″);
    chain.doFilter(request, response);
    }

    public void destroy() {}

    public void init(FilterConfig arg0) throws ServletException {}

    }

  6. frank said,

    on März 11th, 2008 at 3:08 pm

    Wunderbar. Nun die MySQL-Konsole muss natürlich auch in den UTF-8 Modus bei der Verbindung gebracht werden.
    Den Filter sollte man evtl so erweitern, dass der Client eine Fehlermeldung bekommt, wenn er UTF-8 nicht versteht.

  7. Grunzi said,

    on April 8th, 2008 at 9:12 pm

    Also xplanner bringt mich langsam um (irgendwo eine doppelkonvertierung von UTF8 auf LATIN1) aber hier die Tips zum debuggen von MySQL:

    1) Chapter 9.1.4 des Referenzhandbuchs (”Connection Character Sets and Collations”)
    2) SET NAMES ‘utf8′
    3) Charset des Feldes, der Table und der Datenbank checken.
    4) SELECT HEX(field) zeigt die Bytes im Felde an. Man kann dann leich die Kodierung nachprüfen ohne dass das Terminal auch noch dazwischenfunkt.

    :mrgreen:

Leave a reply

:mrgreen: :neutral: :twisted: :shock: :smile: :???: :cool: :evil: :grin: :oops: :razz: :roll: :wink: :cry: :eek: :lol: :mad: :sad: