0

I have an app that uses spring boot 2.7.9 and Spring data jpa 2.7.8.

It has a multitenant Oracle UCP data source, with other complexities like some of the repos are JPA based and other JDBC based hence JPA has been configured like so:

    Bean(name = "entityManagerFactory")
    public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean(EntityManagerFactoryBuilder builder,
            TenantRoutingDataSource tenantRoutingDataSource) {
        return builder.dataSource(tenantRoutingDataSource)
                     .packages("com.orders", "com.orders.migration")
                     .build();
    }

    @Bean(name = "transactionManager")
    public JpaTransactionManager transactionManager(
            @Autowired @Qualifier("entityManagerFactory") LocalContainerEntityManagerFactoryBean entityManagerFactoryBean) {
        return new JpaTransactionManager(entityManagerFactoryBean.getObject());
    }

I have a naming strategy class that looks like this :

@AllArgsConstructor
@NoArgsConstructor
@Component
public class AppIdNamingStrategy extends CamelCaseToUnderscoresNamingStrategy {

    private BatchProperties batchProperties;

    @Override
    public Identifier toPhysicalTableName(final Identifier name, final JdbcEnvironment jdbcEnvironment) {
        return this.customize(name, jdbcEnvironment);
    }

    @Override
    public Identifier toPhysicalSequenceName(final Identifier name, final JdbcEnvironment jdbcEnvironment) {
        return this.customize(name, jdbcEnvironment);
    }
    private Identifier customize(Identifier name, JdbcEnvironment jdbcEnvironment) {
        if (name == null) {
            return null;
        } else {
            StringBuilder builder = new StringBuilder(name.getText().replace('.', '_'));

            for(int i = 1; i < builder.length() - 1; ++i) {
                if (this.isUnderscoreRequiredCustom(builder.charAt(i - 1), builder.charAt(i), builder.charAt(i + 1))) {
                    builder.insert(i++, '_');
                }
            }

            if(isCustomOrderIdentifier(name)) {
                builder.insert(0, batchProperties.getJdbc().getTablePrefix());
            }

            return this.getIdentifier(builder.toString(), name.isQuoted(), jdbcEnvironment);
        }
    }

    private boolean isCustomOrderIdentifier(final Identifier name) {
        return "custom_order".equalsIgnoreCase(name.getText()));
    }

    private boolean isUnderscoreRequiredCustom(char before, char current, char after) {
        return Character.isLowerCase(before) && Character.isUpperCase(current) && Character.isLowerCase(after);
    }

    @Autowired
    public void setBatchProperties(final BatchProperties batchProperties) {
        this.batchProperties = batchProperties;
    }
}

BatchProperties is a service that provides the configurable table prefix from the application.yml which has to be applied to some table names when the application starts.

I configured the above class using the following JPA property however its not picked up :

spring.jpa.hibernate.naming.physical-strategy

Since the above is not working I tried the following :

spring.jpa.properties.hibernate.physical_naming_strategy

The class gets picked up however it seems that hibernate creates its own object instead of using the bean that I created because which the BatchProperties service in the AppIdNamingStrategy is not set.

So I am kind of stuck. How do I programmatically introduce my own naming strategy service ?

Is there a way to get a handle of the naming strategy created by hibernate when using the spring.jpa.properties.hibernate.physical_naming_strategy?

EDIT: Found this thread: Can't set JPA naming strategy after configuring multiple data sources (Spring 1.4.1 / Hibernate 5.x)

It seems that if one uses multiple data sources spring.jpa.hibernate.naming.physical-strategy is not picked up at all.

General Grievance
  • 4,555
  • 31
  • 31
  • 45
humbleCoder
  • 667
  • 14
  • 27
  • Are you sure that BatchProperties class is a Spring component and it will be properly scanned? Please check the annotations and package names. – Mar-Z Mar 22 '23 at 13:45
  • Yes, it's getting scanned. In fact, I see now that it's getting set in the HibernateJpaConfiguration class. And if I don't provide the spring.jpa.properties.hibernate.physical_naming_strategy for some reason somewhere later on hibernate creates its own object of PhysicalNamingStrategyStandardImpl and uses that and if I give the value against this property then hibernates creates its own object of AppIdNamingStrategy and doesn't use the bean I create. spring.jpa.hibernate.naming.physical-strategy this has no impact at all. – humbleCoder Mar 22 '23 at 14:00

0 Answers0