HHH-18111 Call EventManager for stored procedures

This commit is contained in:
Philippe Marschall 2024-05-14 15:58:01 +02:00 committed by Christian Beikov
parent 07bfe6ad73
commit ba149a1cdc
2 changed files with 56 additions and 1 deletions

View File

@ -19,6 +19,8 @@ import org.hibernate.JDBCException;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.spi.EventManager;
import org.hibernate.event.spi.HibernateMonitoringEvent;
import org.hibernate.internal.CoreLogging;
import org.hibernate.procedure.internal.ProcedureCallImpl;
import org.hibernate.procedure.internal.ScalarDomainResultBuilder;
@ -74,6 +76,8 @@ public class OutputsImpl implements Outputs {
if ( sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStartNanos = System.nanoTime();
}
final EventManager eventManager = context.getSession().getEventManager();
final HibernateMonitoringEvent jdbcPreparedStatementExecutionEvent = eventManager.beginJdbcPreparedStatementExecutionEvent();
try {
final boolean isResultSet = jdbcStatement.execute();
currentReturnState = buildCurrentReturnState( isResultSet );
@ -82,6 +86,7 @@ public class OutputsImpl implements Outputs {
throw convert( e, "Error calling CallableStatement.getMoreResults" );
}
finally {
eventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
sqlStatementLogger.logSlowQuery( sql, executeStartNanos, this.context.getSession().getJdbcSessionContext() );
}
}

View File

@ -3,16 +3,19 @@ package org.hibernate.event.jfr;
import java.util.List;
import java.util.Locale;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.event.jfr.internal.JdbcPreparedStatementCreationEvent;
import org.hibernate.event.jfr.internal.JdbcPreparedStatementExecutionEvent;
import org.hibernate.procedure.ProcedureCall;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.RequiresDialect;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jakarta.persistence.ParameterMode;
import jdk.jfr.consumer.RecordedEvent;
import org.moditect.jfrunit.EnableEvent;
import org.moditect.jfrunit.JfrEventTest;
@ -85,6 +88,53 @@ public class JdbcPreparedStatementEventTests {
assertThat( events ).hasSize( 0 );
}
@Test
@RequiresDialect(H2Dialect.class)
@EnableEvent(JdbcPreparedStatementCreationEvent.NAME)
@EnableEvent(JdbcPreparedStatementExecutionEvent.NAME)
public void testJdbcPreparedStatementEventStoredProcedure(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
ProcedureCall call = session.createStoredProcedureCall("DB_OBJECT_SQL", String.class)
.registerStoredProcedureParameter(1, String.class, ParameterMode.IN)
.registerStoredProcedureParameter(2, String.class, ParameterMode.IN)
.setParameter(1, "USER")
.setParameter(2, "SA");
boolean hasResult = call.execute();
assertThat( hasResult ).isTrue();
Object createSa = call.getSingleResult();
assertThat( createSa ).isInstanceOf( String.class );
assertThat( ((String) createSa).toLowerCase( Locale.ROOT ) ).contains( "create user if not exists " );
final List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( JdbcPreparedStatementCreationEvent.NAME )
|| eventName.equals( JdbcPreparedStatementExecutionEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 2 );
RecordedEvent preparedStatementCreationEvent = events.get( 0 );
assertThat( preparedStatementCreationEvent.getEventType().getName() )
.isEqualTo( JdbcPreparedStatementCreationEvent.NAME );
assertThat( preparedStatementCreationEvent.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( preparedStatementCreationEvent.getString( "sql" ).toLowerCase( Locale.ROOT ) )
.contains( "{call " );
RecordedEvent preparedStatementExecutionEvent = events.get( 1 );
assertThat( preparedStatementExecutionEvent.getEventType().getName() )
.isEqualTo( JdbcPreparedStatementExecutionEvent.NAME );
assertThat( preparedStatementExecutionEvent.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( preparedStatementExecutionEvent.getString( "sql" ) )
.isEqualTo( preparedStatementCreationEvent.getString( "sql" ) );
}
);
}
@Entity(name = "TestEntity")
public static class TestEntity {
@Id