I have simple spring-jpa configuration where I have configured Hibernate's ImprovedNamingStrategy
. This means if my entity class has a variable userName
, then Hibernate should convert it to user_name
for querying the database. But this naming conversion stopped working after I upgraded to Hibernate 5. I am getting the error:
ERROR: Unknown column 'user0_.userName' in 'field list'
This is my Hibernate config:
@Configuration @EnableJpaRepositories("com.springJpa.repository") @EnableTransactionManagement public class DataConfig { @Bean public DataSource dataSource(){ DriverManagerDataSource ds = new DriverManagerDataSource(); ds.setDriverClassName("com.mysql.jdbc.Driver"); ds.setUrl("jdbc:mysql://localhost:3306/test"); ds.setUsername("root"); ds.setPassword("admin"); return ds; } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory(){ HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); vendorAdapter.setShowSql(Boolean.TRUE); vendorAdapter.setDatabase(Database.MYSQL); LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setJpaVendorAdapter(vendorAdapter); factory.setDataSource(dataSource()); factory.setPackagesToScan("com.springJpa.entity"); Properties jpaProperties = new Properties(); jpaProperties.put("hibernate.ejb.naming_strategy","org.hibernate.cfg.ImprovedNamingStrategy"); jpaProperties.put("hibernate.dialect","org.hibernate.dialect.MySQL5InnoDBDialect"); factory.setJpaProperties(jpaProperties); factory.afterPropertiesSet(); return factory; } @Bean public SharedEntityManagerBean entityManager() { SharedEntityManagerBean entityManager = new SharedEntityManagerBean(); entityManager.setEntityManagerFactory(entityManagerFactory().getObject()); return entityManager; } @Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager txManager = new JpaTransactionManager(); txManager.setEntityManagerFactory(entityManagerFactory().getObject()); return txManager; } @Bean public ImprovedNamingStrategy namingStrategy(){ return new ImprovedNamingStrategy(); } }
This is my Entity class:
@Getter @Setter @Entity @Table(name="user") public class User{ @Id @GeneratedValue private Long id; private String userName; private String email; private String password; private String role; }
I don't want to explicitly name my database fields within the @Column annotations. I want my configuration which can implicitly convert camel case to underscore.
Please guide.
Thanks for posting your own solution. It helps me so much to set Hibernate 5 naming strategy!
The hibernate.ejb.naming_strategy
property of pre-Hibernate 5.0 seems split into two parts:
hibernate.physical_naming_strategy
hibernate.implicit_naming_strategy
The values of these properties do not implement the NamingStrategy
interface as did hibernate.ejb.naming_strategy
. There are two new interfaces for these purposes:
org.hibernate.boot.model.naming.PhysicalNamingStrategy
org.hibernate.boot.model.naming.ImplicitNamingStrategy
Hibernate 5 provides only one implementation of PhysicalNamingStrategy
(PhysicalNamingStrategyStandardImpl
) that assumes physical identifier names are the same as logical ones.
There are several implementations of ImplicitNamingStrategy
but I found none equivalent to the old ImprovedNamingStrategy
. (See: org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyHbmImpl
)
So, I implemented my own PhysicalNamingStrategy
which is very simple:
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()); } @Override public Identifier toPhysicalColumnName(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); } }
Note that the addUnderscores()
method is from the original org.hibernate.cfg.ImprovedNamingStrategy
.
Then, I set this physical strategy into the persistence.xml file :
<property name="hibernate.physical_naming_strategy" value="my.package.PhysicalNamingStrategyImpl" />
It is a trap to set Hibernate 5 naming strategy as previous version settings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With