Skip to content

Commit 48430ea

Browse files
committed
HHH-19399 log JDBC errors/warnings via dedicated log categories
1 parent f7870db commit 48430ea

File tree

7 files changed

+87
-55
lines changed

7 files changed

+87
-55
lines changed

hibernate-core/src/main/java/org/hibernate/cfg/JdbcSettings.java

+6
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,9 @@ public interface JdbcSettings extends C3p0Settings, AgroalSettings, HikariCPSett
452452
/**
453453
* When enabled, specifies that JDBC statement warnings should be logged.
454454
* <p>
455+
* Logging of JDBC warnings may also be controlled via the log category
456+
* {@value org.hibernate.engine.jdbc.spi.SQLExceptionLogging#WARN_NAME}.
457+
* <p>
455458
* The default is determined by
456459
* {@link org.hibernate.dialect.Dialect#isJdbcLogWarningsEnabledByDefault()}.
457460
*
@@ -463,6 +466,9 @@ public interface JdbcSettings extends C3p0Settings, AgroalSettings, HikariCPSett
463466

464467
/**
465468
* When enabled, specifies that JDBC errors should be logged before being rethrown.
469+
* <p>
470+
* Logging of JDBC errors may also be controlled via the log category
471+
* {@value org.hibernate.engine.jdbc.spi.SQLExceptionLogging#ERROR_NAME}.
466472
*
467473
* @settingDefault {@code true}
468474
*

hibernate-core/src/main/java/org/hibernate/dialect/temptable/TemporaryTableHelper.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,11 @@ public static void cleanTemporaryTableRows(
172172
}
173173
}
174174

175-
175+
/**
176+
* Differs from
177+
* {@link org.hibernate.engine.jdbc.spi.SqlExceptionHelper.StandardWarningHandler}
178+
* because it logs only at DEBUG level.
179+
*/
176180
private static final SqlExceptionHelper.WarningHandler WARNING_HANDLER =
177181
new SqlExceptionHelper.WarningHandlerLoggingSupport() {
178182
public boolean doProcess() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/*
2+
* SPDX-License-Identifier: Apache-2.0
3+
* Copyright Red Hat Inc. and Hibernate Authors
4+
*/
5+
package org.hibernate.engine.jdbc.spi;
6+
7+
import org.hibernate.internal.log.SubSystemLogging;
8+
import org.jboss.logging.BasicLogger;
9+
import org.jboss.logging.Logger;
10+
import org.jboss.logging.annotations.LogMessage;
11+
import org.jboss.logging.annotations.Message;
12+
import org.jboss.logging.annotations.MessageLogger;
13+
14+
import java.lang.invoke.MethodHandles;
15+
16+
import static org.jboss.logging.Logger.Level.WARN;
17+
18+
/**
19+
* Responsible for logging SQL {@linkplain java.sql.SQLException errors}
20+
* and {@linkplain java.sql.SQLWarning warnings}.
21+
*
22+
* @author Gavin King
23+
* @since 7
24+
*/
25+
@MessageLogger(projectCode = "HHH")
26+
public interface SQLExceptionLogging extends BasicLogger {
27+
String ERROR_NAME = SubSystemLogging.BASE + ".jdbc.error";
28+
String WARN_NAME = SubSystemLogging.BASE + ".jdbc.warn";
29+
30+
SQLExceptionLogging ERROR_LOG = Logger.getMessageLogger( MethodHandles.lookup(), SQLExceptionLogging.class, ERROR_NAME );
31+
SQLExceptionLogging WARNING_LOG = Logger.getMessageLogger( MethodHandles.lookup(), SQLExceptionLogging.class, WARN_NAME );
32+
33+
@LogMessage(level = WARN)
34+
@Message(value = "ErrorCode: %s, SQLState: %s", id = 247)
35+
void logErrorCodes(int errorCode, String sqlState);
36+
}

hibernate-core/src/main/java/org/hibernate/engine/jdbc/spi/SqlExceptionHelper.java

+30-41
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
*/
55
package org.hibernate.engine.jdbc.spi;
66

7-
import java.lang.invoke.MethodHandles;
87
import java.sql.Connection;
98
import java.sql.SQLException;
109
import java.sql.SQLWarning;
@@ -16,9 +15,9 @@
1615
import org.hibernate.exception.internal.SQLStateConversionDelegate;
1716
import org.hibernate.exception.internal.StandardSQLExceptionConverter;
1817
import org.hibernate.exception.spi.SQLExceptionConverter;
19-
import org.hibernate.internal.CoreMessageLogger;
2018

21-
import org.jboss.logging.Logger;
19+
import static org.hibernate.engine.jdbc.spi.SQLExceptionLogging.ERROR_LOG;
20+
import static org.hibernate.engine.jdbc.spi.SQLExceptionLogging.WARNING_LOG;
2221
import org.jboss.logging.Logger.Level;
2322

2423
/**
@@ -27,11 +26,6 @@
2726
* @author Steve Ebersole
2827
*/
2928
public class SqlExceptionHelper {
30-
private static final CoreMessageLogger LOG = Logger.getMessageLogger(
31-
MethodHandles.lookup(),
32-
CoreMessageLogger.class,
33-
SqlExceptionHelper.class.getName()
34-
);
3529

3630
private final boolean logWarnings;
3731
private final boolean logErrors;
@@ -142,18 +136,18 @@ public JDBCException convert(SQLException sqlException, Supplier<String> message
142136
*/
143137
public void logExceptions(SQLException sqlException, String message) {
144138
if ( logErrors) {
145-
if ( LOG.isEnabled( Level.WARN ) ) {
139+
if ( ERROR_LOG.isEnabled( Level.WARN ) ) {
146140
SQLException currentException = sqlException;
147141
while ( currentException != null ) {
148142
if ( !isDuplicate( currentException, sqlException ) ) {
149-
LOG.warn( errorCodeMessage( sqlException ) );
150-
LOG.warn( sqlException.getMessage() );
143+
ERROR_LOG.logErrorCodes( sqlException.getErrorCode(), sqlException.getSQLState() );
144+
ERROR_LOG.warn( sqlException.getMessage() );
151145
}
152146
currentException = currentException.getNextException();
153147
}
154148
}
155-
if ( LOG.isDebugEnabled() ) {
156-
LOG.debug( message, sqlException );
149+
if ( ERROR_LOG.isDebugEnabled() ) {
150+
ERROR_LOG.debug( message, sqlException );
157151
}
158152
}
159153
}
@@ -175,18 +169,10 @@ private static boolean isDuplicate(SQLException currentException, SQLException b
175169
return false;
176170
}
177171

178-
private static String errorCodeMessage(SQLException sqlException) {
179-
return "ErrorCode: "
180-
+ sqlException.getErrorCode()
181-
+ ", SQLState: "
182-
+ sqlException.getSQLState()
183-
+ ( sqlException instanceof SQLWarning ? " [warning]" : " [error]" );
184-
}
185-
186172
// SQLWarning ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
187173

188174
/**
189-
* Contract for handling {@linkplain SQLWarning warnings}
175+
* Contract for handling {@linkplain SQLWarning warnings}.
190176
*/
191177
public interface WarningHandler {
192178
/**
@@ -218,8 +204,11 @@ public interface WarningHandler {
218204
*/
219205
public abstract static class WarningHandlerLoggingSupport implements WarningHandler {
220206
@Override
221-
public final void handleWarning(SQLWarning warning) {
222-
logWarning( errorCodeMessage( warning ), warning.getMessage() );
207+
public void handleWarning(SQLWarning warning) {
208+
logWarning(
209+
"SQL Warning Code: " + warning.getErrorCode() + ", SQLState: " + warning.getSQLState(),
210+
warning.getMessage()
211+
);
223212
}
224213

225214
/**
@@ -248,18 +237,24 @@ public StandardWarningHandler(String introMessage) {
248237

249238
@Override
250239
public boolean doProcess() {
251-
return LOG.isEnabled( Level.WARN );
240+
return WARNING_LOG.isEnabled( Level.WARN );
252241
}
253242

254243
@Override
255244
public void prepare(SQLWarning warning) {
256-
LOG.debug( introMessage, warning );
245+
WARNING_LOG.debug( introMessage, warning );
246+
}
247+
248+
@Override
249+
public final void handleWarning(SQLWarning warning) {
250+
WARNING_LOG.logErrorCodes( warning.getErrorCode(), warning.getSQLState() );
251+
WARNING_LOG.warn( warning.getMessage() );
257252
}
258253

259254
@Override
260255
protected void logWarning(String description, String message) {
261-
LOG.warn( description );
262-
LOG.warn( message );
256+
WARNING_LOG.warn( description );
257+
WARNING_LOG.warn( message );
263258
}
264259
}
265260

@@ -275,9 +270,7 @@ protected void logWarning(String description, String message) {
275270
* @param warning The warning to walk
276271
* @param handler The handler
277272
*/
278-
public void walkWarnings(
279-
SQLWarning warning,
280-
WarningHandler handler) {
273+
public void walkWarnings(SQLWarning warning, WarningHandler handler) {
281274
if ( warning != null && handler.doProcess() ) {
282275
handler.prepare( warning );
283276
while ( warning != null ) {
@@ -310,24 +303,22 @@ public void logAndClearWarnings(Statement statement) {
310303
*
311304
* @see #walkWarnings
312305
*/
313-
public void handleAndClearWarnings(
314-
Connection connection,
315-
WarningHandler handler) {
306+
public void handleAndClearWarnings(Connection connection, WarningHandler handler) {
316307
try {
317308
if ( logWarnings ) {
318309
walkWarnings( connection.getWarnings(), handler );
319310
}
320311
}
321312
catch (SQLException sqle) {
322313
// workaround for WebLogic
323-
LOG.debug( "could not log warnings", sqle );
314+
WARNING_LOG.debug( "could not log warnings", sqle );
324315
}
325316
try {
326317
// Sybase fail if we don't do that, sigh...
327318
connection.clearWarnings();
328319
}
329320
catch (SQLException sqle) {
330-
LOG.debug( "could not clear warnings", sqle );
321+
WARNING_LOG.debug( "could not clear warnings", sqle );
331322
}
332323
}
333324

@@ -339,9 +330,7 @@ public void handleAndClearWarnings(
339330
*
340331
* @see #walkWarnings
341332
*/
342-
public void handleAndClearWarnings(
343-
Statement statement,
344-
WarningHandler handler) {
333+
public void handleAndClearWarnings(Statement statement, WarningHandler handler) {
345334
// See HHH-9174. Statement.getWarnings() can be an expensive call for some JDBC drivers.
346335
// Don't do it unless the log level would actually allow a warning to be logged.
347336
if ( logWarnings ) {
@@ -350,15 +339,15 @@ public void handleAndClearWarnings(
350339
}
351340
catch (SQLException sqlException) {
352341
// workaround for WebLogic
353-
LOG.debug( "could not log warnings", sqlException );
342+
WARNING_LOG.debug( "could not log warnings", sqlException );
354343
}
355344
}
356345
try {
357346
// Sybase fail if we don't do that, sigh...
358347
statement.clearWarnings();
359348
}
360349
catch (SQLException sqle) {
361-
LOG.debug( "could not clear warnings", sqle );
350+
WARNING_LOG.debug( "could not clear warnings", sqle );
362351
}
363352
}
364353
}

hibernate-core/src/main/java/org/hibernate/internal/CoreMessageLogger.java

+3-3
Original file line numberDiff line numberDiff line change
@@ -291,9 +291,9 @@ void scopingTypesToSessionFactoryAfterAlreadyScoped(
291291
SessionFactoryImplementor factory,
292292
SessionFactoryImplementor factory2);
293293

294-
@LogMessage(level = WARN)
295-
@Message(value = "SQL Error: %s, SQLState: %s", id = 247)
296-
void sqlWarning(int errorCode, String sqlState);
294+
// @LogMessage(level = WARN)
295+
// @Message(value = "SQL Error: %s, SQLState: %s", id = 247)
296+
// void sqlWarning(int errorCode, String sqlState);
297297

298298
@LogMessage(level = INFO)
299299
@Message(value = "Start time: %s", id = 251)

hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/AbstractInformationExtractorImpl.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141

4242
import static java.util.Collections.addAll;
4343
import static org.hibernate.boot.model.naming.DatabaseIdentifier.toIdentifier;
44+
import static org.hibernate.engine.jdbc.spi.SQLExceptionLogging.ERROR_LOG;
4445
import static org.hibernate.internal.util.StringHelper.EMPTY_STRINGS;
4546
import static org.hibernate.internal.util.StringHelper.isBlank;
4647
import static org.hibernate.internal.util.StringHelper.splitTrimmingTokens;
@@ -398,7 +399,7 @@ private Identifier getCurrentSchema() {
398399
.toIdentifier( extractionContext.getJdbcConnection().getSchema() );
399400
}
400401
catch (SQLException sqle) {
401-
LOG.sqlWarning( sqle.getErrorCode(), sqle.getSQLState() );
402+
ERROR_LOG.logErrorCodes( sqle.getErrorCode(), sqle.getSQLState() );
402403
}
403404
catch (AbstractMethodError ignore) {
404405
// jConnect and jTDS report that they "support" schemas, but they don't really
@@ -424,7 +425,7 @@ private Identifier getCurrentCatalog() {
424425
.toIdentifier( extractionContext.getJdbcConnection().getCatalog() );
425426
}
426427
catch (SQLException sqle) {
427-
LOG.sqlWarning( sqle.getErrorCode(), sqle.getSQLState() );
428+
ERROR_LOG.logErrorCodes( sqle.getErrorCode(), sqle.getSQLState() );
428429
}
429430
}
430431
return currentCatalog;
@@ -443,7 +444,7 @@ private String getCurrentCatalogFilter(JdbcEnvironment jdbcEnvironment) {
443444
currentCatalogFilter = extractionContext.getJdbcConnection().getCatalog();
444445
}
445446
catch (SQLException sqle) {
446-
LOG.sqlWarning( sqle.getErrorCode(), sqle.getSQLState() );
447+
ERROR_LOG.logErrorCodes( sqle.getErrorCode(), sqle.getSQLState() );
447448
}
448449
}
449450
return currentCatalogFilter;
@@ -463,7 +464,7 @@ private String getCurrentSchemaFilter(JdbcEnvironment jdbcEnvironment) {
463464
currentSchemaFilter = extractionContext.getJdbcConnection().getSchema();
464465
}
465466
catch (SQLException sqle) {
466-
LOG.sqlWarning( sqle.getErrorCode(), sqle.getSQLState() );
467+
ERROR_LOG.logErrorCodes( sqle.getErrorCode(), sqle.getSQLState() );
467468
}
468469
catch (AbstractMethodError ignore) {
469470
// jConnect and jTDS report that they "support" schemas, but they don't really

hibernate-core/src/test/java/org/hibernate/orm/test/annotations/uniqueconstraint/UniqueConstraintBatchingTest.java

+2-6
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66

77
import org.hibernate.cfg.AvailableSettings;
88
import org.hibernate.dialect.H2Dialect;
9-
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
10-
import org.hibernate.internal.CoreMessageLogger;
9+
import org.hibernate.engine.jdbc.spi.SQLExceptionLogging;
1110

1211
import org.hibernate.testing.orm.junit.JiraKey;
1312
import org.hibernate.testing.logger.LoggerInspectionRule;
@@ -20,11 +19,9 @@
2019
import org.junit.jupiter.api.BeforeEach;
2120
import org.junit.jupiter.api.Test;
2221

23-
import org.jboss.logging.Logger;
2422

2523
import jakarta.persistence.PersistenceException;
2624

27-
import java.lang.invoke.MethodHandles;
2825

2926
import static org.junit.jupiter.api.Assertions.assertEquals;
3027
import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -47,8 +44,7 @@
4744
public class UniqueConstraintBatchingTest {
4845

4946
@Rule
50-
public LoggerInspectionRule logInspection = new LoggerInspectionRule(
51-
Logger.getMessageLogger( MethodHandles.lookup(), CoreMessageLogger.class, SqlExceptionHelper.class.getName() ) );
47+
public LoggerInspectionRule logInspection = new LoggerInspectionRule( SQLExceptionLogging.ERROR_LOG );
5248

5349
private Triggerable triggerable;
5450

0 commit comments

Comments
 (0)