HHH-12688 - Duplicated Error Information Displayed in the Log

This commit is contained in:
Vlad Mihalcea 2018-06-19 14:43:31 +03:00
parent 62b2af760e
commit bcb71fcdd6
6 changed files with 129 additions and 13 deletions

View File

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

View File

@ -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;

View File

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

View File

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

View File

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

View File

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