HHH-12688 - Duplicated Error Information Displayed in the Log
This commit is contained in:
parent
62b2af760e
commit
bcb71fcdd6
|
@ -10,6 +10,8 @@ import java.sql.Connection;
|
|||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.Statement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.exception.internal.SQLStateConverter;
|
||||
|
@ -124,11 +126,22 @@ public class SqlExceptionHelper {
|
|||
LOG.debug( message, sqlException );
|
||||
}
|
||||
final boolean warnEnabled = LOG.isEnabled( Level.WARN );
|
||||
|
||||
List<String> previousWarnMessages = new ArrayList<>();
|
||||
List<String> previousErrorMessages = new ArrayList<>();
|
||||
|
||||
while ( sqlException != null ) {
|
||||
if ( warnEnabled ) {
|
||||
LOG.warn( "SQL Error: " + sqlException.getErrorCode() + ", SQLState: " + sqlException.getSQLState() );
|
||||
String warnMessage = "SQL Error: " + sqlException.getErrorCode() + ", SQLState: " + sqlException.getSQLState();
|
||||
if ( !previousWarnMessages.contains( warnMessage ) ) {
|
||||
LOG.warn( warnMessage );
|
||||
previousWarnMessages.add( warnMessage );
|
||||
}
|
||||
}
|
||||
if ( !previousErrorMessages.contains( sqlException.getMessage() ) ) {
|
||||
LOG.error( sqlException.getMessage() );
|
||||
previousErrorMessages.add( sqlException.getMessage() );
|
||||
}
|
||||
LOG.error( sqlException.getMessage() );
|
||||
sqlException = sqlException.getNextException();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
*/
|
||||
package org.hibernate.test.annotations.immutable;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.boot.model.process.internal.ScanningCoordinator;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.internal.SessionImpl;
|
||||
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.test.annotations.uniqueconstraint;
|
||||
|
||||
import java.util.Map;
|
||||
import javax.persistence.PersistenceException;
|
||||
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
|
||||
import org.hibernate.internal.CoreMessageLogger;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.logger.LoggerInspectionRule;
|
||||
import org.hibernate.testing.logger.Triggerable;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import static org.hibernate.testing.transaction.TransactionUtil.doInJPA;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* @author Vlad Mihalcea
|
||||
*/
|
||||
@TestForIssue(jiraKey = "HHH-12688")
|
||||
public class UniqueConstraintBatchingTest extends BaseEntityManagerFunctionalTestCase {
|
||||
|
||||
protected Class[] getAnnotatedClasses() {
|
||||
return new Class[] {
|
||||
Room.class,
|
||||
Building.class,
|
||||
House.class
|
||||
};
|
||||
}
|
||||
|
||||
@Rule
|
||||
public LoggerInspectionRule logInspection = new LoggerInspectionRule(
|
||||
Logger.getMessageLogger( CoreMessageLogger.class, SqlExceptionHelper.class.getName() ) );
|
||||
|
||||
private Triggerable triggerable;
|
||||
|
||||
@Override
|
||||
protected void addConfigOptions(Map options) {
|
||||
options.put( AvailableSettings.STATEMENT_BATCH_SIZE, 5 );
|
||||
triggerable = logInspection.watchForLogMessages( "Unique index" );
|
||||
triggerable.reset();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBatching() throws Exception {
|
||||
Room livingRoom = new Room();
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
livingRoom.setId( 1l );
|
||||
livingRoom.setName( "livingRoom" );
|
||||
entityManager.persist( livingRoom );
|
||||
} );
|
||||
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
House house = new House();
|
||||
house.setId( 1l );
|
||||
house.setCost( 100 );
|
||||
house.setHeight( 1000l );
|
||||
house.setRoom( livingRoom );
|
||||
entityManager.persist( house );
|
||||
} );
|
||||
|
||||
try {
|
||||
doInJPA( this::entityManagerFactory, entityManager -> {
|
||||
House house2 = new House();
|
||||
house2.setId( 2l );
|
||||
house2.setCost( 100 );
|
||||
house2.setHeight( 1001l );
|
||||
house2.setRoom( livingRoom );
|
||||
entityManager.persist( house2 );
|
||||
} );
|
||||
fail( "Should throw exception" );
|
||||
}
|
||||
catch (PersistenceException e) {
|
||||
assertEquals( 1, triggerable.triggerMessages().size() );
|
||||
assertTrue( triggerable.triggerMessage().startsWith( "Unique index or primary key violation" ) );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -94,7 +94,7 @@ public class LockNoneWarmingTest extends BaseCoreFunctionalTestCase {
|
|||
query.setLockMode( "i", LockMode.NONE );
|
||||
query.setLockMode( "b", LockMode.NONE );
|
||||
query.list();
|
||||
assertFalse( triggerable.triggerMessage(), triggerable.wasTriggered() );
|
||||
assertFalse( "Log message was not triggered", triggerable.wasTriggered() );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,9 @@
|
|||
package org.hibernate.testing.logger;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
|
@ -16,8 +18,8 @@ import org.jboss.logging.Logger.Level;
|
|||
final class TriggerOnPrefixLogListener implements LogListener, Triggerable {
|
||||
|
||||
private Set<String> expectedPrefixes = new HashSet<>();
|
||||
private final AtomicBoolean triggered = new AtomicBoolean( false );
|
||||
private final AtomicReference<String> triggerMessage = new AtomicReference<String>( null );
|
||||
|
||||
private final List<String> triggerMessages = new CopyOnWriteArrayList<>();
|
||||
|
||||
public TriggerOnPrefixLogListener(String expectedPrefix) {
|
||||
expectedPrefixes.add( expectedPrefix );
|
||||
|
@ -32,8 +34,7 @@ final class TriggerOnPrefixLogListener implements LogListener, Triggerable {
|
|||
if ( renderedMessage != null ) {
|
||||
for ( String expectedPrefix : expectedPrefixes ) {
|
||||
if ( renderedMessage.startsWith( expectedPrefix ) ) {
|
||||
triggered.set( true );
|
||||
triggerMessage.set( renderedMessage );
|
||||
triggerMessages.add( renderedMessage );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,17 +42,21 @@ final class TriggerOnPrefixLogListener implements LogListener, Triggerable {
|
|||
|
||||
@Override
|
||||
public String triggerMessage() {
|
||||
return triggerMessage.get();
|
||||
return !triggerMessages.isEmpty() ? triggerMessages.get(0) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> triggerMessages() {
|
||||
return triggerMessages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean wasTriggered() {
|
||||
return triggered.get();
|
||||
return !triggerMessages.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
triggered.set( false );
|
||||
triggerMessage.set( null );
|
||||
triggerMessages.clear();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
*/
|
||||
package org.hibernate.testing.logger;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public interface Triggerable {
|
||||
|
||||
String triggerMessage();
|
||||
|
@ -13,4 +16,8 @@ public interface Triggerable {
|
|||
boolean wasTriggered();
|
||||
|
||||
void reset();
|
||||
|
||||
default List<String> triggerMessages() {
|
||||
return Collections.singletonList( triggerMessage() );
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue