gpt4 book ai didi

spring - 如何获取存储在默认模式表中的租户标识符?

转载 作者:行者123 更新时间:2023-12-01 15:53:26 25 4
gpt4 key购买 nike

我正致力于使用 hibernate 在基于 Spring 的应用程序中启用 Multi-Tenancy 。我创建了 CurrentTenantIdentifierResolver 的自定义实现,并覆盖了 resolveCurrentTenantIdentifier() 方法以确定租户标识符。当我提供硬编码的租户标识符时,应用程序工作正常。

但是随后提出了一个要求,即根据请求 header 中的值从数据库默认模式中的表中获取租户标识符。为此,我在很多地方进行了搜索,并进行了一些尝试,但收效甚微。

如有任何帮助,我们将不胜感激。请让我知道我需要提供哪些信息才能更好地理解问题场景。

CustomTenantIdentifierResolver.java

public class CustomTenantIdentifierResolver implements CurrentTenantIdentifierResolver {

public static final String DEFAULT_TENANT_SCHEMA = "public";

@Override
public String resolveCurrentTenantIdentifier() {
try {
Provider<TenantRequestContext> tenantProvider = SpringContext
.getBean(Provider.class);
if (tenantProvider == null) {
return DEFAULT_TENANT_SCHEMA;
} else {
TenantRequestContext tenantRequestContext = tenantProvider
.get();
String tenantId = tenantRequestContext.getTenantIdValue();
String tenantSchema = tenantRequestContext.getTenantSchema(tenantId);
return tenantSchema;
}
} catch (Exception ex) {
return DEFAULT_TENANT_SCHEMA;
}
// return "myschema";
}

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

}

TenantRequestContextImpl.java

@Component  
@Scope(value = WebApplicationContext.SCOPE_REQUEST, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class TenantRequestContextImpl implements TenantRequestContext{

@Autowired
private TenantReadService tenantReadService;

@Override
public String getTenantIdValue() {
String tenantId =((ServletRequestAttributes)RequestContextHolder.currentRequestAttributes())
.getRequest().getHeader("tenantId");
return tenantId;
}

@Override
public String getTenantSchema(String tenantId) {
Tenant tenant = tenantReadService.findById(Integer.parseInt(tenantId));
return tenant.getTenantSchemaName();
}
}

TenantReadServiceImpl.java

@Repository
public class TenantReadServiceImpl implements TenantReadService {

@Autowired
private SessionFactory defaultSessionFactory;

public TenantReadServiceImpl() {

}

public TenantReadServiceImpl(SessionFactory defaultSessionFactory) {
this.defaultSessionFactory = defaultSessionFactory;
}

@Override
@Transactional
public Tenant findById(Integer tenantId) {
String hql = "from Tenant where id=" + tenantId;
Query query = defaultSessionFactory.getCurrentSession().createQuery(hql);
Tenant tenant = (Tenant) query.uniqueResult();
defaultSessionFactory.getCurrentSession().clear();
return tenant;
}
}

MultitenancyPlatformConfig.java

@Configuration
@EnableTransactionManagement
@ComponentScan("com.mypackage")
public class MultitenancyPlatformConfig {

@Bean(name="defaultDataSource")
public DataSource dataSource() {
final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
DataSource dataSource = dsLookup.getDataSource(java:comp/env/jdbc/myDataSource);
return dataSource;
}

@Autowired
@Bean(name = "defaultSessionFactory")
public SessionFactory getSessionFactory(DataSource defaultDataSource) {
LocalSessionFactoryBuilder sessionBuilder = new LocalSessionFactoryBuilder(
defaultDataSource);
sessionBuilder.addAnnotatedClasses(Tenant.class);
sessionBuilder.addProperties(hibProperties());
return sessionBuilder.buildSessionFactory();
}

private Properties hibProperties() {
Properties properties = new Properties();
properties.put("hibernate.format_sql",
"true");
properties.put("hibernate.dialect",
"org.hibernate.dialect.PostgreSQLDialect");
properties.put("hibernate.default_schema", "public");
return properties;
}

@Autowired
@Bean(name = "tenantReadService")
public TenantReadService getTenantReadService(SessionFactory defaultSessionFactory) {
return new TenantReadServiceImpl(defaultSessionFactory);
}
}

MyPlatformConfig.java

@Configuration
@EnableTransactionManagement
@ComponentScan("com.mypackage")
@EnableJpaRepositories("com.mypackage.repository")
public class MyPlatformConfig {

@Bean
public DataSource dataSource() {
final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
DataSource dataSource = dsLookup.getDataSource("java:comp/env/jdbc/ihubDataSource");
return dataSource;
}

@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
vendorAdapter.setGenerateDdl(false);
vendorAdapter.setDatabase(Database.POSTGRESQL);
vendorAdapter.setDatabasePlatform("org.postgresql.Driver");

LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(vendorAdapter);
factory.setPackagesToScan("com.mypackage.entity");
factory.setJpaProperties(hibProperties());
return factory;
}

private Properties hibProperties() {
Properties properties = new Properties();
properties.put("hibernate.dialect","org.hibernate.dialect.PostgreSQLDialect");
properties.put("hibernate.format_sql","true");
properties.put("hibernate.tenant_identifier_resolver"," com.mypackage.tenantresolvers.CustomTenantIdentifierResolver");
properties.put("hibernate.multi_tenant_connection_provider", "com.mypackage.connectionproviders.MultiTenantConnectionProviderImpl");
properties.put("hibernate.multiTenancy", "SCHEMA");
return properties;
}

@Bean
public JpaTransactionManager transactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
return transactionManager;
}
}

最佳答案

下面是我将如何解决这个问题:

  1. 使用自定义 ServletFilter从请求 header 中提取值。
  2. 在您的自定义 ServletFilter 中:对默认模式执行查询以获取租户标识符并将其放入 ThreadLocal
  3. resolveCurrentTenantIdentifier只需从 ThreadLocal 返回值。

关于spring - 如何获取存储在默认模式表中的租户标识符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31300264/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com