Hibernate で CHAR を String にマップする
   1 min read

例えば、生 JDBC でchar型カラムのクエリを書くとString型にマップされます

    final Connection connection = DriverManager.getConnection(...);
    final Statement statement = connection.createStatement();
    final ResultSet resultSet = statement.executeQuery("select char_column from foo_table");

    // java.lang.String
    resultSet.getMetaData().getColumnClassName(1);

が、Hibernate の Native query を用いて同じように実行するとCharacter型にマップされます:

    final EntityManagerFactory factory = Persistence.createEntityManagerFactory(...);
    final EntityManager em = factory.createEntityManager();
    final Query q = em.createNativeQuery("select char_column from foo_table", Tuple.class);
    final List<Tuple> res = q.getResultList();

    // java.lang.Character
    res.get(0).get(0).getClass();

この挙動を決めているのは org.hibernate.dialect.Dialectのこの辺りです:

    registerHibernateType( Types.CHAR, StandardBasicTypes.CHARACTER.getName() );
	registerHibernateType( Types.CHAR, 1, StandardBasicTypes.CHARACTER.getName() );
	registerHibernateType( Types.CHAR, 255, StandardBasicTypes.STRING.getName() );

この挙動を変えるには、カスタムの Dialect を実装し、それを persistence.xml なりで指定するようにします。

カスタム Dialect の例:

package com.example.dialect;

import java.sql.Types;

import org.hibernate.dialect.H2Dialect;
import org.hibernate.type.StandardBasicTypes;

public class H2CustomDialect extends H2Dialect {

    public H2CustomDialect() {
        super();

        registerHibernateType(Types.CHAR, StandardBasicTypes.STRING.getName());
        registerHibernateType(Types.CHAR, 1, StandardBasicTypes.STRING.getName());
        registerHibernateType(Types.CHAR, 255, StandardBasicTypes.STRING.getName());

    }

}

参考: