'Upgrade to Hibernate 5, physical naming strategy is not working

We are in the process of upgrading to Hibernate 5.5.7 from Hibernate 3. The issue I'm encountering now concerns Hibernate's physical naming strategy. In addition, we're also upgrading Spring to 5.3.10

As I understand it, Hibernate 5 uses a two part mechanism for mapping entity fields to physical columns. (There are other mappings, but field to column mapping is what I'm focused on.)

  1. implicit naming strategy: resolves the field name into a logical name. If the name attribute in the Column annotation is provided, this becomes the explicit logical name.
  2. physical naming strategy: This maps the logical name produced above to the physical name used in the database.

Based on the this, I found the following in the Hibernate documentation confirming the physical naming strategy should always work, regardless on how the logical name was produced:

It is true that the resolution to acct_num could have been handled using an ImplicitNamingStrategy in this case.

But the point here is the separation of concerns. The PhysicalNamingStrategy will be applied regardless of whether the attribute explicitly specified the column name or whether we determined that implicitly. The ImplicitNamingStrategy would only be applied if an explicit name was not given. So, it all depends on needs and intent.

So, this (finally) leads me to my question. I can't figure out why the physical_naming_strategy isn't working. Given the entity structure below:

Item.java:

@Entity
@Table(name = "catalogue_item")
@Proxy(lazy = true)
@BatchSize(size = 100)
@Access(AccessType.FIELD)
public class Item extends CatalogObject implements DeepCloneable, AttributeGroup {
private static Log LOG = LogFactory.getLog(Item.class);

private static final int MIN_GROUP_INDCATOR_VALUE = getDefaultGroupIndicatorValue();

@Column(name = "groupIndicator", nullable = false, insertable = true, updatable = true)
private int groupIndicator = MIN_GROUP_INDCATOR_VALUE;

@Column(name = "UPC_TBL_NBR", nullable = false, insertable = true, updatable = false)
private Integer upcTableNumber;

@Embedded
private ItemIdentifier itemIdentifier;

@Transient
private Long productId;

@Column(name = "product_name", insertable = true, updatable = true)
private String productName;

@ManyToOne(targetEntity = com.qrs.catalog.dal.crux.keystone.SelectionCodeImpl.class)
@JoinColumn(name = "selcode")
private SelectionCode selcode;

@Column(name = "selcode_name", insertable = true, updatable = true)
private String selcodeName;

@Transient
private AttributeFilter attributeFilter;

@Embedded
private CommonRetailGroup commonRetailGroup = new CommonRetailGroup();
    
public Item() {
}

public Item(ItemIdentifier itemIdentifier) {
    this.itemIdentifier = itemIdentifier;
}

...snipped...

CommonRetailGroup.java:

@Embeddable
@Access(AccessType.FIELD)
public class CommonRetailGroup extends AbstractComponentAttributeGroup {


   @Embedded
   private PrepackCode prepackCode;

   @Embedded
   private NrfColorCode nrfColorCode;

   @Embedded
   private ColorDescription colorDescription;
   ...snipped...

NRFColorCode.java:

@Embeddable
@Access(AccessType.FIELD)
public class NrfColorCode extends AbstractAttribute {


   @Column(name="nrfColorCodeVal", length=3)
   private Integer nrfColorCodeValue;

   @Temporal(value=TemporalType.TIMESTAMP)
   @Column(name="nrfColorCodeUdtDt")
   private Date nrfColorCodeUpdated;

   public NrfColorCode() {
   }
   ...snipped...

and the applicationContext.xml:

<bean id="dataSourceTarget" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="oracle.jdbc.driver.OracleDriver"/>
    <property name="jdbcUrl" value="jdbc:oracle:thin:@@db.host@:@db.port@:@db.sid@"/>
    <property name="user" value="@db.username@"/>
    <property name="password" value="@db.password@"/>
    <property name="maxPoolSize" value="${db.pooled.connections.max}"/>
    <property name="initialPoolSize" value="${db.pooled.connections.min}"/>
    <property name="maxIdleTime" value="1000"/>
    <property name="connectionTesterClassName" value="com.mchange.v2.c3p0.impl.DefaultConnectionTester"/>
    <property name="testConnectionOnCheckout" value="true"/>
    <property name="acquireIncrement" value="${db.pooled.connections.min}"/>
</bean>

<bean id="dataSource" class="com.qrs.catalog.dal.crux.CatalogDataSourceWrapper">
    <constructor-arg ref="dataSourceTarget"/>
    <constructor-arg><value>${sql.slowQueryMillis}</value></constructor-arg>
    <constructor-arg><value>${sql.excessiveQueryMillis}</value></constructor-arg>
</bean>

<bean id="sessionFactory" class="com.qrs.catalog.dal.OpenTextSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="annotatedClasses">
        <list>
            <value>com.qrs.catalog.dal.crux.CatalogObject</value>
            <value>com.qrs.catalog.dal.crux.CatalogId</value>
            ...snipped for brevity...
            <value>com.qrs.catalog.dal.crux.AttributesAnalytics</value>
            <value>com.qrs.catalog.dal.crux.dmdb2.TbmTpcBillMstr</value>
            <value>com.qrs.catalog.dal.crux.dmdb2.TbtTpcBillTrans</value>
        </list>
    </property>
    <property name="mappingResources">
        <list>
            <value>com/qrs/catalog/dal/crux/keystone/BarCode.hbm.xml</value>
        </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.show_sql">false</prop>
            <prop key="hibernate.cache.use_query_cache">true</prop>
            <prop key="hibernate.max_fetch_depth">0</prop>
            <prop key="hibernate.cache.use_second_level_cache">true</prop>
            <prop key="hibernate.cache.region.factory_class">ehcache</prop>
            <prop key="hibernate.implicit_naming_strategy">org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl</prop>
            <prop key="hibernate.physical_naming_strategy">com.qrs.catalog.dal.crux.CustomOracleNamingStrategy</prop>
            <prop key="hibernate.connection.release_mode">auto</prop>
            <prop key="hibernate.dialect">com.qrs.catalog.dal.crux.OracleCustomDialect</prop>
            <prop key="hibernate.query.factory_class">com.qrs.catalog.dal.crux.SmartQueryTranslatorFactory</prop>
            <prop key="hibernate.jdbc.use_scrollable_resultset">true</prop>
        </props>
    </property>
    <property name="entityInterceptor" ref="customNullsFirstInterceptor"/>
</bean>
...snipped for brevity...

I'm still obxerving the following query, snipped for brevity:

... Sql = select distinct item0_.nrfColorCodeVal as col_0_0_, item0_.colorDescVal as col_1_0_ ...

I've even added a hibernate.properties file, to no avail:

hibernate.show_sql=false
hibernate.cache.use_query_cache=true
hibernate.max_fetch_depth=0
hibernate.cache.use_second_level_cache=true
hibernate.cache.region.factory_class=ehcache
hibernate.implicit_naming_strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
hibernate.physical_naming_strategy=com.qrs.catalog.dal.crux.CustomOracleNamingStrategy
hibernate.connection.release_mode=auto
hibernate.dialect=com.qrs.catalog.dal.crux.OracleCustomDialect
hibernate.jdbc.use_scrollable_resultset=true

I've written a custom naming strategy, as well at using the hibernate CamelCaseToUnderscoreNamingStrategy, to no avail. The only way I can get it to work is to force the @Column name attribute to "nrf_color_code_value". However, this defeats the purpose of the physical naming strategy in the first place.

Thank you for any help on this.

-randy



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source