Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use snake case in Spring JPA Hibernate

I hava to configure hibernate jpa manually in my spring boot project because there are 2 datasources I need to references. One of the JPA bean configuration is as belows:

@Configuration
@EntityScan("com.channeljin.common.data.entities.user")
@EnableJpaRepositories(
        entityManagerFactoryRef = "userEntityManagerFactory",
        transactionManagerRef = "userTransactionManager",
        basePackages = "com.channeljin.common.data.repo.user")
public class UserDatasourceConfig {

    @Autowired
    private UserDatasourceProperties properties;

    @Bean
    public DataSource userDatasource() {
        PoolProperties poolProperties = new PoolProperties();
        poolProperties.setDriverClassName("com.mysql.jdbc.Driver");
        poolProperties.setUrl(properties.getUrl());
        poolProperties.setUsername(properties.getUsername());
        poolProperties.setPassword(properties.getPassword());
        org.apache.tomcat.jdbc.pool.DataSource ds = new org.apache.tomcat.jdbc.pool.DataSource();
        ds.setPoolProperties(poolProperties);
        return ds;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean userEntityManagerFactory() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(false);
        Map<String, String> properties = new HashMap<>();
//        properties.put("hibernate.implicit_naming_strategy",
//                "org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl");
//        properties.put("hibernate.physical_naming_strategy",
//                "org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl");
        properties.put("hibernate.show_sql", "true");
        LocalContainerEntityManagerFactoryBean factoryBean =
                new LocalContainerEntityManagerFactoryBean();
        factoryBean.setDataSource(userDatasource());
        factoryBean.setPackagesToScan("com.channeljin.common.data.entities.user");
        factoryBean.setJpaVendorAdapter(vendorAdapter);
        factoryBean.getJpaPropertyMap().putAll(properties);
        return factoryBean;
    }

    @Bean
    public PlatformTransactionManager userTransactionManager() {
        return new JpaTransactionManager(userEntityManagerFactory().getObject());
    }
}

The problem is that the entity's camelCase field like 'createTime' not be translated to snake_case field like 'create_time' in final generated SQL. I don't want to use the @Columnannotation and I prefer the default naming strategy way. So what the naming strategy I should use? The comment line in code above seems not work.

UPDATE :I googled and it seems that the org.hibernate.cfg.ImprovedNamingStrategy will change the camelCase to snake_case but it target the Hibernate4 but the latest Spring boot uses Hibernate5.

like image 829
Guisong He Avatar asked Sep 15 '17 07:09

Guisong He


1 Answers

After debugging I figured out I should use the Spring's naming stragegies: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy. And the complete bean definition here for copy & paste guys.

@Bean
    public LocalContainerEntityManagerFactoryBean userEntityManagerFactory() {
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        vendorAdapter.setGenerateDdl(false);
        Map<String, String> properties = new HashMap<>();
        properties.put("hibernate.implicit_naming_strategy",
                "org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy");
        properties.put("hibernate.physical_naming_strategy",
                "org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy");
        properties.put("hibernate.show_sql", "true");
        LocalContainerEntityManagerFactoryBean factoryBean = new LocalContainerEntityManagerFactoryBean();
        factoryBean.setDataSource(userDatasource());
        factoryBean.setPackagesToScan("com.channeljin.common.data.entities.user");
        factoryBean.setJpaVendorAdapter(vendorAdapter);
        factoryBean.getJpaPropertyMap().putAll(properties);
        return factoryBean;
    }
like image 139
Guisong He Avatar answered Sep 26 '22 15:09

Guisong He