首页 > 解决方案 > 如果将 Hibernate 与数据库(和 c3p0 dbpooling)一起使用仍然可以安全地绕过 Hibernate 直接获得连接

问题描述

将 Hibernate 4.3.11 与 H2 1.4.199 和 C3p0 一起使用

如果将 Hibernate 与数据库一起使用仍然可以并且安全地绕过 Hibernate 从池中直接获取连接?

我正在尝试编写一个 sql 查询,现在我知道我可以使用 session.createSQLQuery() 但这会返回一个 Hibernate org.hibernate SQLQuery 类而不是 java.sql.Connection,这对我尝试设置参数造成了问题,所以我想尝试使用 Connection 代替。

标签: javasqlhibernateh2c3p0

解决方案


尝试这个。

import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;

sessionFactory.getSessionFactoryOptions().getServiceRegistry().getService(ConnectionProvider.class).getConnection();

我没有对此进行测试,目前无法执行此操作。我在 ConnectionProvider 上只有 50-50 岁,因为我不确定 c3p0 的提供程序类是什么。可能是org.hibernate.c3p0.internal.C3P0ConnectionProvider,或者你已经知道了。

编辑 11-10-2019

org.hibernate.engine.jdbc.connections.spi.ConnectionProvider据我所知,连接是从接口的实现返回的。

org.hibernate.engine.jdbc.connections.internal.DatasourceConnectionProviderImpl
org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl

这两种实现都java.sql.Connection从服务注册时内部维护的 Datasource 或 PooledConnections 获取。

DatasourceConnectionProviderImpl有以下方法。

    @Override
    public Connection getConnection() throws SQLException {
        if ( !available ) {
            throw new HibernateException( "Provider is closed!" );
        }
        return useCredentials ? dataSource.getConnection( user, pass ) : dataSource.getConnection();
    }

    @Override
    public void closeConnection(Connection connection) throws SQLException {
        connection.close();
    }

DriverManagerConnectionProviderImpl方法如下

@Override
public Connection getConnection() throws SQLException {
    if ( !active ) {
        throw new HibernateException( "Connection pool is no longer active" );
    }

    return pool.poll();
}

public Connection poll() throws SQLException {
        Connection conn = availableConnections.poll();
        if ( conn == null ) {
            synchronized (allConnections) {
                if(allConnections.size() < maxSize) {
                    addConnections( 1 );
                    return poll();
                }
            }
            throw new HibernateException( "The internal connection pool has reached its maximum size and no connection is currently available!" );
        }
        conn.setAutoCommit( autoCommit );
        return conn;
    }


@Override
public void closeConnection(Connection conn) throws SQLException {
    if (conn == null) {
        return;
    }

    pool.add( conn );
}

正如你所看到的,它们都有不同的处理连接的方式。如果您关闭连接,我不会想象会出现重大问题,因为第一个连接会返回新连接,而第二个连接会在连接关闭时补充池。但是,如果您不打算关闭,请知道在您的应用程序中调用了哪个实现,并确保您没有泄漏。

其他两个实现用于 Hikari 和 UserSupplied 模式。


推荐阅读