使用 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.

在你的情况下,我认为你需要 SCHEMADATABASE 并且必须实现 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" );
    }
}

有关详细信息,请参阅链接文档。