solidjb
solidjb

Reputation: 114

Column marked with @Nationalized not mapping to correct column type with Hibernate 6.2.2 and MySql 5.7

We recently upgraded our application from Spring Boot 2.3.9 to Spring Boot 3.1.0.

This included an upgrade from Hibernate 5.4.28.Final to 6.2.2.Final.

We are running MySql in AWS RDS - 5.7.mysql_aurora.2.11.2 - The default database encoding is latin1.

We noticed after the upgrade that all of the String fields that were annotated as @Nationalized had an issue.

We declared many fields like this:

@Nationalized
private String firstName;

Before Upgrade

With Hibernate 5.4.28.Final, columns like this would show up in the generated jpa DDL like this:

first_name nvarchar(255)

And then show up in the database like this:

`first_name` varchar(255) CHARACTER SET utf8 DEFAULT NULL,

After Upgrade

With Hibernate 6.2.2.final, columns would now show up in the generated jpa DDL like this:

first_name varchar(255)

And then show up in the database like this:

`first_name` varchar(255) DEFAULT NULL,

I tracked this down issue down to the code in org.hibernate.dialect.MySQLDialect lines 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() );

The field objects are correctly being mapped to the field type of NVARCHAR (with type -9), but when the query builder tries to turn that column object into its string representation, it can never pick nvarchar because that isn't even an option.

The only choices the query mapper has is varchar(), mediumtext and text based upon the mapping above.

I know we can change the default character set and collation of our database to be utf8mb4, and we may pursue that strategy, but I am trying to understand the purpose of this change.

Why would NVARCHAR only map to varchar especially when the org.hibernate.dialect.NationalizationSupport for the mysql dialect is EXPLICIT

Upvotes: 2

Views: 363

Answers (1)

solidjb
solidjb

Reputation: 114

I discussed this with the Hibernate team here

https://hibernate.zulipchat.com/#narrow/stream/132096-hibernate-user/topic/Hibernate.205.20to.206.20Migration.20Issue

It appears as though the mapping was inadvertently changed because MySql 8 has deprecated nvarchar.

The hibernate team agreed that the mapping should still work for MySql 5.7, and made a change to fix it.

https://github.com/hibernate/hibernate-orm/pull/6827

Instead of mapping nvarcahr -> nvarchar, the fix is to map nvarchar -> varchar character set utf8, which will work on both mysql 5.7 and mysql 8.

Upvotes: 1

Related Questions