From 92ffe6df751972650bba23daf37cacaf173a5fe3 Mon Sep 17 00:00:00 2001 From: Gavin King Date: Sun, 13 Jul 2025 19:05:01 +0200 Subject: [PATCH] Use the JDBC metadata to display more info about the datasource Not convinced I like how this turned out --- .../internal/DatabaseConnectionInfoImpl.java | 32 +++++++---- .../DatasourceConnectionProviderImpl.java | 48 +++++++++------- .../ExtractedDatabaseMetaDataImpl.java | 55 +++++++++++++------ .../env/spi/ExtractedDatabaseMetaData.java | 4 ++ .../TestDataSourceConnectionProvider.java | 1 + 5 files changed, 92 insertions(+), 48 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DatabaseConnectionInfoImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DatabaseConnectionInfoImpl.java index 46c98c6c9d54..c71b4e077c95 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DatabaseConnectionInfoImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DatabaseConnectionInfoImpl.java @@ -112,17 +112,27 @@ public Integer getPoolMaxSize() { @Override public String toInfoString() { - return "\tDatabase JDBC URL [" + handleEmpty( jdbcUrl ) + ']' + - "\n\tDatabase driver: " + handleEmpty( jdbcDriver ) + - "\n\tDatabase version: " + handleEmpty( dialectVersion ) + - "\n\tAutocommit mode: " + handleEmpty( autoCommitMode ) + - "\n\tIsolation level: " + handleEmpty( isolationLevel ) + - "\n\tPool: " + handleEmpty( connectionProviderClass ) + - "\n\tMinimum pool size: " + handleEmpty( poolMinSize ) + - "\n\tMaximum pool size: " + handleEmpty( poolMaxSize ); - } - - private static String handleEmpty(String value) { + return """ + \tDatabase JDBC URL [%s] + \tDatabase driver: %s + \tDialect version: %s + \tAutocommit mode: %s + \tIsolation level: %s + \tPool: %s + \t\tMinimum size: %s + \t\tMaximum size: %s""" + .formatted( + handleEmpty( jdbcUrl ), + handleEmpty( jdbcDriver ), + handleEmpty( dialectVersion ), + handleEmpty( autoCommitMode ), + handleEmpty( isolationLevel ), + handleEmpty( connectionProviderClass ), + handleEmpty( poolMinSize ), + handleEmpty( poolMaxSize ) ); + } + + static String handleEmpty(String value) { return isNotEmpty( value ) ? value : DEFAULT; } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DatasourceConnectionProviderImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DatasourceConnectionProviderImpl.java index d5cb499e5a8a..be99c3497d6f 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DatasourceConnectionProviderImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DatasourceConnectionProviderImpl.java @@ -157,36 +157,42 @@ public DatabaseConnectionInfo getDatabaseConnectionInfo(Dialect dialect) { @Override public DatabaseConnectionInfo getDatabaseConnectionInfo(Dialect dialect, ExtractedDatabaseMetaData metaData) { - final String url; - final String driver; - final String isolationLevel; - if ( metaData != null ) { - url = metaData.getUrl(); - driver = metaData.getDriver(); - isolationLevel = toIsolationNiceName( metaData.getTransactionIsolation() ) - + " [default " + toIsolationNiceName( metaData.getDefaultTransactionIsolation() ) + "]"; - } - else { - url = null; - driver = null; - isolationLevel = null; - } - return new DatabaseConnectionInfoImpl( DatasourceConnectionProviderImpl.class, - url, - driver, + metaData == null ? null : metaData.getUrl(), + metaData == null ? null : metaData.getDriver(), dialect.getVersion(), null, - isolationLevel, + metaData == null + ? null + : toIsolationNiceName( metaData.getTransactionIsolation() ) + + " [default " + toIsolationNiceName( metaData.getDefaultTransactionIsolation() ) + "]", null, null ) { @Override public String toInfoString() { - return dataSourceJndiName != null - ? "\tDataSource JNDI name [" + dataSourceJndiName + "]\n" + super.toInfoString() - : super.toInfoString(); + var infoString = new StringBuilder(); + if ( dataSourceJndiName != null ) { + infoString + .append( "\tDataSource JNDI name [" ) + .append( dataSourceJndiName ) + .append( "]\n" ); + } + if ( metaData != null ) { + infoString + .append( "\tDatabase: ") + .append( handleEmpty( metaData.getDatabaseProductName() ) ) + .append( " " ) + .append( handleEmpty( metaData.getDatabaseProductVersion() ) ) + .append( "\n\t\tCatalog: ") + .append( handleEmpty( metaData.getConnectionCatalogName() ) ) + .append( "\n\t\tSchema: ") + .append( handleEmpty( metaData.getConnectionSchemaName() ) ) + .append( "\n" ); + } + infoString.append( super.toInfoString() ); + return infoString.toString(); } }; } diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java index d672ed1229a6..065d5e7fc9ed 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/internal/ExtractedDatabaseMetaDataImpl.java @@ -33,6 +33,9 @@ public class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData private final JdbcEnvironment jdbcEnvironment; private final JdbcConnectionAccess connectionAccess; + private final String databaseProductName; + private final String databaseProductVersion; + private final String connectionCatalogName; private final String connectionSchemaName; @@ -61,6 +64,8 @@ private ExtractedDatabaseMetaDataImpl( JdbcConnectionAccess connectionAccess, String connectionCatalogName, String connectionSchemaName, + String databaseProductName, + String databaseProductVersion, boolean supportsRefCursors, boolean supportsNamedParameters, boolean supportsScrollableResults, @@ -78,6 +83,8 @@ private ExtractedDatabaseMetaDataImpl( this.connectionAccess = connectionAccess; this.connectionCatalogName = connectionCatalogName; this.connectionSchemaName = connectionSchemaName; + this.databaseProductName = databaseProductName; + this.databaseProductVersion = databaseProductVersion; this.supportsRefCursors = supportsRefCursors; this.supportsNamedParameters = supportsNamedParameters; this.supportsScrollableResults = supportsScrollableResults; @@ -138,6 +145,16 @@ public SQLStateType getSqlStateType() { return sqlStateType; } + @Override + public String getDatabaseProductName() { + return databaseProductName; + } + + @Override + public String getDatabaseProductVersion() { + return databaseProductVersion; + } + @Override public String getConnectionCatalogName() { return connectionCatalogName; @@ -195,22 +212,24 @@ public static class Builder { private final boolean jdbcMetadataIsAccessible; private final JdbcConnectionAccess connectionAccess; - private String connectionSchemaName; - private String connectionCatalogName; - - private boolean supportsRefCursors; - private boolean supportsNamedParameters; - private boolean supportsScrollableResults; - private boolean supportsGetGeneratedKeys; - // In absence of DatabaseMetaData batching updates is assumed to be supported - private boolean supportsBatchUpdates = true; - private boolean supportsDataDefinitionInTransaction; - private boolean doesDataDefinitionCauseTransactionCommit; - private SQLStateType sqlStateType; - private String url; - private String driver; - private int defaultTransactionIsolation; - private int transactionIsolation; + private String connectionSchemaName; + private String connectionCatalogName; + private String databaseProductName; + private String databaseProductVersion; + + private boolean supportsRefCursors; + private boolean supportsNamedParameters; + private boolean supportsScrollableResults; + private boolean supportsGetGeneratedKeys; + // In absence of DatabaseMetaData batching updates is assumed to be supported + private boolean supportsBatchUpdates = true; + private boolean supportsDataDefinitionInTransaction; + private boolean doesDataDefinitionCauseTransactionCommit; + private SQLStateType sqlStateType; + private String url; + private String driver; + private int defaultTransactionIsolation; + private int transactionIsolation; public Builder(JdbcEnvironment jdbcEnvironment, boolean jdbcMetadataIsAccessible, JdbcConnectionAccess connectionAccess) { this.jdbcEnvironment = jdbcEnvironment; @@ -221,6 +240,8 @@ public Builder(JdbcEnvironment jdbcEnvironment, boolean jdbcMetadataIsAccessible public Builder apply(DatabaseMetaData databaseMetaData) throws SQLException { connectionCatalogName = databaseMetaData.getConnection().getCatalog(); // NOTE : databaseMetaData.getConnection().getSchema() would require java 1.7 as baseline + databaseProductName = databaseMetaData.getDatabaseProductName(); + databaseProductVersion = databaseMetaData.getDatabaseProductVersion(); supportsRefCursors = StandardRefCursorSupport.supportsRefCursors( databaseMetaData ); supportsNamedParameters = databaseMetaData.supportsNamedParameters(); supportsScrollableResults = databaseMetaData.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE ); @@ -292,6 +313,8 @@ public ExtractedDatabaseMetaDataImpl build() { connectionAccess, connectionCatalogName, connectionSchemaName, + databaseProductName, + databaseProductVersion, supportsRefCursors, supportsNamedParameters, supportsScrollableResults, diff --git a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java index 6ed473de9990..954e68fb4425 100644 --- a/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java +++ b/hibernate-core/src/main/java/org/hibernate/engine/jdbc/env/spi/ExtractedDatabaseMetaData.java @@ -25,6 +25,10 @@ public interface ExtractedDatabaseMetaData { */ JdbcEnvironment getJdbcEnvironment(); + String getDatabaseProductName(); + + String getDatabaseProductVersion(); + /** * Retrieve the name of the catalog in effect when we connected to the database. * diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/datasource/TestDataSourceConnectionProvider.java b/hibernate-core/src/test/java/org/hibernate/orm/test/datasource/TestDataSourceConnectionProvider.java index 98b88915898b..c563b1291ff1 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/datasource/TestDataSourceConnectionProvider.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/datasource/TestDataSourceConnectionProvider.java @@ -17,6 +17,7 @@ import java.util.Map; import java.util.logging.Logger; +@SuppressWarnings( "unused" ) // used by DatasourceTest in this package public class TestDataSourceConnectionProvider extends DatasourceConnectionProviderImpl implements ServiceRegistryAwareService {