最近公司项目的Hibernate从3升级到5之后,在调试过程中发现,MYSQL数据库下,使用原生SQL语句查询的结果字段名从原来的大写变成了小写。
比如表中的字段名为 “TEST_NAME” ,我们使用“select test_name from test_table ”进行查询,之前3版本的时候返回的字段名为 “TEST_NAME” ,但是升级到5之后返回的字段名为 “test_name” ,由于代码中很多地方使用的是大写名称获取结果值,改代码不现实,后来检查3版本和5版本的源码,发现问题所在。
hibernate3版本中获取字段名的代码
public String getColumnName(int position) throws HibernateException {
try {
return this.resultSetMetaData.getColumnName(position);
} catch (SQLException var3) {
throw new HibernateException("Could not resolve column name [" + position + "]", var3);
}
}
这段代码在CustomLoader.Metadata类中,resultSetMetaData对象为mysql驱动封装的查询结果的元数据,包含表和字段等信息。
接下来看看hibernate5版本中获取字段名的代码
public String getColumnName(int position) throws HibernateException {
try {
return this.factory.getDialect().getColumnAliasExtractor().extractColumnAlias(this.resultSetMetaData, position);
} catch (SQLException var3) {
throw new HibernateException("Could not resolve column name [" + position + "]", var3);
}
}
5版本中获取字段的代码在JdbcResultMetadata类中,可以看到5版本是通过数据库方言类配置的字段名采集器ColumnAliasExtractor来获取字段名,项目中配置的方言类为MySQL57Dialect,使用的是默认字段名采集器
public ColumnAliasExtractor getColumnAliasExtractor() {
return ColumnAliasExtractor.COLUMN_LABEL_EXTRACTOR;
}
COLUMN_LABEL_EXTRACTOR对象为匿名内部类
public static final ColumnAliasExtractor COLUMN_LABEL_EXTRACTOR = new ColumnAliasExtractor() {
@Override
public String extractColumnAlias(ResultSetMetaData metaData, int position) throws SQLException {
return metaData.getColumnLabel( position );
}
};
好了,问题就出在这里
3版本使用的是getColumnName(position)获取字段名,而5版本则使用的是getColumnLabel(position)方法。
找到问题后就很好解决了,我们自定义的一个方言类,然后继承MySQL57Dialect,然后重写getColumnAliasExtractor()方法,返回我们自定义的字段名采集器,比如这样:
@Override
public ColumnAliasExtractor getColumnAliasExtractor() {
return new ColumnAliasExtractor() {
@Override
public String extractColumnAlias(ResultSetMetaData metaData, int position) throws SQLException {
return metaData.getColumnName(position);
}
};
}
使用getColumnName(position)方法获取字段名,这样获取的就是我们想要的正确字段名。