I have one global naming strategy but for a few entities I want to use a different one. Is it possible in jpa or hibernate?
clarification: i don't want to use @Table(name="xxx") nor @Column(name="xxx"). i'm asking about naming strategy component (described for example here: Hibernate naming strategy). that's a component that infer the column and table names for you
This name can be customized in two ways: it can be derived automatically by using an ImplicitNamingStrategy or it can be defined explicitly by using annotations. The ImplicitNamingStrategy governs how Hibernate derives a logical name from our Java class and property names.
By default, Hibernate uses the implicit naming strategy defined by the JPA specification. This value is an alias for jpa. This is the naming strategy defined by the JPA 2.0 specification. The logical name of an entity class is either the name provided in the @Entity annotation or the unqualified class name.
naming. strategy ; Hibernate 5 defines a Physical and Implicit naming strategies. Spring Boot configures SpringPhysicalNamingStrategy by default. This implementation provides the same table structure as Hibernate 4: all dots are replaced by underscores and camel cases are replaced by underscores as well.
PhysicalNamingStrategy. The idea of a PhysicalNamingStrategy is to define custom naming rules without having to hard-code them into the mapping via explicit names. Following is an implementation of PhysicalNamingStrategy to define custom table name and column name.
I don't see a way in the Hibernate source code. The EntityBinder
is coming up with names using ObjectNameNormalizer.NamingStrategyHelper
, which gets the naming strategy from either Configuration.namingStrategy
(the global one) or from a complex path which goes through MetadataImpl
and lands nowhere (no usages).
So you're likely stuck with overriding field names manually. I don't even see an obvious way to get context about the field, so I think even a split-brain naming strategy looks like it's out of the question.
Update: After seeing @anthony-accioly's answer, I thought I that last sentence may have been wrong. So I tested it as follows
package internal.sandbox.domain;
@Entity
public class SomeEntity {
private String id;
private String someField;
@Id
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getSomeField() {
return someField;
}
public void setSomeField(String someField) {
this.someField = someField;
}
}
with a JpaConfiguration
as follows
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories("internal.sandbox.dao")
@Import(DataSourceConfiguration.class)
public class JpaConfiguration {
@Bean
@Autowired
public LocalContainerEntityManagerFactoryBean localContainerEntityManagerFactoryBean(DataSource dataSource) {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setDatabasePlatform("org.hibernate.dialect.PostgreSQL82Dialect");
vendorAdapter.setDatabase(Database.POSTGRESQL);
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("internal.sandbox"); // note, no ".domain"
factory.setDataSource(dataSource);
Properties properties = new Properties();
properties.setProperty("hibernate.cache.use_second_level_cache", "false");
properties.setProperty("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
factory.setJpaProperties(properties);
return factory;
}
...
a Spring Data DAO as follows
public interface SomeEntityDao extends CrudRepository<SomeEntity, String> {
}
and an integration test as follows
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {ApplicationConfiguration.class, JpaConfiguration.class})
public class SomeEntityDaoIntegrationTests {
@Autowired
private SomeEntityDao someEntityDao;
@Test
public void testSave() {
SomeEntity someEntity = new SomeEntity();
someEntity.setId("foo");
someEntity.setSomeField("bar");
this.someEntityDao.save(someEntity);
}
}
I put breakpoints in the ImprovedNamingStrategy
, and classToTableName()
was called with "SomeEntity" and propertyToColumnName()
was called with "someField".
In other words, package information isn't being passed in, so at least in this setup, it can't be used to apply a different naming strategy based on package name.
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