You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无需反射指定hibernate.multi_tenant_connection_provider的实现方案

问题解决方案

你完全可以跳过属性文件配置类路径、Hibernate反射实例化的流程,手动注册自行创建的实例,具体实现步骤如下:

1. 移除属性文件中的对应配置

删掉原来的两行反射加载配置:

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

2. 改造组件类增加带参构造

修改MapMultiTenantConnectionProvider类,用成员变量接收配置,替代静态变量引用:

public class MapMultiTenantConnectionProvider extends AbstractMultiTenantConnectionProvider {

    private static Logger log = LoggerFactory.getLogger(MapMultiTenantConnectionProvider.class);
    private Map<String, ConnectionProvider> connectionProviderMap = new HashMap<>();
    // 配置改为成员变量,不需要静态存储
    private final MyConfig config;

    // 新增带参构造接收外部传入的配置
    public MapMultiTenantConnectionProvider(MyConfig config) {
        this.config = config;
    }

    @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)) {
            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;
    }
}

租户ID解析器MultiTenantCurrentTenantIdentifierResolver也可以用同样方式增加带参构造,传入你需要的用户上下文、请求持有类等动态依赖。

3. 构建SessionFactory时手动注册实例

在你初始化Hibernate SessionFactory的逻辑中,手动实例化两个组件后直接注册到服务注册表:

// 此处已经拿到DropWizard初始化好的configuration对象
MyConfig config = ...;
// 自行实例化两个组件,传入所有需要的依赖
MapMultiTenantConnectionProvider connectionProvider = new MapMultiTenantConnectionProvider(config);
MultiTenantCurrentTenantIdentifierResolver tenantResolver = new MultiTenantCurrentTenantIdentifierResolver(用户上下文依赖);

// 构建服务注册表时手动注册服务
StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
        .applySettings(其他Hibernate常规配置)
        // 注册自定义的多租户连接提供器实例
        .addService(MultiTenantConnectionProvider.class, connectionProvider)
        // 注册自定义的租户ID解析器实例
        .addService(CurrentTenantIdentifierResolver.class, tenantResolver)
        .build();

// 后续正常构建SessionFactory即可
SessionFactory sessionFactory = new MetadataSources(serviceRegistry)
        .addAnnotatedClass(你的实体类.class)
        .buildMetadata()
        .buildSessionFactory();

补充说明

该方式完全绕过了Hibernate的反射实例化逻辑,你可以完全控制两个组件的生命周期和依赖注入,不需要再用静态变量存储配置。如果是配合Spring等DI容器使用的场景,也可以把这两个组件交给容器管理,注入所有依赖后再注册到Hibernate服务注册表即可。

内容的提问来源于stack exchange,提问作者Michael

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 19:09:01