Spring Boot 2.7.9+JPA多数据源下自定义命名策略Autowired注入失效
问题:多租户环境下Spring Boot JPA自定义命名策略无法注入依赖的问题
环境与JPA配置
我有一个基于Spring Boot 2.7.9和Spring Data JPA 2.7.8的应用,采用多租户Oracle UCP数据源,部分仓库基于JPA、部分基于JDBC,JPA配置如下:
@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()); }
自定义命名策略实现
我定义了如下命名策略类,它继承自CamelCaseToUnderscoresNamingStrategy,需要注入BatchProperties(用于从application.yml中读取可配置的表前缀,为指定表名添加前缀):
@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; } }
遇到的问题
- 尝试通过配置属性
spring.jpa.hibernate.naming.physical-strategy指定该命名策略,但未被识别 - 改用
spring.jpa.properties.hibernate.physical_naming_strategy配置后,类被识别,但Hibernate会自行创建实例,而非使用Spring容器中已注入BatchProperties的Bean,导致BatchProperties未被注入 - 补充:多数据源场景下,
spring.jpa.hibernate.naming.physical-strategy完全无效
求助
- 如何通过程序化方式引入自定义命名策略服务,确保依赖被正确注入?
- 是否有办法获取Hibernate通过
spring.jpa.properties.hibernate.physical_naming_strategy创建的命名策略实例?
内容的提问来源于stack exchange,提问作者humbleCoder
相关产品推荐
相关产品推荐

