首页 > 解决方案 > 在运行时有条件地覆盖 entityManager 工厂映射

问题描述

我有一个使用AbstractRoutingDataSource. 一些 DB 的架构略有不同,并且在某些表中缺少一些列(这是静态的,每个 DB 都知道)。如果数据库没有列,我不想为每个数据库模式复制所有存储库和实体,我只想将丢失的列标记为瞬态(但如果列可用,仍然保存所有信息)。

我能够使用基于 XML 的映射文件覆盖实体管理器工厂中基于注释的映射,我可以为所有可能的模式创建该映射文件。我的想法是使用适当的 XML 映射覆盖为每个租户创建一个实体管理器工厂。理想情况下,在租户的第一个请求中,它将实例化实体管理器工厂,然后检查要应用的映射覆盖。伪代码:

@Configuration
@EnableTransactionManagement
class JPAconfig {

  @Bean
  public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource myAbstractRoutingDataSource, TenantService tenantService) {
    final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
    em.setDataSource(myAbstractRoutingDataSource);
    em.setPackagesToScan("myPackagesToScan");
    final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
    em.setJpaVendorAdapter(vendorAdapter);
    em.setJpaProperties(additionalProperties());
    String schemaVer = env.getProperty("db.schema.version");

    // At runtime based on the tenant, override annotation based mappings
    em.setMappingResources(tenantService.getMappingsForTenant());
    
    return em;
  }
}

不幸LocalContainerEntityManagerFactoryBean的是,它是一个工厂 bean,似乎只允许单例或原型范围。也可以LocalContainerEntityManagerFactoryBean在编译时定义所有可能的 bean,并在运行时根据租户以某种方式选择正确的工厂。

标签: springspring-bootspring-data-jpa

解决方案


更改休眠属性/配置后尝试重新加载应用程序上下文:

ApplicationContextProvider.getApplicationContext().refresh();

参考:Spring Hibernate:重新加载实体映射


推荐阅读