如果将 Hibernate 与数据库(和 c3p0 dbpooling)一起使用仍然可以并且安全地绕过 Hibernate 直接获得连接

If using Hibernate with Database (and c3p0 dbpooling) is is still possible and safe to directly get connection bypassing Hibernate

将 Hibernate 4.3.11 与 H2 1.4.199 和 C3p0 结合使用

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

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

试试这个。

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

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

我还没有测试过这个,现在不能做。我在 ConnectionProvider 上只有 50-50,因为我不确定 c3p0 的提供者 class 是什么。可能是 org.hibernate.c3p0.internal.C3P0ConnectionProvider 或者你已经知道了。

编辑 2019 年 11 月 10 日

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

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

这两种实现都在从服务注册时内部维护的数据源或池化连接中获取 java.sql.Connection

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

如您所见,它们都有不同的连接处理方式。如果您关闭连接,我认为不会出现重大问题,因为第一个 returns 新连接和第二个在连接关闭时补充池。但是,如果您不打算关闭,请了解在您的应用程序中调用了哪个实现并确保您没有泄漏。

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