How to get value as String object instead of Character object

In Hibernate 6.3.1.Final, if column is nvarchar(1), then value come as Character object while using session native query. Is there any way to get values as String object instead of Character object ?

You could call toString() on the result or you can construct the native query with the proper result type e.g. session.createNativeQuery( "...", String.class )

We are actually migrating from 5.4.32.Final to 6.3.1.Final. In our application, there are more than 1000 session native queries. In the previous version, the value of nvarchar(1) came as a string object. So we used cast to convert the result to a string. But in the latest version, values are coming as character objects. So it throws a ClassCastException as we are expecting those values to be strings. So is there any way to get a value as a string object? If we use session.createNativeQuery(“…”, String.class), it will only return string results. But there can also be other data types.

So is there any way to get a value as a string object?

There is, but I would recommend you to not do that and instead fix your queries as changing this behavior might be surprising in other scenarios. You can override the Dialect#resolveSqlTypeDescriptor to return a custom VarcharJdbcType/NVarcharJdbcType. These custom JdbcType implementations then override the getJdbcRecommendedJavaTypeMapping method and always return typeConfiguration.getJavaTypeRegistry().getDescriptor(String.class).

If we use session.createNativeQuery(“…”, String.class), it will only return string results. But there can also be other data types.

I don’t know what you mean by “but there can also be other data types”. If you mean to say that you might have multiple select items for which you want to read the values, then you should look into @SqlResultSetMapping.

3 Likes

Hi @beikov ,

Your answer was very helpful. Thanks for a nice explanation. I am stuck in the same situation. But your solution is not working for my case. In my case, I am querying from the external database. Where my application does not have any HBM file to map that database, is it the reason for not Descriptor being working here? If so how to handle this scenario? I don’t want to change much of the code that’s the reason finding for any wrapper solution available or not.

My answer applies just as well for your case. If you don’t like Hibernate ORM treating char(1)/nchar(1) as java.lang.Character, then you will have to provide custom JdbcType implementations that just always return typeConfiguration.getJavaTypeRegistry().getDescriptor(String.class) in getJdbcRecommendedJavaTypeMapping.

Hi @beikov, We already applied this solution, but it is not working for those tables with no HBM file. As my code was using a different session factory we set the configuration property like this:

dialect = "com.test.testDataModel.util.CustomSqlServerDialect";
        prop.setProperty("hibernate.dialect", dialect);
public JdbcType resolveSqlTypeDescriptor(String columnTypeName,
                                             int jdbcTypeCode,
                                             int precision,
                                             int scale,
                                             JdbcTypeRegistry jdbcTypeRegistry) {


        CustomNVarCharJdbcType customNVarcharJdbctype = new CustomNVarCharJdbcType();

        switch ( jdbcTypeCode ) {

            case Types.CHAR:
            case Types.NCHAR:
            case Types.NVARCHAR:
            case Types.VARCHAR:
                jdbcTypeRegistry.addDescriptor(customNVarcharJdbctype);   // converting character to string
                break;                                                    
        }

        return super.resolveSqlTypeDescriptor(
                columnTypeName,
                jdbcTypeCode,
                precision,
                scale,
                jdbcTypeRegistry
        );
    }

Would be please verify and let us know if there is anything we can do to solve the problem?

Write a custom org.hibernate.boot.model.TypeContributor and register your custom JDBC types there via typeContributions.contributeJdbcType(JdbcType). No need for a custom dialect.