воскресенье, 30 января 2011 г.

Настраиваем кодировку MySQL+Hibernate+Spring

Недавно возникла у меня проблема с кодировками. Надо было написать маленький проект с формой, сохранением данных в базе, ну и отображением. Казалось бы ничего сложного, но вот данные пользователь должен был вводить на русском языке. Насмотревшись на '???????' начинаем решать проблему.


Начнем с клиентской части.
Во-первых не забываем на странице указывать:


contentType="text/html;charset=UTF-8"


Во-вторых, данные передавать только POST'ом (для GET'a у меня завести так и не получилось)
и в-третьих в web.xml добавляем фильтр который будет отвечать за кодировку:


    <filter>
        <filter-name>characterEncodingFilter</filter-name>
        <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
        <init-param>
            <param-name>encoding</param-name>
            <param-value>UTF-8</param-value>
        </init-param>
        <init-param>
            <param-name>forceEncoding</param-name>
            <param-value>true</param-value>
        </init-param>
    </filter>


    <filter-mapping>
        <filter-name>characterEncodingFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


Все, с клиентом разобрались. Данные на сервер будут поступать в нужном нам виде (и клиент их правильно примет и покажет). Тут все хорошо. Едем дальше. 


Теперь разберемся с Hibernate и MySQL. Добавляем следующие строки в настройки хибера:

<bean id="sessionFactory" ....
...

 <property name="hibernateProperties">
 <props>

  <prop key="hibernate.connection.Charset">UTF-8</prop>
  <prop key="hibernate.connection.CharacterEncoding">UTF-8</prop>
  <prop key="hibernate.connection.Useunicode">true</prop>


Если необходимо, чтобы Hibernate создавал таблицы сам, добавляем в настройки


<prop key="hibernate.hbm2ddl.auto">update</prop>




Существует несколько способов, чтобы изменить кодировку MySQL. Для начала стоит заметить, что просмотреть текущую кодировку можно с помощью команды 

 show variables like 'char%';

Нас интересует не все переменные, а только эти:


character_set_client (в какой кодировке данные придут от клиента)
character_set_connection (в какую их нужно преобразовать)
character_set_results (и в какой нужно показать результат)


Изменить эти переменные можно командой SET NAMES 'utf8';
Это равносильно:


Set character_set_client = utf8;
Set character_set_connection = utf8;
Set character_set_results = utf8;


Каждый решает для себя каким из этих  двух вариантов пользоваться.  Но есть одно "НО". Нужно помнить, что эти команды работают в пределах текущего соединения с базой, и при новом подключении все настройки сбросятся в дефолтные настройки для сервера. Поэтому если кодировку необходимо поменять раз и навсегда, и забыть об этой проблеме, то идем в папку с установленным MySQL, находим файлик my.ini или my.cnf и меняем


default-character-set=utf8


Обратите внимание, что эта опция в файле встречается два раза, и поменять кодировку нужно в двух местах. В первой секции настройки для MySQL клиента, вторая секция для сервера.


Теперь вернемся к вопросу Hibernate и автоматическим созданием таблиц. В жизни бывает всякое, и может быть нет возможности залезть в конфигурационный файл MySQL. Даже если вы установили проперти для utf8, то при автоматическом создании таблиц это вас не спасет. Потому что Hibernate создает их в дефолтной кодировке для сервера. Но можно сделать так, чтобы Hibernate создавал таблицу в той кодировке, которая нам нужна.
Сначала создадим класс


public class CustomMySQLDialect extends MySQL5InnoDBDialect{


    public String getTableTypeString(){
        return " ENGINE=InnoDB DEFAULT CHARSET=utf8";
    }
}


Потом в настройке добавляем


<prop key="hibernate.dialect">CustomMySQLDialect</prop>


Думаю здесь и так все понятно. При создании таблиц Hibernate будет дописывать эту строку, тем самым явно определяя кодировку.


Дело за малым, перезагружаем MySQL, создаем базу данных, запускаем проект и радуемся жизни!

4 комментария: