Hibernate + MySQL:如何为数据库和表设置编码 utf-8

Posted

技术标签:

【中文标题】Hibernate + MySQL:如何为数据库和表设置编码 utf-8【英文标题】:Hibernate + MySQL: How to set the encoding utf-8 for database and tables 【发布时间】:2012-10-15 07:53:25 【问题描述】:

我的系统在 Linux Mandriva、RDBMS - MySQL 5 上运行。 我需要在 UTF-8 中创建数据库和表。

这是hibernate.cfg.xml的片段-

... 
 <property name="hibernate.hbm2ddl.auto">create-drop</property>   
 <property name="hibernate.dialect">org.hibernate.dialect.mysqlDialect</property>
 <property name="hibernate.connection.characterEncoding">utf8</property> 
...

my.cnf -

# The MySQL server
[mysqld]
...
default-character-set=cp1251
character-set-server=cp1251
collation-server=cp1251_general_ci
init-connect="SET NAMES cp1251"
skip-character-set-client-handshake
...
[mysqldump]
...    
default-character-set=cp1251
...

一些类,例如-

@Entity
@Table(name = "USER")
public class User 
    @Id 
    @Column(name = "USERID")
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;

    @Column(name = "USERNAME")
    private String name;

    @Column(name = "USERPASSWORD")
    private String password;

    @Column(name = "USERIP")
    private String ip;
        // getter's and setter's here
        ...

但是当表格生成时,我看到编码 latin1 例如 -

SHOW CREATE TABLE USER;

USER  | CREATE TABLE `user` (
  `USERID` int(11) NOT NULL auto_increment,
  `USERIP` varchar(255) default NULL,
  `USERNAME` varchar(255) default NULL,
  `USERPASSWORD` varchar(255) default NULL,
  PRIMARY KEY  (`USERID`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 |

如何将编码改为UTF-8

我将非常感谢您提供的信息! 谢谢!

...

这很奇怪,我都改成了utf8 -

# The MySQL server
    [mysqld]
    ...
    default-character-set=utf8
    character-set-server=utf8
    collation-server=utf8_general_ci
    init-connect="SET NAMES utf8"
    skip-character-set-client-handshake
    ...
    [mysqldump]
    ...    
    default-character-set=utf8
    ...

现在 -

SHOW CREATE TABLE USER;

USER  | CREATE TABLE `USER` (
  `USERID` int(11) NOT NULL auto_increment,
  `USERIP` varchar(255) default NULL,
  `USERNAME` varchar(255) default NULL,
  `USERPASSWORD` varchar(255) default NULL,
  PRIMARY KEY  (`USERID`)
) ENGINE=MyISAM DEFAULT CHARSET=cp1251 |

【问题讨论】:

my.cnf : 默认字符集=cp1251 ?将其更改为 utf8 ! 这对我了解在应用各种默认值后我最终使用的字符集和排序规则很有用SELECT CHARACTER_SET_NAME, COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA='&lt;database-name&gt;' AND TABLE_NAME='&lt;table-name&gt;' AND COLUMN_NAME='&lt;column-name&gt;'; 【参考方案1】:

您还可以使用编码创建数据库。 只需使用phpMyAdmin 创建数据库/表即可。

您可以在休眠设置的 URL 中指定一些 URL 参数以使用 UTF8 进行连接:

<!-- Database Settings -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!--  for performance reasons changed to MyISAM from org.hibernate.dialect.MySQLInnoDBDialect -->
<property name="dialect">org.openmeetings.app.hibernate.utils.MySQL5MyISAMDialect</property>
<property name="connection.url">jdbc:mysql://localhost/openmeetings?autoReconnect=true&amp;useUnicode=true&amp;createDatabaseIfNotExist=true&amp;characterEncoding=utf-8</property>    

<property name="hibernate.connection.CharSet">utf8</property>
<property name="hibernate.connection.characterEncoding">utf8</property>
<property name="hibernate.connection.useUnicode">true</property>

您不需要将数据库中的整个编码设置为utf8 仅当您使用

<!-- Database Scheme Auto Update -->
<property name="hbm2ddl.auto">update</property>   

您必须将 MySQL 的默认编码设置为 utf8。因为hbm2dll 将使用数据库的默认编码。

您可能仍然使用hbm2ddl.auto,并手动修改数据库的表以具有utf8排序规则。

如果您不使用hbm2ddl.auto,您可以简单地使用您喜欢的编码创建表。 无需将数据库设置为特殊编码。

塞巴斯蒂安

【讨论】:

我应该另外指出,我在 URL 参数中使用了 createDatabaseIfNotExist=true,这意味着数据库将以默认编码创建。这就是为什么您需要在 my.cnf 中进行系统范围的编码。 值得注意的是,不建议在生产环境中对 hbm2ddl.auto 使用“更新”。见***.com/questions/221379/… postgreSQL 数据库怎么办? 我遇到了同样的问题,Hibernate 属性根本没有帮助,因为我使用不同的连接池来创建我的数据库连接。在我的例子中是 tomcat.jdbc 连接池,所以编码必须在 org.apache.tomcat.jdbc.pool.DataSource 的 PoolProperties 中设置【参考方案2】:

如何将编码改为UTF-8?

我使用了扩展MySQLDialect 的本地方言类并更改了表类型字符串:

public class LocalMysqlDialect extends MySQLDialect 
    @Override
    public String getTableTypeString() 
        return " DEFAULT CHARSET=utf8";
    

我实际上是在扩展 MySQL5InnoDBDialect 类型,所以我真的在使用:

public class LocalMysqlDialect extends MySQL5InnoDBDialect 
    @Override
    public String getTableTypeString() 
        return " ENGINE=InnoDB DEFAULT CHARSET=utf8";
    

【讨论】:

hibernate.connection.CharSethibernate.connection.characterEncodinghibernate.connection.useUnicode 属性似乎对我不起作用(我使用的是 Spring Boot 1.3.3),但扩展 MySQL5InnoDBDialect 终于成功了。 【参考方案3】:

考虑像这样更改连接 url 配置:

<property name="hibernate.connection.url">
    jdbc:mysql://localhost/yourdatabase?UseUnicode=true&amp;characterEncoding=utf8
</property>

它解决了这个问题。

【讨论】:

拯救了我的一天!谢谢! 我使用 Spring Boot,但您的解决方案帮助了我,谢谢。我在application.properties 文件的spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase?useUnicode=true&amp;characterEncoding=utf8&amp;useJDBCCompliantTimezoneShift=true&amp;useLegacyDatetimeCode=false&amp;serverTimezone=UTC 行中添加了characterEncoding=utf8 参数。【参考方案4】:

首先在Java方面你应该指定UTF-8而不是utf8,参考table here。

其次,characterEncoding 不是用于创建表的字符集,这只是一个字符集,将在与数据库进行通信和读取/写入数据时使用。

MySQL Docs 表示在创建表期间,如果在这些方面没有指定任何内容,则将使用 DB 字符集。这意味着为了使这成为可能,您的数据库(不是 MySQL 服务器)应该这样创建:

create database DB_NAME character set utf8;

之后,您在此数据库中的表应以 utf8 编码创建。与排序规则相同的故事。

当然你不应该依赖 Hibernate 的 hbm2ddl,阅读here 了解更多详情。

【讨论】:

【参考方案5】:

我正在使用 Spring-Data。我已经尝试在 URL 中激活参数:

jdbc:mysql://localhost:3306/DATABASE?createDatabaseIfNotExist=true&amp;useUnicode=true&amp;characterEncoding=utf-8

另外,我已经尝试过使用休眠属性,但最终对我有用的解决方案是@Gray 提出的解决方案

@Bean
@Autowired
public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) 
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl(dbGenerateDdl); 
    vendorAdapter.setShowSql(dbShowSql);
    if (Arrays.asList(environment.getActiveProfiles()).contains("prod"))
        vendorAdapter.setDatabasePlatform(CustomMysqlDialect.class.getName());

    Properties jpaProperties = new Properties();
    jpaProperties.put("hibernate.connection.CharSet", "utf-8");
    jpaProperties.put("hibernate.connection.useUnicode", true);
    jpaProperties.put("hibernate.connection.characterEncoding", "utf-8");

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan("com.example.model");
    factory.setDataSource(dataSource);
    factory.setJpaProperties(jpaProperties);

    return factory;

这条线拯救了我的一天:

vendorAdapter.setDatabasePlatform(CustomMysqlDialect.class.getName());

【讨论】:

【参考方案6】:

对于使用 Spring Boot 的用户:将 characterEncoding=utf8 参数添加到您的 application.properties 文件到此行:

spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase?useUnicode=true&characterEncoding=utf8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=UTC

【讨论】:

【参考方案7】:

如何更改数据库排序规则?

ALTER DATABASE [数据库] CHARACTER SET utf8 COLLATE utf8_unicode_ci;

【讨论】:

【参考方案8】:

通过 Spring Java Config dataSource() 这应该会有所帮助:

@Bean
public DataSource dataSource()     
    BasicDataSource dataSource = new BasicDataSource();    
    //your username/pass props
    dataSource.setConnectionProperties("useUnicode=true;characterEncoding=utf8;characterSetResults=UTF-8;");
    return dataSource;

注意';'在属性字符串的末尾!

【讨论】:

【参考方案9】:

您可以使用 Hibernate @Type 属性,根据您的要求,您可以自定义注释并应用在字段之上。喜欢:

  public class PhoneNumberType implements UserType 
    @Override
    public int[] sqlTypes() 
  return new int[]Types.INTEGER, Types.INTEGER, Types.INTEGER;
    

    @Override
    public Class returnedClass() 
        return PhoneNumber.class;
    

    // other methods
       

一、空SafeGet方法:

    @Override
    public Object nullSafeGet(ResultSet rs, String[] names, 
    SharedSessionContractImplementor session, Object owner) throws HibernateException,                   
      SQLException 
    int countryCode = rs.getInt(names[0]);
     if (rs.wasNull())
        return null;
     int cityCode = rs.getInt(names[1]);
    int number = rs.getInt(names[2]);
    PhoneNumber employeeNumber = new PhoneNumber(countryCode, cityCode, number);
     return employeeNumber;
     

接下来,null SafeSet 方法:

    @Override
     public void nullSafeSet(PreparedStatement st, Object value, 
      int index, SharedSessionContractImplementor session) 
       throws HibernateException, SQLException 
        if (Objects.isNull(value)) 
        st.setNull(index, Types.INTEGER);
         else 
        PhoneNumber employeeNumber = (PhoneNumber) value;
        st.setInt(index,employeeNumber.getCountryCode());
        st.setInt(index+1,employeeNumber.getCityCode());
        st.setInt(index+2,employeeNumber.getNumber());
      
     

最后,我们可以在我们的 OfficeEmployee 实体类中声明我们自定义的 PhoneNumberType:

    @Entity
    @Table(name = "OfficeEmployee")
     public class OfficeEmployee 

      @Columns(columns =  @Column(name = "country_code"), 
      @Column(name = "city_code"), @Column(name = "number") )
      @Type(type = "com.baeldung.hibernate.customtypes.PhoneNumberType")
       private PhoneNumber employeeNumber;

     // other fields and methods
      

这可能会解决您的问题,这将适用于所有数据库。如果您想了解更多信息,请参考 :: https://www.baeldung.com/hibernate-custom-types 同样,您必须进行 UTF-8 编码/解码和 ISO-8859-1 解码/编码

【讨论】:

以上是关于Hibernate + MySQL:如何为数据库和表设置编码 utf-8的主要内容,如果未能解决你的问题,请参考以下文章

如何为 mysqlcluster 创建休眠配置文件?

如何为存储过程编写 Hibernate 映射文件?

如何为 Hibernate 查询集成用户权限/限制?

如何为 sql server 配置休眠配置文件

Java/Hibernate:如何为复杂的 SQL 编写 DAO 代码

如何为连接表中的其他属性创建多对多 Hibernate 映射?