我们最近将我们的应用程序从Sping Boot 2.3.9升级到Spring Boot 3.1.0。
这包括从Hibernate 5.4.28.Final升级到6.2.2.Final。
我们正在AWS RDS - 5.7.mysql_aurora.2.11.2中运行MySql-默认数据库编码为latin 1。
升级后我们注意到,所有注解为@Nationalized的String字段都有问题。
我们声明了许多这样的字段:
@Nationalized
private String firstName;
升级前
在Hibernate 5.4.28.Final中,这样的列将在生成的jpa DDL中显示为:
first_name nvarchar(255)
然后在数据库中显示如下:
`first_name` varchar(255) CHARACTER SET utf8 DEFAULT NULL,
升级后
使用Hibernate 6.2.2.final,列现在将显示在生成的jpa DDL中,如下所示:
first_name varchar(255)
然后在数据库中显示如下:
`first_name` varchar(255) DEFAULT NULL,
我将这个问题追踪到org.hibernate.dialect.MySQLDialect第330-341行的代码
final CapacityDependentDdlType.Builder nvarcharBuilder = CapacityDependentDdlType.builder(
NVARCHAR,
columnType( NCLOB ),
"char",
this
)
.withTypeCapacity( getMaxVarcharLength(), "varchar($l)" )
.withTypeCapacity( maxMediumLobLen, "mediumtext" );
if ( getMaxVarcharLength() < maxLobLen ) {
nvarcharBuilder.withTypeCapacity( maxLobLen, "text" );
}
ddlTypeRegistry.addDescriptor( nvarcharBuilder.build() );
字段对象被正确地Map到NVARCHAR的字段类型(类型为-9),但是当查询构建器试图将该列对象转换为字符串表示时,它永远不能选择nvarchar
,因为这甚至不是一个选项。
根据上面的Map,查询Map器仅有的选择是varchar()
、mediumtext
和text
。
我知道我们可以将数据库的默认字符集和排序规则更改为utf8 mb 4,我们可能会采用这种策略,但我正在尝试理解这种更改的目的。
为什么NVARCHAR
只Map到varchar
,特别是当org.hibernate.dialect.NationalizationSupport为mysql方言的时候是EXPLICIT
1条答案
按热度按时间13z8s7eq1#
我在这里与Hibernate团队讨论了这个问题
https://hibernate.zulipchat.com/#narrow/stream/132096-hibernate-user/topic/Hibernate.205.20to.206.20Migration.20Issue
看起来好像Map被无意中更改了,因为MySql 8已经弃用了nvarchar。
hibernate团队同意Map仍然适用于MySql 5.7,并进行了修改以修复它。
https://github.com/hibernate/hibernate-orm/pull/6827
而不是Mapnvarcahr -> nvarchar,修复是Mapnvarchar -> varchar字符集utf8,这将在mysql 5.7和mysql 8上工作。