Now, I’m using hibernate(5.6) through springbootjpa(2.7.4), and I have encountered a problem. In a case sensitive database (even column names), I annotated a property with @Column annotation and gave an uppercase column names, but in Hibernate, it was converted to lowercase.
I checked the source code and found that in the Ejb3Column class, the explicitly specified column names have been converted by PhysicalNamingStrategy; By default, SpringPhysicalNamingStrategy is used in springboot, which always converts column names to lowercase.
Ejb3Column.java
public void redefineColumnName(String columnName, String propertyName, boolean applyNamingStrategy) {
...
if ( applyNamingStrategy ) {
if ( StringHelper.isEmpty( columnName ) ) {
// there is no @Column annotationed
...
//Do nothing otherwise
}
else {
final Identifier explicitName = database.toIdentifier( columnName );
final Identifier physicalName = physicalNamingStrategy.toPhysicalColumnName( explicitName, database.getJdbcEnvironment() ); // HERE!!!, the explicitColumnName has been converted
mappingColumn.setName( physicalName.render( database.getDialect() ) );
}
}
else {
if ( StringHelper.isNotEmpty( columnName ) ) {
mappingColumn.setName( normalizer.toDatabaseIdentifierText( columnName ) );
}
}
}
SpringPhysicalNamingStrategy.java
public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment jdbcEnvironment) {
return apply(name, jdbcEnvironment);
}
private Identifier apply(Identifier name, JdbcEnvironment jdbcEnvironment) {
if (name == null) {
return null;
}
StringBuilder builder = new StringBuilder(name.getText().replace('.', '_'));
for (int i = 1; i < builder.length() - 1; i++) {
if (isUnderscoreRequired(builder.charAt(i - 1), builder.charAt(i), builder.charAt(i + 1))) {
builder.insert(i++, '_');
}
}
return getIdentifier(builder.toString(), name.isQuoted(), jdbcEnvironment);
}
protected Identifier getIdentifier(String name, boolean quoted, JdbcEnvironment jdbcEnvironment) {
if (isCaseInsensitive(jdbcEnvironment)) {
name = name.toLowerCase(Locale.ROOT); // HERE!!! lowercase
}
return new Identifier(name, quoted);
}
protected boolean isCaseInsensitive(JdbcEnvironment jdbcEnvironment) {
return true;
}
So, why not directly using the explicit-name without converting by naming-strategy for those columns which are annotated by @Column with name=”Col_NAME”?
Just comment the line.
// final Identifier physicalName = physicalNamingStrategy.toPhysicalColumnName( explicitName, database.getJdbcEnvironment() );