java 基于架构-多租户- Sping Boot

igetnqfo  于 2023-01-15  发布在  Java
关注(0)|答案(1)|浏览(259)

我正在尝试创建简约的基于架构-多租户- Sping Boot ,但我得到以下错误。应用程序可以从GitHub https://github.com/ivoronline/spring_boot_db_multitenant下载
错误

Unable to instantiate specified multi-tenant connection provider [com.ivoronline.spring_boot_db_multitenant.config.TenantConnectionProvider]

application.properties

#spring.jpa.properties.hibernate.multiTenancy = SCHEMA
spring.jpa.properties.hibernate.multiTenancy                     = SCHEMA
spring.jpa.properties.hibernate.multi_tenant_connection_provider = com.ivoronline.spring_boot_db_multitenant.config.TenantConnectionProvider
spring.jpa.properties.hibernate.tenant_identifier_resolver       = com.ivoronline.spring_boot_db_multitenant.config.TenantIdentifierResolver

# JPA / HIBERNATE
spring.jpa.hibernate.ddl-auto = create

DataSourceConfig.java

@Configuration
public class DataSourceConfig {

      @Bean
      public DataSource dataSource()   {
        DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
                          dataSourceBuilder.url("jdbc:postgresql://localhost:5432/multitenant");
                          dataSourceBuilder.username("postgres");
                          dataSourceBuilder.password("letmein");
                          dataSourceBuilder.driverClassName("org.postgresql.Driver");
        return            dataSourceBuilder.build();
      }
    
    }

TenantIdentifierResolver.java

@Component
public class TenantIdentifierResolver implements CurrentTenantIdentifierResolver {

  static final String DEFAULT_TENANT = "public";

  @Override
  public String resolveCurrentTenantIdentifier() {
    return "public";
  }

  @Override
  public boolean validateExistingCurrentSessions() {
    return true;  
  }

}

TenantConnectionProvider.java

@Component
public class TenantConnectionProvider implements MultiTenantConnectionProvider {

  private DataSource datasource;

  public TenantConnectionProvider(DataSource dataSource) {
    this.datasource = dataSource;
  }

  @Override
  public Connection getAnyConnection() throws SQLException {
    return datasource.getConnection();
  }

  @Override
  public void releaseAnyConnection(Connection connection) throws SQLException {
    connection.close();
  }

  @Override
  public Connection getConnection(String tenantIdentifier) throws SQLException {
    final Connection connection = getAnyConnection();
    //connection.createStatement().execute(String.format("SET SCHEMA \"%s\";", tenantIdentifier));
    connection.createStatement().execute("SET Schema 'public'");
    return connection;
  }

  @Override
  public void releaseConnection(String tenantIdentifier, Connection connection) throws SQLException {
    //connection.createStatement().execute(String.format("SET SCHEMA \"%s\";", TenantIdentifierResolver.DEFAULT_TENANT));
    connection.createStatement().execute("SET Schema 'public'");
    releaseAnyConnection(connection);
  }

  @Override
  public boolean supportsAggressiveRelease() {
    return false;
  }

  @Override
  public boolean isUnwrappableAs(Class unwrapType) {
    return false;
  }

  @Override
  public <T> T unwrap(Class<T> unwrapType) {
    return null;
  }

}
qrjkbowd

qrjkbowd1#

Hibernate期望属性hibernate.multi_tenant_connection_provider定义Hibernate可以示例化的已经初始化的对象或类名。在您的情况下,TenantConnectionProvider类没有默认构造函数,因此Hibernate失败(此外,您期望TenantConnectionProviderspring组件)。通常有两个选项来配置此类Hibernate SPI:

  1. Hibernate方式-使用ManagedBeanRegistry与Spring上下文交互
public class TenantConnectionProvider implements MultiTenantConnectionProvider, ServiceRegistryAwareService {

    private ServiceRegistryImplementor serviceRegistry;
    
    // default constructor
    public TenantConnectionProvider() {
        super();
    }

    @Override
    public void injectServices(ServiceRegistryImplementor serviceRegistry) {
        this.serviceRegistry = serviceRegistry;
    }
    
    protected DataSource getDataSource() {
        return serviceRegistry.getService(ManagedBeanRegistry.class)
                .getBean(DataSource.class)
                .getBeanInstance();
    }
    
    ...

}
  1. spring-boot方式-在Java代码中配置JPA属性:
@Bean
public HibernatePropertiesCustomizer tenantConnectionProviderCustomizer(TenantConnectionProvider tenantConnectionProvider) {
    return hibernateProperties -> {
        hibernateProperties.put(AvailableSettings.MULTI_TENANT_CONNECTION_PROVIDER, tenantConnectionProvider);
    };
}

相关问题