Kirill
Kirill

Reputation: 1610

Hibernate ImprovedNamingStrategy doesn't work

I have a database with columns naming using snakecase and entities where columns named in camelcase. The project was written using spring boot and had this configuration:

    @Primary
    @Bean
    public LocalContainerEntityManagerFactoryBean mainEntityManagerFactory(
            @Qualifier("mainDataSource") DataSource mainDataSource,
            @Qualifier("mainJpaProperties") JpaProperties mainJpaProperties) {

        AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
        adapter.setShowSql(mainJpaProperties.isShowSql());
        adapter.setDatabase(mainJpaProperties.getDatabase());
        adapter.setDatabasePlatform(mainJpaProperties.getDatabasePlatform());
        adapter.setGenerateDdl(mainJpaProperties.isGenerateDdl());

        Map<String, Object> jpaProperties = new HashMap<>();
        jpaProperties.putAll(mainJpaProperties.getHibernateProperties(mainDataSource));
        jpaProperties.put("jpa.hibernate.naming_strategy", "org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy");

        return new EntityManagerFactoryBuilder(adapter, mainJpaProperties, persistenceUnitManager)
                .dataSource(mainDataSource)
                .packages(Employee.class)
                .properties(jpaProperties)
                .persistenceUnit("main")
                .jta(false)
                .build();
    }

this is application.properties content:

jpa.hibernate.hbm2ddl.auto=none
jpa.hibernate.ddlAuto=none
jpa.hibernate.naming_strategy = org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy
jpa.generateDdl=false
jpa.showSql=false
jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQL9Dialect

Now I can't use spring boot and trying to convert configuration:

@Primary
@Bean
public LocalContainerEntityManagerFactoryBean mainEntityManagerFactory(
    @Qualifier("mainDataSource") DataSource mainDataSource
) {
    AbstractJpaVendorAdapter adapter = new HibernateJpaVendorAdapter();
    adapter.setShowSql(Boolean.valueOf(environment.getProperty("jpa.showSql")));
    adapter.setDatabase(Database.POSTGRESQL);
    adapter.setDatabasePlatform(environment.getProperty("jpa.hibernate.dialect"));
    adapter.setGenerateDdl(Boolean.valueOf(environment.getProperty("jpa.generateDdl")));

    Properties jpaProperties = new Properties();
    jpaProperties.put("jpa.hibernate.dialect", environment.getProperty("jpa.hibernate.dialect"));
    jpaProperties.put("hibernate.naming_strategy", "main.util.NamingStrategy");


    LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
    factoryBean.setDataSource(mainDataSource);
    factoryBean.setJpaVendorAdapter(adapter);
    factoryBean.setPersistenceUnitName("main");
    factoryBean.setPersistenceUnitManager(persistenceUnitManager);
    factoryBean.setJpaProperties(jpaProperties);
    factoryBean.setPackagesToScan(packageToScan);

    factoryBean.afterPropertiesSet();

    return factoryBean;
}

main.util.NamingStrategy is just a copypaste of org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy.

When I trying to run it it looks like that this naming strategy doesn't work because I get an error:

org.hibernate.AnnotationException:
Unable to create unique key constraint (emp_address_id, year, yearNumber)
on table employeedata:
database column 'emp_address_id' not found.
Make sure that you use the correct column name which depends
on the naming strategy in use
(it may not be the same as the property name in the entity,
especially for relational types)

How can I make this work without spring boot?

Upvotes: 3

Views: 2886

Answers (2)

jumping_monkey
jumping_monkey

Reputation: 7829

Just to put it explicitly(as i had to spend some time figuring it out from Maciej's answer), this works for me on Hibernate 5.x:

properties.put("hibernate.physical_naming_strategy", "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");

Upvotes: 3

Maciej Marczuk
Maciej Marczuk

Reputation: 3733

jpa.hibernate.naming_strategy property key is used only in Spring Boot's configuration.

When you configure hibernate by yourself you should use Hibernate properties instead. Proper name of Hibernate naming strategy property key is hibernate.ejb.naming_strategy

Try to replace it in your jpaProperties object:

Properties jpaProperties = new Properties();
jpaProperties.put("hibernate.dialect", environment.getProperty("jpa.hibernate.dialect")); //jpa dialect property key is different too
jpaProperties.put("hibernate.ejb.naming_strategy", "main.util.NamingStrategy");

List of all miscellaneous properties:

https://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html_single/#configuration-misc-properties

I am assuming that you only removed Spring Boot and you are still using Hibernate 4.x (in Hibernate 5.x NamingStrategy was replaced with ImplicitNamingStrategy and PhysicalNamingStrategy)

For hibernate 5.x you should use org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNam‌​ingStrategy and default Hibernate's ImplicitNamingStrategy:

https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.4-Release-Notes#naming-strategy

Configuration key for this physical naming strategy is: hibernate.physical_naming_strategy

Upvotes: 2

Related Questions