Database/Schema在调用API时未切换。

huangapple go评论50阅读模式
英文:

Database/Schema is not being switched when API is called

问题

I am trying to implement hibernate multitenancy in my SpringBootWebApplication.

PROBLEM - tenant is being set in filter but when query is called Datasource is not being switched.
bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: ERROR: relation "xyz" does not exist.

Here are the details

  • spring-boot-starter-parent -- 2.5.12

  • MyBatis for BE queries.

  • Hibernate for multi-tenancy.

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
    basePackages = {"com.xyz.*"}
)
public class HibernateConfig {
    @Autowired
    private JpaProperties jpaProperties;

    public HibernateConfig() {
    }

    @Bean
    JpaVendorAdapter jpaVendorAdapter() {
        return new HibernateJpaVendorAdapter();
    }

    @Bean(name = {"entityManagerFactory"})
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, MultiTenantConnectionProvider multiTenantConnectionProviderImpl, CurrentTenantIdentifierResolver currentTenantIdentifierResolverImpl){
        Map<String, Object> jpaPropertiesMap = new HashMap(this.jpaProperties.getProperties());
        jpaPropertiesMap.put("hibernate.multiTenancy", MultiTenancyStrategy.SCHEMA);
        jpaPropertiesMap.put("hibernate.multi_tenant_connection_provider", multiTenantConnectionProviderImpl);
        jpaPropertiesMap.put("hibernate.tenant_identifier_resolver", currentTenantIdentifierResolverImpl);
        jpaPropertiesMap.put("hibernate.format_sql", true);
        jpaPropertiesMap.put("hibernate.show_sql", true);
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource);
        em.setJpaVendorAdapter(this.jpaVendorAdapter());
        em.setJpaPropertyMap(jpaPropertiesMap);
        em.setPackagesToScan(new String[]{"com.xyz.*"});
        return em;
    }
}
@Component
public class DataSourceBasedMultiTenantConnectionProviderImpl extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl {
    private static final long serialVersionUID = 1L;
    private static final String DEFAULT_TENANT_ID = "master";
    @Autowired
    private DataSource defaultDS;
    @Autowired
    private ApplicationContext context;
    private Map<String, DataSource> map = new HashMap();
    boolean init = false;

    public DataSourceBasedMultiTenantConnectionProviderImpl() {
    }

    @PostConstruct
    public void load() {
        this.map.put("master", this.defaultDS);
    }

    protected DataSource selectAnyDataSource() {
        return (DataSource)this.map.get("master");
    }

    protected DataSource selectDataSource(String tenantIdentifier) {
        if (!this.init) {
            this.init = true;
            TenantDataSource tenantDataSource = (TenantDataSource)this.context.getBean(TenantDataSource.class);
            this.map.putAll(tenantDataSource.getAll());
        }

        return this.map.get(tenantIdentifier) != null ? (DataSource)this.map.get(tenantIdentifier) : (DataSource)this.map.get("master");
    }
}

The above Datasource provider is not being called.
Thanks in advance for your Help!!!

英文:

I am trying to implement hibernate multitenancy in my SpringBootWebApplication.

PROBLEM - tenant is being set in filter but when query is called Datasource is not being switched.
bad SQL grammar []; nested exception is org.postgresql.util.PSQLException: ERROR: relation "xyz" does not exist.

Here are the details

  • spring-boot-starter-parent -- 2.5.12

  • MyBatis for BE queries.

  • Hibernate for multi-tenancy.

    @Configuration
    @EnableTransactionManagement
    @EnableJpaRepositories(
        basePackages = {&quot;com.xyz.*&quot;}
    )
    public class HibernateConfig {
        @Autowired
        private JpaProperties jpaProperties;
    
        public HibernateConfig() {
        }
    
        @Bean
        JpaVendorAdapter jpaVendorAdapter() {
            return new HibernateJpaVendorAdapter();
        }
    
        @Bean(name = {&quot;entityManagerFactory&quot;})
        public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource, MultiTenantConnectionProvider multiTenantConnectionProviderImpl, CurrentTenantIdentifierResolver currentTenantIdentifierResolverImpl){
            Map&lt;String, Object&gt; jpaPropertiesMap = new HashMap(this.jpaProperties.getProperties());
            jpaPropertiesMap.put(&quot;hibernate.multiTenancy&quot;, MultiTenancyStrategy.SCHEMA);
            jpaPropertiesMap.put(&quot;hibernate.multi_tenant_connection_provider&quot;, multiTenantConnectionProviderImpl);
            jpaPropertiesMap.put(&quot;hibernate.tenant_identifier_resolver&quot;, currentTenantIdentifierResolverImpl);
            jpaPropertiesMap.put(&quot;hibernate.format_sql&quot;, true);
            jpaPropertiesMap.put(&quot;hibernate.show_sql&quot;, true);
            LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
            em.setDataSource(dataSource);
            em.setJpaVendorAdapter(this.jpaVendorAdapter());
            em.setJpaPropertyMap(jpaPropertiesMap);
            em.setPackagesToScan(new String[]{&quot;com.xyz.*&quot;});
            return em;
        }
    }
    @Component
    public class DataSourceBasedMultiTenantConnectionProviderImpl extends AbstractDataSourceBasedMultiTenantConnectionProviderImpl {
        private static final long serialVersionUID = 1L;
        private static final String DEFAULT_TENANT_ID = &quot;master&quot;;
        @Autowired
        private DataSource defaultDS;
        @Autowired
        private ApplicationContext context;
        private Map&lt;String, DataSource&gt; map = new HashMap();
        boolean init = false;
    
        public DataSourceBasedMultiTenantConnectionProviderImpl() {
        }
    
        @PostConstruct
        public void load() {
            this.map.put(&quot;master&quot;, this.defaultDS);
        }
    
        protected DataSource selectAnyDataSource() {
            return (DataSource)this.map.get(&quot;master&quot;);
        }
    
        protected DataSource selectDataSource(String tenantIdentifier) {
            if (!this.init) {
                this.init = true;
                TenantDataSource tenantDataSource = (TenantDataSource)this.context.getBean(TenantDataSource.class);
                this.map.putAll(tenantDataSource.getAll());
            }
    
            return this.map.get(tenantIdentifier) != null ? (DataSource)this.map.get(tenantIdentifier) : (DataSource)this.map.get(&quot;master&quot;);
        }
    }

The above Datasource provider is not being called.
Thanks in advance for your Help!!!

答案1

得分: 0

我找到了问题。

我的项目正在使用MyBatis进行数据库查询。由于配置是通过Hibernate设置的,所以在触发查询时使用SpringDataJPA或Hibernate有助于切换数据库。

英文:

I have found the issue.

My project is using MyBatis for Database queries. Since the configuration is set via hibernate, so using SpringDataJPA or hibernate helped in switching the DB while triggering the query.

huangapple
  • 本文由 发表于 2023年5月25日 20:37:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/76332345.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定