javahibernate

Initial SessionFactory creation failed - org.hibernate.MappingException: An association from the table X refers to an unmapped class: Y


I am migrating application from Hibernate 4 to Hibernate 5. I can't win with naming strategy. Of course I have already read: hibernate ImprovedNamingStrategy overrides Table name in entity and ImprovedNamingStrategy no longer working in Hibernate 5

In hibernate.cfg.xml I have both:

<mapping resource="com/ubs/investor/cpss/domain/BonusHis.hbm.xml"/>
<mapping resource="com/ubs/investor/cpss/domain/Instrument.hbm.xml"/>

I already changed AnnotationConfiguration to Configuration and now I have:

private void reloadHibernateSessionFactoryFromConf(Map<String, String> prop) {
        try {
            sessionFactory = null;
            Configuration config = new Configuration(); //hibernate5

            for(Map.Entry<String, String> entry : prop.entrySet()) {
                config.setProperty(entry.getKey(), entry.getValue());
            }
            if(namingStrategy!=null){
                configuration.setNamingStrategy(namingStrategy); //code which I think spoil application
            }
            if(annotatedEntityPackages!=null){
                addAnnotatedClasses(config);
            }
            sessionFactory = config.configure().buildSessionFactory();
        } catch (final HibernateException e) {
            LOGGER.error("SessionFactory creation failed", e);
        }

and namingStrategy was put by:

<property name="namingStrategy">
            <bean class="org.hibernate.cfg.ImprovedNamingStrategy"/>
        </property>

I already tried to comment configuration.setNamingStrategy(namingStrategy); at all. I tried configuration.setPhysicalNamingStrategy(PhysicalNamingStrategyImpl.INSTANCE); but also CamelCase, UpperCase etc. and everytime error is the same. Whatever I do with this namingStrategy class won't be mapped.

Example class:

public class UpperCaseNamingStrategy extends PhysicalNamingStrategyStandardImpl {

    @Override
    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
        return context.getIdentifierHelper().toIdentifier(
                StringUtils.upperCase(name.getText(), Locale.ENGLISH));
    }

    @Override
    public Identifier toPhysicalCatalogName(final Identifier name, final JdbcEnvironment context) {
        return context.getIdentifierHelper().toIdentifier(
                StringUtils.upperCase(name.getText(), Locale.ENGLISH));
    }

    @Override
    public Identifier toPhysicalSchemaName(final Identifier name, final JdbcEnvironment context) {
        return context.getIdentifierHelper().toIdentifier(
                StringUtils.upperCase(name.getText(), Locale.ENGLISH));
    }

    @Override
    public Identifier toPhysicalSequenceName(final Identifier name, final JdbcEnvironment context) {
        return context.getIdentifierHelper().toIdentifier(
                StringUtils.upperCase(name.getText(), Locale.ENGLISH));
    }

    @Override
    public Identifier toPhysicalTableName(final Identifier name, final JdbcEnvironment context) {
        return context.getIdentifierHelper().toIdentifier(
                StringUtils.upperCase(name.getText(), Locale.ENGLISH));
    }

}

but still I can see in logs:

org.hibernate.MappingException: An association from the table BONUS_HIS refers to an unmapped class: domain.Instrument at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:709) at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:746) at repository.legacy.HibernateSessionManager.reloadHibernateSessionFactoryFromConf

So what is implementation of org.hibernate.cfg.ImprovedNamingStrategy in hibernate 5?

@Edit

Actually I used:

public class PhysicalNamingStrategyImpl extends PhysicalNamingStrategyStandardImpl implements Serializable {

    public static final PhysicalNamingStrategyImpl INSTANCE = new PhysicalNamingStrategyImpl();

    @Override
    public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) {
        return new Identifier(addUnderscores(name.getText()), name.isQuoted());
    }
   
    protected static String addUnderscores(String name) {
        final StringBuilder buf = new StringBuilder( name.replace('.', '_') );
        for (int i=1; i<buf.length()-1; i++) {
            if (
                    Character.isLowerCase( buf.charAt(i-1) ) &&
                            Character.isUpperCase( buf.charAt(i) ) &&
                            Character.isLowerCase( buf.charAt(i+1) )
            ) {
                buf.insert(i++, '_');
            }
        }
        return buf.toString().toLowerCase(Locale.ROOT);
    }
}

and completely removed:

<property name="namingStrategy">
     <bean class="org.hibernate.cfg.ImprovedNamingStrategy"/>
</property>

but I don't think it's correct solutions because I can still see: org.hibernate.MappingException: An association from the table BONUS_HIS refers to an unmapped class: domain.Instrument


Solution

  • When using a mixed approach with annotations and XML, it is crucial to follow the correct order for creating the SessionFactory to avoid issues. The correct sequence is as follows:

    Initialize the Configuration object:

    Configuration config = new Configuration();
    

    Add the annotated classes:

    addAnnotatedClasses(config);
    

    Build the SessionFactory:

    sessionFactory = config.buildSessionFactory();
    

    If this order is not followed, the XML configurations may override the annotations, leading to potential conflicts and errors.