Spring引导 - JPA Hibernate - Mysql UTF8引起:com.mysql.jdbc.MysqlDataTruncation:数据截断:列

时间:2017-01-25 12:47:58

标签: java spring hibernate utf-8 spring-data-jpa

我的Windows机器上的MySql 5.7 Spring boot 1.4.0 RELEASE mysql jdbc驱动程序是5.1.39

我有一个表,有几个VARCHAR列,它们都设置为VARCHAR(100)。 对于表格,编码设置为:ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

我已经确认如果我使用MYSql Workbench,我可以插入100个非英文字符(例如中文)。

现在我的java代码中,我要插入的字段是西班牙语字符串,getBytes().length返回115,因此它是115字节。

由于DB中的字段是100个字符,我认为插入115字节的字符串应该不是问题。但这是我的问题,我得到了这个:

Caused by: com.mysql.jdbc.MysqlDataTruncation: Data truncation: Data too long for column 'addr1' at row 1

我尝试将useUnicode=true&connectionCollation=utf8_general_ci&characterSetResults=utf-8&characterEncoding=utf-8添加到网址,尝试添加connectionProperty useUnicode=true;characterEncoding=utf-8;到我的application.yaml等,没有运气

然后我将@EnableAutoConfiguration更改为@Configuration并添加此内容:

@Bean
public DataSource datasource() {
    org.apache.tomcat.jdbc.pool.DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource();
    ds.setDriverClassName(databaseDriverClassName);
    ds.setUrl(datasourceUrl);
    ds.setUsername(databaseUsername);
    ds.setPassword(databasePassword);
    ds.setConnectionProperties("useUnicode=true;characterEncoding=utf-8;");
    ds.setInitSQL("SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci';");

    return ds;

}

@Bean
public EntityManagerFactory entityManagerFactory() {
    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    vendorAdapter.setGenerateDdl(false);

    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setJpaVendorAdapter(vendorAdapter);
    factory.setPackagesToScan("com.xxx.xxx.entity");
    Properties properties = new Properties();
    properties.setProperty("hibernate.connection.useUnicode", "true");
    properties.setProperty("hibernate.connection.charSet", "utf8mb4");
    properties.setProperty("hibernate.connection.characterEncoding", "utf8mb4");
    properties.setProperty("hibernate.id.new_generator_mappings", "false");
    factory.setJpaProperties(properties);
    factory.setDataSource(datasource());
    factory.afterPropertiesSet();

    return factory.getObject();
}

仍然有同样的事情!

我现在花了两天时间...... :(我认为一定是一个简单的错误,但错误是什么?

由于

编辑:尝试通过调用存储库界面来保存记录,它工作正常!所以问题是调用entitymanager.merge()。是否需要为实体管理器设置任何属性来处理UTF8?

编辑:我添加了更多调试代码,现在问题似乎与JPA或hibernate无关......

我得到的字符串来自对SOAP magento SOAP API的SOAP调用。这是我现在的代码:

    String s = "其次受影响较大的是金融体系,过去那么多年金融体系受益于低利率、信贷宽松、影子银行大扩张等,金融企业疯狂的扩张资产负债表,一个个都赚的钵满盆满(看看过去数年金融企业的疯狂高利润和增速,从业人员增速和工";
    salesOrderModel.setAddr1(s);

    try {
        System.out.println(s + ", " + "[" + s.length() + "][" + s.getBytes("UTF-8").length + "]");
    } catch (Exception e) {
        e.printStackTrace();
    }

使用上面的代码,entitymanager.merge()没有问题,数据被插入到数据库中,这就是系统输出:

其次受影响较大的是金融体系,过去那么多年金融体系受益于低利率、信贷宽松、影子银行大扩张等,金融企业疯狂的扩张资产负债表,一个个都赚的钵满盆满(看看过去数年金融企业的疯狂高利润和增速,从业人员增速和工, [99][297]

现在,如果我注释掉B1和B2,并取消注释A1和A2:

salesOrderModel.setAddr1(address.getStreet());
    String s = address.getStreet();


    try {
        System.out.println(s + ", " + "[" + s.length() + "][" + s.getBytes("UTF-8").length + "]");
    } catch (Exception e) {
        e.printStackTrace();
    }

我收到了帖子开头提到的异常,这是系统输出:

Plaça Pla de L'Estany, 5, Edificio Vueling Airlines S.A., [113][115]

字符串长度为113.

如果我这样做:

String s = "Plaça Pla de L'Estany, 5, Edificio Vueling Airlines S.A.";

输出是:

Plaça Pla de L'Estany, 5, Edificio Vueling Airlines S.A., [56][57]

现在字符串长度为56(对比113)。为什么呢?

1 个答案:

答案 0 :(得分:0)

终于我终于找到了问题,我的愚蠢错误!

该字符串对于该字段来说确实太长了。基本上该字符串包含两行Plaça Pla de L'Estany, 5, Edificio Vueling Airlines S.A.,直到现在我才注意到它。

我的坏!