我可以通过 Spring/Hibernate/c3p0 将一个池数据源用于多个数据库吗?

2024-02-06

我们的应用程序使用 Spring/Hibernate 进行数据库访问。我们使用多个休眠会话工厂(hibernate3.LocalSessionFactoryBean),因为数据位于多个单独的数据库中。每个会话工厂都使用 c3p0 配置了一个池数据源(c3p0.ComboPooledDataSource).

事实上,这些数据库都驻留在同一个数据库服务器上。我们的问题是,我们最终会得到许多数据库连接池,所有这些都连接到同一台服务器。有没有一种方法可以共享一个池数据源来访问同一服务器上的多个数据库?是否可以配置jdbcUrl在会话工厂级别,而不是在数据源级别?

或者这在实践中不是一个真正的问题?配置多个数据库连接池是否完全可以?


一个连接连接一个数据库。

如果您有 2 个数据库 DB1 和 DB2,并且需要一个连接池,则需要为这两个数据库准备好连接。

如果实际上每个池有 1 个连接,则 C1 和 C2(我知道您有更多连接,但它们是相同的......) 当然,可以将这两个连接放在同一个连接池中。 然后你就会有一个带有C1和C2的连接池。 您对连接池有何期望?对我来说 -> 能够为您提供随机的已准备好的连接,您可以直接使用它,而无需创建新连接的开销。

现在猜猜看,如果您的唯一池中同时有 C1 和 C2,您根本无法获得“随机”连接,因为它们不属于同一个数据库...因此,您将需要检查是否连接返回指向预期数据库的点,否则您将有 50% 的机会在 DB2 上执行请求 R1。

所以是的,这是可能的,您可以简单地实现一个连接池,该连接池仅使用 2 个子连接池 CP1 和 CP2,并且将随机使用这些子连接池之一的 getConnection,但您必须检查之后您将使用正确的连接池,因此最好将两个不同的连接池分开。

我不知道为什么你只想要一个连接池。也许您希望能够告诉您的应用程序“所有连接池都有 100 个连接”,并且您希望您的应用程序自动在您拥有的每个池中设置优化的连接数?对我来说这似乎是可能的,但我不知道是否已经存在通用实现,也许您可​​以做一个连接池包装器,它将在所有现有池之间共享所使用的连接的平均百分比,然后调整池大小或类似的东西...


对我来说,在应用程序中拥有多个连接池是完全可以的。 在同一个应用程序中使用 2 个不同的数据库(Oracle + MongoDB 或类似的东西)是完全可以的,在同一服务器上使用 2 个使用 2 个 Oracle 数据库模式的连接池也是完全可以的,即使两个数据库都有完全相同的表。


您应该查看具有多个客户(通常是 B2B)的 SaaS 应用程序的多租户策略: - 一种是为每个客户拥有一个数据库,并且每个表都有一列“customer_id”。它更容易维护,但表上有更多行(但显然您索引了 customer_id 列) - 另一种可能是您所做的:每个客户都有一个数据库/数据源/连接池/会话工厂,并且每个数据库都将具有相同的表。最终,您将拥有一些机制,例如“自定义主会话工厂”,它将使用 ThreadLocal(由某些凭证过滤器设置?)来存储 customerId 以选择适当的子会话工厂。

例如,请看以下文章(关于该主题的文章有很多):http://relation.to/Bloggers/MultitenancyInHibernate http://relation.to/Bloggers/MultitenancyInHibernate

public class MyTenantAwareConnectionProvider implements ConnectionProvider {
    public static final String BASE_JNDI_NAME_PARAM = "MyTenantAwareConnectionProvider.baseJndiName";

    private String baseJndiName;

    public void configure(Properties props) {
        baseJndiName = props.getProperty( BASE_JNDI_NAME_PARAM );
    }

    public Connection getConnection() throws SQLException {
        final String tenantId = TenantContext.getTenantId()
        final String tenantDataSourceName = baseJndiName + '/' + tenantId;
        DataSource tenantDataSource = JndiHelper.lookupDataSource( tenantDataSourceName );
        return tenantDataSource.getConnection();
    }

    public void closeConnection(Connection conn) throws SQLException {
        conn.close();
    }

    public boolean supportsAggressiveRelease() {
        // so long as the tenant identifier remains available in TL throughout, we can
        return true;
    }

    public close() {
        // currently nothing to do here
    }
}

这几乎和我告诉你的一样,只是这里有一个动态连接提供程序而不是动态会话提供程序。 (这里的租户 = 在我的例子中的客户)

您可以注意到,此示例中没有连接池,但您肯定可以实现自己的 PooledMyTenantAwareConnectionProvider ;)

祝你好运。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

我可以通过 Spring/Hibernate/c3p0 将一个池数据源用于多个数据库吗? 的相关文章

随机推荐