使用 Spring 和 Hibernate 在多租户环境中访问数据的策略
Strategy for accessing data in multi-tenant environment with Spring and Hibernate
我在一个多租户环境中工作,在该环境中,可以使用 Web 应用程序(休息)前端从大约 10 个不同的数据源(和实体管理器)访问数据。
要使用的实体管理器取决于其余 api 中的 URL 参数,例如。 api/orders/1/1000003.
我需要使用entitymanager "1" 来获取数据。目前,在创建休眠会话并通过休眠条件创建查询之前,我在调用 setDistrict(1) 的存储库层中使用了一种方法。
一切正常,但我担心该方法需要同步以避免从错误的实体管理器获取数据。
当我同步存储库方法时,我担心性能会很糟糕..
实现此多租户访问的好策略是什么,以便性能良好并且在重负载下也能返回正确的数据?
感谢您的建议。
Hibernate 的 SessionFactory 允许使用 tenancy behavior:
SCHEMA Correlates to the separate schema approach. It is an error to attempt to open a session without a tenant identifier using
this strategy. Additionally, a
org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider
must be specified.
DATABASE Correlates to the separate database approach. It is an error to attempt to open a session without a tenant identifier
using this strategy. Additionally, a
org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider
must be specified.
DISCRIMINATOR Correlates to the partitioned (discriminator) approach. It is an error to attempt to open a session without a tenant
identifier using this strategy. This strategy is not yet implemented
in Hibernate as of 4.0 and 4.1. Its support is planned for 5.0.
在你的情况下,我认为你需要 SCHEMA 或 DATABASE 并且必须实现 MultiTenantConnectionProvider (source).
/**
* Simplisitc implementation for illustration purposes supporting 2 hard coded providers (pools) and leveraging
* the support class {@link org.hibernate.service.jdbc.connections.spi.AbstractMultiTenantConnectionProvider}
*/
public class MultiTenantConnectionProviderImpl extends AbstractMultiTenantConnectionProvider {
private final ConnectionProvider acmeProvider = ConnectionProviderUtils.buildConnectionProvider( "acme" );
private final ConnectionProvider jbossProvider = ConnectionProviderUtils.buildConnectionProvider( "jboss" );
@Override
protected ConnectionProvider getAnyConnectionProvider() {
return acmeProvider;
}
@Override
protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) {
if ( "acme".equals( tenantIdentifier ) ) {
return acmeProvider;
}
else if ( "jboss".equals( tenantIdentifier ) ) {
return jbossProvider;
}
throw new HibernateException( "Unknown tenant identifier" );
}
}
有关详细信息,请参阅链接文档。
我在一个多租户环境中工作,在该环境中,可以使用 Web 应用程序(休息)前端从大约 10 个不同的数据源(和实体管理器)访问数据。
要使用的实体管理器取决于其余 api 中的 URL 参数,例如。 api/orders/1/1000003.
我需要使用entitymanager "1" 来获取数据。目前,在创建休眠会话并通过休眠条件创建查询之前,我在调用 setDistrict(1) 的存储库层中使用了一种方法。
一切正常,但我担心该方法需要同步以避免从错误的实体管理器获取数据。 当我同步存储库方法时,我担心性能会很糟糕..
实现此多租户访问的好策略是什么,以便性能良好并且在重负载下也能返回正确的数据?
感谢您的建议。
Hibernate 的 SessionFactory 允许使用 tenancy behavior:
SCHEMA Correlates to the separate schema approach. It is an error to attempt to open a session without a tenant identifier using this strategy. Additionally, a org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider must be specified.
DATABASE Correlates to the separate database approach. It is an error to attempt to open a session without a tenant identifier using this strategy. Additionally, a org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider must be specified.
DISCRIMINATOR Correlates to the partitioned (discriminator) approach. It is an error to attempt to open a session without a tenant identifier using this strategy. This strategy is not yet implemented in Hibernate as of 4.0 and 4.1. Its support is planned for 5.0.
在你的情况下,我认为你需要 SCHEMA 或 DATABASE 并且必须实现 MultiTenantConnectionProvider (source).
/**
* Simplisitc implementation for illustration purposes supporting 2 hard coded providers (pools) and leveraging
* the support class {@link org.hibernate.service.jdbc.connections.spi.AbstractMultiTenantConnectionProvider}
*/
public class MultiTenantConnectionProviderImpl extends AbstractMultiTenantConnectionProvider {
private final ConnectionProvider acmeProvider = ConnectionProviderUtils.buildConnectionProvider( "acme" );
private final ConnectionProvider jbossProvider = ConnectionProviderUtils.buildConnectionProvider( "jboss" );
@Override
protected ConnectionProvider getAnyConnectionProvider() {
return acmeProvider;
}
@Override
protected ConnectionProvider selectConnectionProvider(String tenantIdentifier) {
if ( "acme".equals( tenantIdentifier ) ) {
return acmeProvider;
}
else if ( "jboss".equals( tenantIdentifier ) ) {
return jbossProvider;
}
throw new HibernateException( "Unknown tenant identifier" );
}
}
有关详细信息,请参阅链接文档。