1
votes

Microsoft SQL Server, column in database is defined as NVARCHAR, but in Java code defined as @Column(name = "Column_Name", columnDefinition = "VARCHAR").

Hibernate fails with validation error below:

Caused by: org.hibernate.tool.schema.spi.SchemaManagementException: Schema-validation: wrong column type encountered in column [Column_Name] in table [Table_Name]; found [nvarchar (Types#NVARCHAR)], but expecting [varchar (Types#VARCHAR)] at org.hibernate.tool.schema.internal.SchemaValidatorImpl.validateColumnType(SchemaValidatorImpl.java:105) ~[hibernate-core-5.0.12.Final.jar:5.0.12.Final]

That would be no surprise, but reverse way (database VARCHAR, code NVARCHAR) does pass without errors.

This sounds illogical, I think that VARCHAR definition in code with NVARCHAR in database could work because there is no expected Unicode data loss, and NVARCHAR in code with VARCHAR in database should be validation error because that way there can be Unicode data loss.

Is there a reason for such strange validation behavior?

1
Loss depends on the direction - paparazzo
Yes, and from validation behavior the direction seems to be wrong. - weidox

1 Answers

1
votes
public class SQLServerUnicodeDialect extends org.hibernate.dialect.SQLServerDialect {
    public SQLServerUnicodeDialect() {
        super();
        registerColumnType(Types.CHAR, "nchar(1)");
        registerColumnType(Types.LONGVARCHAR, "nvarchar(max)" );
        registerColumnType(Types.VARCHAR, 4000, "nvarchar($l)");
        registerColumnType(Types.VARCHAR, "nvarchar(max)");
        registerColumnType(Types.CLOB, "nvarchar(max)" );

        registerColumnType(Types.NCHAR, "nchar(1)");
        registerColumnType(Types.LONGNVARCHAR, "nvarchar(max)");
        registerColumnType(Types.NVARCHAR, 4000, "nvarchar($l)");
        registerColumnType(Types.NVARCHAR, "nvarchar(max)");
        registerColumnType(Types.NCLOB, "nvarchar(max)");

        registerHibernateType(Types.NCHAR, StandardBasicTypes.CHARACTER.getName());
        registerHibernateType(Types.LONGNVARCHAR, StandardBasicTypes.TEXT.getName());
        registerHibernateType(Types.NVARCHAR, StandardBasicTypes.STRING.getName());
        registerHibernateType(Types.NCLOB, StandardBasicTypes.CLOB.getName() );
    }
}

try this code, in the registerColumnType put the paramter types.NVARCHAR