Я работаю над включением мультиарендности в моем приложении на основе Spring с использованием спящего режима. Я создал индивидуальную реализацию CurrentTenantIdentifierResolver
и переопределил метод resolveCurrentTenantIdentifier()
для определения идентификатора клиента. Приложение отлично работает, когда я указываю жестко запрограммированный идентификатор клиента.
Но затем возникла потребность получить идентификатор клиента из таблицы в схеме базы данных по умолчанию на основе значения в заголовке запроса. Я искал об этом во многих местах и провел несколько попыток, но без особого успеха.
Любая помощь по этому поводу будет принята с благодарностью. Пожалуйста, дайте мне знать, какую всю информацию мне нужно предоставить для лучшего понимания сценария проблемы.
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;
}
}