指定 hibernate.multi_tenant_connection_provider 而不使用反射

Specify hibernate.multi_tenant_connection_provider without using reflection

目前我正在使用它在属性文件中指定休眠多租户连接提供程序和解析器。

hibernate.multi_tenant_connection_provider: com.app.MapMultiTenantConnectionProvider
hibernate.tenant_identifier_resolver: com.app.MultiTenantCurrentTenantIdentifierResolver

Hibernate 正在使用反射来加载这些 类。问题是我需要这些 类 才能访问某些变量。例如。 DropWizard 配置文件和用户组织了解数据库 URL 是什么以及租户 ID。目前我必须将变量设为静态,以便提供者可以访问它。

this 这样的教程在属性文件中指定了所有必需的信息,而我需要我的信息根据当前连接的用户是动态的。

这是我必须处理静态变量的示例。总的来说,它使代码非常混乱。

public class MapMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider {

    private static Logger log = LoggerFactory.getLogger(MapMultiTenantConnectionProvider.class);

    private Map<String, ConnectionProvider> connectionProviderMap = new HashMap<>();

    public MapMultiTenantConnectionProvider() throws IOException {
    }

    @Override
    protected ConnectionProvider getAnyConnectionProvider() {
        return getConnectionProviderForTenant("chorus");
    }

    @Override
    protected ConnectionProvider selectConnectionProvider(final String tenantIdentifier) {

        return getConnectionProviderForTenant(tenantIdentifier);
    }

    private ConnectionProvider getConnectionProviderForTenant(final String tenantId) {

        final ConnectionProvider connectionProvider;

        if (!connectionProviderMap.containsKey(tenantId)) {

            // Access a static variable here that contains the database URL, username, etc
            final MyConfig config = MyApp.CONFIGURATION;

            final Properties properties = new Properties();
            properties.setProperty("hibernate.connection.url", config.connectionUrl);
            properties.setProperty("hibernate.connection.username", config.username);
            properties.setProperty("hibernate.connection.password", config.password);
            properties.setProperty("hibernate.dialect", config.databaseConfig.getHibernateDialect());
            
            final DriverManagerConnectionProviderImpl newConnectionProvider = new DriverManagerConnectionProviderImpl();

            newConnectionProvider.configure(properties);

            this.connectionProviderMap.put(tenantId, newConnectionProvider);

            connectionProvider = newConnectionProvider;
        } else {
            connectionProvider = connectionProviderMap.get(tenantId);
        }
        return connectionProvider;
    }
}

我想创建一个实例并像这样传入配置(或任何其他需要的)。

new MapMultiTenantConnectionProvider(configuration)

是否可以通过创建它的实例而不是在属性文件中定义它来指定提供程序?

您可以实现 ServiceRegistryAwareService 接口来访问 Hibernate ServiceRegistry,它使您可以访问几乎所有的 Hibernate 配置。我不知道您通常如何访问此 dropwizard 配置,但如果它可通过托管 bean 访问,您可以访问 ManagedBeanRegistry 并访问提供此信息的 bean。除此之外,您无能为力。但请注意,您当前的实现不是线程安全的。您应该使用 ConcurrentHashMap 并使用 putIfAbsent,甚至更好,computeIfAbsent.