Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -23,14 +23,13 @@
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProviderConfigurationException;
import org.hibernate.engine.jdbc.connections.spi.DatabaseConnectionInfo;
import org.hibernate.exception.JDBCConnectionException;
import org.hibernate.internal.log.ConnectionInfoLogger;
import org.hibernate.service.UnknownUnwrapTypeException;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.Stoppable;

import io.agroal.api.AgroalDataSource;
import io.agroal.api.configuration.AgroalConnectionFactoryConfiguration;
import io.agroal.api.configuration.AgroalConnectionPoolConfiguration;
import io.agroal.api.configuration.supplier.AgroalConnectionFactoryConfigurationSupplier;
import io.agroal.api.configuration.supplier.AgroalPropertiesReader;
import io.agroal.api.security.NamePrincipal;
Expand All @@ -40,8 +39,12 @@
import static java.util.stream.Collectors.toMap;
import static org.hibernate.cfg.AgroalSettings.AGROAL_CONFIG_PREFIX;
import static org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.toIsolationNiceName;
import static org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl.getCatalog;
import static org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl.getFetchSize;
import static org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl.getIsolation;
import static org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl.getSchema;
import static org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl.hasCatalog;
import static org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl.hasSchema;
import static org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator.allowJdbcMetadataAccess;

/**
Expand Down Expand Up @@ -108,7 +111,7 @@ public void configure(Map<String, Object> properties) throws HibernateException

ConnectionInfoLogger.INSTANCE.configureConnectionPool( "Agroal" );
try {
final Map<String, String> config = toStringValuedProperties( properties );
final var config = toStringValuedProperties( properties );
if ( !properties.containsKey( AgroalSettings.AGROAL_MAX_SIZE ) ) {
final String maxSize =
properties.containsKey( JdbcSettings.POOL_SIZE )
Expand Down Expand Up @@ -166,27 +169,41 @@ public boolean supportsAggressiveRelease() {

@Override
public DatabaseConnectionInfo getDatabaseConnectionInfo(Dialect dialect) {
final AgroalConnectionPoolConfiguration acpc =
agroalDataSource.getConfiguration().connectionPoolConfiguration();
final AgroalConnectionFactoryConfiguration acfc = acpc.connectionFactoryConfiguration();
return new DatabaseConnectionInfoImpl(
AgroalConnectionProvider.class,
acfc.jdbcUrl(),
// Attempt to resolve the driver name from the dialect,
// in case it wasn't explicitly set and access to the
// database metadata is allowed
acfc.connectionProviderClass() != null
? acfc.connectionProviderClass().toString()
: extractDriverNameFromMetadata(),
dialect.getVersion(),
Boolean.toString( acfc.autoCommit() ),
acfc.jdbcTransactionIsolation() != null && acfc.jdbcTransactionIsolation().isDefined()
? toIsolationNiceName( acfc.jdbcTransactionIsolation().level() )
: toIsolationNiceName( getIsolation( agroalDataSource ) ),
acpc.minSize(),
acpc.maxSize(),
getFetchSize( agroalDataSource )
);
final var poolConfig = agroalDataSource.getConfiguration().connectionPoolConfiguration();
final var connectionConfig = poolConfig.connectionFactoryConfiguration();
try ( var connection = agroalDataSource.getConnection() ) {
final var info = new DatabaseConnectionInfoImpl(
AgroalConnectionProvider.class,
connectionConfig.jdbcUrl(),
// Attempt to resolve the driver name from the dialect,
// in case it wasn't explicitly set and access to the
// database metadata is allowed
connectionConfig.connectionProviderClass() != null
? connectionConfig.connectionProviderClass().toString()
: extractDriverNameFromMetadata(),
dialect.getClass(),
dialect.getVersion(),
hasSchema( connection ),
hasCatalog( connection ),
getSchema( connection ),
getCatalog( connection ),
Boolean.toString( connectionConfig.autoCommit() ),
connectionConfig.jdbcTransactionIsolation() != null
&& connectionConfig.jdbcTransactionIsolation().isDefined()
? toIsolationNiceName( connectionConfig.jdbcTransactionIsolation().level() )
: toIsolationNiceName( getIsolation( connection ) ),
poolConfig.minSize(),
poolConfig.maxSize(),
getFetchSize( connection )
);
if ( !connection.getAutoCommit() ) {
connection.rollback();
}
return info;
}
catch (SQLException e) {
throw new JDBCConnectionException( "Could not create connection", e );
}
}

private String extractDriverNameFromMetadata() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProviderConfigurationException;
import org.hibernate.engine.jdbc.connections.spi.DatabaseConnectionInfo;
import org.hibernate.exception.JDBCConnectionException;
import org.hibernate.internal.log.ConnectionInfoLogger;
import org.hibernate.service.UnknownUnwrapTypeException;
import org.hibernate.service.spi.Configurable;
Expand Down Expand Up @@ -43,8 +44,12 @@
import static org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.extractSetting;
import static org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.getConnectionProperties;
import static org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator.toIsolationNiceName;
import static org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl.getCatalog;
import static org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl.getFetchSize;
import static org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl.getIsolation;
import static org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl.getSchema;
import static org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl.hasCatalog;
import static org.hibernate.engine.jdbc.connections.internal.DatabaseConnectionInfoImpl.hasSchema;
import static org.hibernate.internal.util.config.ConfigurationHelper.getBoolean;
import static org.hibernate.internal.util.config.ConfigurationHelper.getInteger;

Expand Down Expand Up @@ -159,23 +164,40 @@ public void configure(Map<String, Object> properties) {
final var poolSettings = poolSettings( properties );
dataSource = createDataSource( jdbcUrl, connectionProps, poolSettings );

final Integer fetchSize = getFetchSize( dataSource );
if ( isolation == null ) {
isolation = getIsolation( dataSource );
try ( var connection = dataSource.getConnection() ) {
final Integer fetchSize = getFetchSize( connection );
final boolean hasSchema = hasSchema( connection );
final boolean hasCatalog = hasCatalog( connection );
final String schema = getSchema( connection );
final String catalog = getCatalog( connection );
if ( isolation == null ) {
isolation = getIsolation( connection );
}
dbInfoProducer = dialect -> new DatabaseConnectionInfoImpl(
C3P0ConnectionProvider.class,
jdbcUrl,
jdbcDriverClass,
dialect.getClass(),
dialect.getVersion(),
hasSchema,
hasCatalog,
schema,
catalog,
Boolean.toString( autocommit ),
isolation == null ? null : toIsolationNiceName( isolation ),
requireNonNullElse( getInteger( C3P0_STYLE_MIN_POOL_SIZE.substring( 5 ), poolSettings ),
DEFAULT_MIN_POOL_SIZE ),
requireNonNullElse( getInteger( C3P0_STYLE_MAX_POOL_SIZE.substring( 5 ), poolSettings ),
DEFAULT_MAX_POOL_SIZE ),
fetchSize
);
if ( !connection.getAutoCommit() ) {
connection.rollback();
}
}
catch (SQLException e) {
throw new JDBCConnectionException( "Could not create connection", e );
}
dbInfoProducer = dialect -> new DatabaseConnectionInfoImpl(
C3P0ConnectionProvider.class,
jdbcUrl,
jdbcDriverClass,
dialect.getVersion(),
Boolean.toString( autocommit ),
isolation == null ? null : toIsolationNiceName( isolation ),
requireNonNullElse( getInteger( C3P0_STYLE_MIN_POOL_SIZE.substring( 5 ), poolSettings ),
DEFAULT_MIN_POOL_SIZE ),
requireNonNullElse( getInteger( C3P0_STYLE_MAX_POOL_SIZE.substring( 5 ), poolSettings ),
DEFAULT_MAX_POOL_SIZE ),
fetchSize
);
}

private DataSource createDataSource(String jdbcUrl, Properties connectionProps, Map<String, Object> poolProperties) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import jakarta.persistence.Id;

import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.H2Dialect;

import org.hibernate.testing.RequiresDialect;
Expand All @@ -20,6 +19,8 @@
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.Test;

import static org.hibernate.cfg.JdbcSettings.CONNECTION_PROVIDER;
import static org.hibernate.cfg.JdbcSettings.ISOLATION;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
Expand Down Expand Up @@ -52,8 +53,8 @@ protected Class<?>[] getAnnotatedClasses() {
@Override
protected void addSettings(Map<String,Object> settings) {
connectionProvider = new C3P0ProxyConnectionProvider();
settings.put( AvailableSettings.CONNECTION_PROVIDER, connectionProvider );
settings.put( AvailableSettings.ISOLATION, "READ_COMMITTED" );
settings.put( CONNECTION_PROVIDER, connectionProvider );
settings.put( ISOLATION, "READ_COMMITTED" );
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import jakarta.persistence.Id;

import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.dialect.H2Dialect;

import org.hibernate.testing.RequiresDialect;
Expand All @@ -20,6 +19,8 @@
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.junit.Test;

import static org.hibernate.cfg.JdbcSettings.CONNECTION_PROVIDER;
import static org.hibernate.cfg.JdbcSettings.ISOLATION;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
Expand Down Expand Up @@ -52,8 +53,8 @@ protected Class<?>[] getAnnotatedClasses() {
@Override
protected void addSettings(Map<String,Object> settings) {
connectionProvider = new C3P0ProxyConnectionProvider();
settings.put( AvailableSettings.CONNECTION_PROVIDER, connectionProvider );
settings.put( AvailableSettings.ISOLATION, "REPEATABLE_READ" );
settings.put( CONNECTION_PROVIDER, connectionProvider );
settings.put( ISOLATION, "REPEATABLE_READ" );
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.test.c3p0;

import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import org.hibernate.boot.SessionFactoryBuilder;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.testing.RequiresDialect;
import org.hibernate.testing.jdbc.SQLStatementInterceptor;
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
import org.hibernate.testing.orm.junit.JiraKey;
import org.junit.Test;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Map;

import static org.hibernate.cfg.JdbcSettings.CONNECTION_PROVIDER;
import static org.hibernate.cfg.JdbcSettings.ISOLATION;
import static org.hibernate.testing.transaction.TransactionUtil.doInHibernate;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;

/**
* @author Vlad Mihalcea
*/
@JiraKey(value = "HHH-12749")
@RequiresDialect(H2Dialect.class)
public class C3P0EmptyIsolationLevelTest extends
BaseNonConfigCoreFunctionalTestCase {

private C3P0ProxyConnectionProvider connectionProvider;
private SQLStatementInterceptor sqlStatementInterceptor;

@Override
protected void configureSessionFactoryBuilder(SessionFactoryBuilder sfb) {
sqlStatementInterceptor = new SQLStatementInterceptor( sfb );
}

@Override
protected Class<?>[] getAnnotatedClasses() {
return new Class<?>[] {
Person.class,
};
}

@Override
protected void addSettings(Map<String,Object> settings) {
connectionProvider = new C3P0ProxyConnectionProvider();
settings.put( CONNECTION_PROVIDER, connectionProvider );
settings.put( ISOLATION, "" );
}

@Test
public void testStoredProcedureOutParameter() throws SQLException {
clearSpies();

doInHibernate( this::sessionFactory, session -> {
Person person = new Person();
person.id = 1L;
person.name = "Vlad Mihalcea";

session.persist( person );
} );

assertEquals( 1, sqlStatementInterceptor.getSqlQueries().size() );
assertTrue( sqlStatementInterceptor.getSqlQueries().get( 0 ).toLowerCase().startsWith( "insert into" ) );
Connection connectionSpy = connectionProvider.getConnectionSpyMap().keySet().iterator().next();
verify( connectionSpy, never() ).setTransactionIsolation( Connection.TRANSACTION_READ_COMMITTED );

clearSpies();

doInHibernate( this::sessionFactory, session -> {
Person person = session.find( Person.class, 1L );

assertEquals( "Vlad Mihalcea", person.name );
} );

assertEquals( 1, sqlStatementInterceptor.getSqlQueries().size() );
assertTrue( sqlStatementInterceptor.getSqlQueries().get( 0 ).toLowerCase().startsWith( "select" ) );
connectionSpy = connectionProvider.getConnectionSpyMap().keySet().iterator().next();
verify( connectionSpy, never() ).setTransactionIsolation( Connection.TRANSACTION_READ_COMMITTED );
}

private void clearSpies() {
sqlStatementInterceptor.getSqlQueries().clear();
connectionProvider.clear();
}

@Entity(name = "Person")
public static class Person {

@Id
private Long id;

private String name;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -833,11 +833,6 @@ public NameQualifierSupport getNameQualifierSupport() {
return NameQualifierSupport.SCHEMA;
}

@Override
public boolean supportsNamedParameters(DatabaseMetaData databaseMetaData) {
return false;
}

@Override
public FunctionalDependencyAnalysisSupport getFunctionalDependencyAnalysisSupport() {
return FunctionalDependencyAnalysisSupportImpl.TABLE_REFERENCE;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3694,7 +3694,7 @@ public Set<String> getKeywords() {
* <li>Call {@link IdentifierHelperBuilder#applyIdentifierCasing(DatabaseMetaData)}
* <li>Call {@link IdentifierHelperBuilder#applyReservedWords(DatabaseMetaData)}
* <li>Applies {@link AnsiSqlKeywords#sql2003()} as reserved words</li>
* <li>Applies the {#link #sqlKeywords} collected here as reserved words</li>
* <li>Applies the {@link #sqlKeywords} collected here as reserved words</li>
* <li>Applies the Dialect's {@link NameQualifierSupport}, if it defines one</li>
* </ul>
*
Expand Down Expand Up @@ -4083,7 +4083,7 @@ public String[] getDropSchemaCommand(String schemaName) {
* {@link Connection#getSchema()} is always available directly.
* Never used internally.
*/
@Deprecated
@Deprecated(since = "7.0")
public String getCurrentSchemaCommand() {
return null;
}
Expand Down Expand Up @@ -4891,7 +4891,7 @@ public boolean addPartitionKeyToPrimaryKey() {
* an exception. Just rethrow and Hibernate will
* handle it.
*/
public boolean supportsNamedParameters(@Nullable DatabaseMetaData databaseMetaData) throws SQLException {
public boolean supportsNamedParameters(DatabaseMetaData databaseMetaData) throws SQLException {
return databaseMetaData != null && databaseMetaData.supportsNamedParameters();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -662,11 +662,6 @@ public NameQualifierSupport getNameQualifierSupport() {
return NameQualifierSupport.SCHEMA;
}

@Override
public boolean supportsNamedParameters(DatabaseMetaData databaseMetaData) {
return false;
}

@Override
public FunctionalDependencyAnalysisSupport getFunctionalDependencyAnalysisSupport() {
return FunctionalDependencyAnalysisSupportImpl.TABLE_REFERENCE;
Expand Down
Loading
Loading