HHH-17270 Expose JFR events for SessionEventLister

This commit is contained in:
Andrea Boriero 2023-09-28 17:11:04 +02:00 committed by Steve Ebersole
parent e4128b1e1a
commit d27cc10438
56 changed files with 2921 additions and 278 deletions

View File

@ -17,6 +17,9 @@ import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.jfr.CachePutEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.event.jfr.internal.JfrEventManager.CacheActionDescription;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.PostCommitInsertEventListener;
@ -161,11 +164,23 @@ public class EntityInsertAction extends AbstractEntityInsertAction {
protected boolean cacheInsert(EntityPersister persister, Object ck) {
SharedSessionContractImplementor session = getSession();
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
final EntityDataAccess cacheAccessStrategy = persister.getCacheAccessStrategy();
boolean insert = false;
try {
session.getEventListenerManager().cachePutStart();
return persister.getCacheAccessStrategy().insert( session, ck, cacheEntry, version );
insert = cacheAccessStrategy.insert( session, ck, cacheEntry, version );
return insert;
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cacheAccessStrategy,
getPersister(),
insert,
CacheActionDescription.ENTITY_INSERT
);
session.getEventListenerManager().cachePutEnd();
}
}
@ -240,11 +255,22 @@ public class EntityInsertAction extends AbstractEntityInsertAction {
protected boolean cacheAfterInsert(EntityDataAccess cache, Object ck) {
SharedSessionContractImplementor session = getSession();
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
boolean afterInsert = false;
try {
eventListenerManager.cachePutStart();
return cache.afterInsert( session, ck, cacheEntry, version );
afterInsert = cache.afterInsert( session, ck, cacheEntry, version );
return afterInsert;
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cache,
getPersister(),
afterInsert,
CacheActionDescription.ENTITY_AFTER_INSERT
);
eventListenerManager.cachePutEnd();
}
}

View File

@ -19,6 +19,8 @@ import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.event.jfr.CachePutEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.event.service.spi.EventListenerGroup;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.PostCommitUpdateEventListener;
@ -307,11 +309,23 @@ public class EntityUpdateAction extends EntityAction {
protected boolean updateCache(EntityPersister persister, Object previousVersion, Object ck) {
final SharedSessionContractImplementor session = getSession();
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
final EntityDataAccess cacheAccessStrategy = persister.getCacheAccessStrategy();
boolean update = false;
try {
session.getEventListenerManager().cachePutStart();
return persister.getCacheAccessStrategy().update( session, ck, cacheEntry, nextVersion, previousVersion );
update = cacheAccessStrategy.update( session, ck, cacheEntry, nextVersion, previousVersion );
return update;
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cacheAccessStrategy,
getPersister(),
update,
JfrEventManager.CacheActionDescription.ENTITY_UPDATE
);
session.getEventListenerManager().cachePutEnd();
}
}
@ -420,10 +434,21 @@ public class EntityUpdateAction extends EntityAction {
protected void cacheAfterUpdate(EntityDataAccess cache, Object ck, SharedSessionContractImplementor session) {
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
boolean put = false;
try {
eventListenerManager.cachePutStart();
boolean put = cache.afterUpdate( session, ck, cacheEntry, nextVersion, previousVersion, lock );
put = cache.afterUpdate( session, ck, cacheEntry, nextVersion, previousVersion, lock );
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cache,
getPersister(),
put,
JfrEventManager.CacheActionDescription.ENTITY_AFTER_UPDATE
);
final StatisticsImplementor statistics = session.getFactory().getStatistics();
if ( put && statistics.isStatisticsEnabled() ) {
statistics.entityCachePut(
@ -431,8 +456,6 @@ public class EntityUpdateAction extends EntityAction {
cache.getRegion().getName()
);
}
}
finally {
eventListenerManager.cachePutEnd();
}

View File

@ -17,6 +17,9 @@ import org.hibernate.cache.spi.QueryResultsCache;
import org.hibernate.cache.spi.QueryResultsRegion;
import org.hibernate.cache.spi.TimestampsCache;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.jfr.CacheGetEvent;
import org.hibernate.event.jfr.CachePutEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import static org.hibernate.cache.spi.SecondLevelCacheLogger.L2CACHE_LOGGER;
@ -61,11 +64,19 @@ public class QueryResultsCacheImpl implements QueryResultsCache {
deepCopy( results )
);
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
try {
session.getEventListenerManager().cachePutStart();
cacheRegion.putIntoCache( key, cacheItem, session );
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cacheRegion,
true,
JfrEventManager.CacheActionDescription.QUERY_RESULT
);
session.getEventListenerManager().cachePutEnd();
}
@ -142,11 +153,18 @@ public class QueryResultsCacheImpl implements QueryResultsCache {
private CacheItem getCachedData(QueryKey key, SharedSessionContractImplementor session) {
CacheItem cachedItem = null;
final CacheGetEvent cacheGetEvent = JfrEventManager.beginCacheGetEvent();
try {
session.getEventListenerManager().cacheGetStart();
cachedItem = (CacheItem) cacheRegion.getFromCache( key, session );
}
finally {
JfrEventManager.completeCacheGetEvent(
cacheGetEvent,
session,
cacheRegion,
cachedItem != null
);
session.getEventListenerManager().cacheGetEnd( cachedItem != null );
}
return cachedItem;

View File

@ -14,6 +14,9 @@ import org.hibernate.cache.spi.TimestampsRegion;
import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.jfr.CacheGetEvent;
import org.hibernate.event.jfr.CachePutEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.stat.spi.StatisticsImplementor;
import org.jboss.logging.Logger;
@ -58,7 +61,7 @@ public class TimestampsCacheEnabledImpl implements TimestampsCache {
if ( debugEnabled ) {
log.debugf( "Pre-invalidating space [%s], timestamp: %s", space, ts );
}
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
try {
eventListenerManager.cachePutStart();
@ -67,6 +70,13 @@ public class TimestampsCacheEnabledImpl implements TimestampsCache {
timestampsRegion.putIntoCache( space, ts, session );
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
timestampsRegion,
true,
JfrEventManager.CacheActionDescription.TIMESTAMP_PRE_INVALIDATE
);
eventListenerManager.cachePutEnd();
}
@ -92,11 +102,19 @@ public class TimestampsCacheEnabledImpl implements TimestampsCache {
}
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
try {
eventListenerManager.cachePutStart();
timestampsRegion.putIntoCache( space, ts, session );
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
timestampsRegion,
true,
JfrEventManager.CacheActionDescription.TIMESTAMP_INVALIDATE
);
eventListenerManager.cachePutEnd();
if ( stats ) {
@ -175,11 +193,18 @@ public class TimestampsCacheEnabledImpl implements TimestampsCache {
private Long getLastUpdateTimestampForSpace(String space, SharedSessionContractImplementor session) {
Long ts = null;
final CacheGetEvent cacheGetEvent = JfrEventManager.beginCacheGetEvent();
try {
session.getEventListenerManager().cacheGetStart();
ts = (Long) timestampsRegion.getFromCache( space, session );
}
finally {
JfrEventManager.completeCacheGetEvent(
cacheGetEvent,
session,
timestampsRegion,
ts != null
);
session.getEventListenerManager().cacheGetEnd( ts != null );
}
return ts;

View File

@ -12,7 +12,11 @@ import org.hibernate.cache.MutableCacheKeyBuilder;
import org.hibernate.cache.spi.access.CachedDomainDataAccess;
import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.jfr.CacheGetEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.type.descriptor.converter.spi.BasicValueConverter;
import org.hibernate.type.descriptor.java.JavaType;
@ -28,14 +32,58 @@ public final class CacheHelper {
public static Object fromSharedCache(
SharedSessionContractImplementor session,
Object cacheKey,
EntityPersister persister,
CachedDomainDataAccess cacheAccess) {
return fromSharedCache( session, cacheKey, persister, false, cacheAccess );
}
public static Object fromSharedCache(
SharedSessionContractImplementor session,
Object cacheKey,
EntityPersister persister,
boolean isNaturalKey,
CachedDomainDataAccess cacheAccess) {
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
Object cachedValue = null;
eventListenerManager.cacheGetStart();
final CacheGetEvent cacheGetEvent = JfrEventManager.beginCacheGetEvent();
try {
cachedValue = cacheAccess.get( session, cacheKey );
}
finally {
JfrEventManager.completeCacheGetEvent(
cacheGetEvent,
session,
cacheAccess.getRegion(),
persister,
isNaturalKey,
cachedValue != null
);
eventListenerManager.cacheGetEnd( cachedValue != null );
}
return cachedValue;
}
public static Object fromSharedCache(
SharedSessionContractImplementor session,
Object cacheKey,
CollectionPersister persister,
CachedDomainDataAccess cacheAccess) {
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
Object cachedValue = null;
eventListenerManager.cacheGetStart();
final CacheGetEvent cacheGetEvent = JfrEventManager.beginCacheGetEvent();
try {
cachedValue = cacheAccess.get( session, cacheKey );
}
finally {
JfrEventManager.completeCacheGetEvent(
cacheGetEvent,
session,
cacheAccess.getRegion(),
persister,
cachedValue != null
);
eventListenerManager.cacheGetEnd( cachedValue != null );
}
return cachedValue;

View File

@ -23,6 +23,8 @@ import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.Resolution;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.jfr.CachePutEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.NaturalIdLogging;
import org.hibernate.metamodel.mapping.NaturalIdMapping;
@ -268,11 +270,14 @@ public class NaturalIdResolutionsImpl implements NaturalIdResolutions, Serializa
switch ( source ) {
case LOAD: {
if ( CacheHelper.fromSharedCache( s, cacheKey, cacheAccess ) != null ) {
if ( CacheHelper.fromSharedCache( s, cacheKey, persister, cacheAccess ) != null ) {
// prevent identical re-cachings
return;
}
final boolean put = cacheAccess.putFromLoad(
boolean put = false;
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
try {
put = cacheAccess.putFromLoad(
s,
cacheKey,
id,
@ -285,17 +290,45 @@ public class NaturalIdResolutionsImpl implements NaturalIdResolutions, Serializa
cacheAccess.getRegion().getName()
);
}
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session(),
cacheAccess,
rootEntityPersister,
put,
true,
JfrEventManager.CacheActionDescription.ENTITY_LOAD
);
}
break;
}
case INSERT: {
final boolean put = cacheAccess.insert( s, cacheKey, id );
boolean put = false;
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
try {
put = cacheAccess.insert( s, cacheKey, id );
if ( put && statistics.isStatisticsEnabled() ) {
statistics.naturalIdCachePut(
rootEntityDescriptor.getNavigableRole(),
cacheAccess.getRegion().getName()
);
}
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session(),
cacheAccess,
rootEntityPersister,
put,
true,
JfrEventManager.CacheActionDescription.ENTITY_INSERT
);
}
s.asEventSource().getActionQueue().registerProcess(
(success, session) -> {
@ -326,32 +359,62 @@ public class NaturalIdResolutionsImpl implements NaturalIdResolutions, Serializa
cacheAccess.remove( s, previousCacheKey);
final SoftLock lock = cacheAccess.lockItem( s, cacheKey, null );
final boolean put = cacheAccess.update( s, cacheKey, id );
boolean put = false;
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
try {
put = cacheAccess.update( s, cacheKey, id );
if ( put && statistics.isStatisticsEnabled() ) {
statistics.naturalIdCachePut(
rootEntityDescriptor.getNavigableRole(),
cacheAccess.getRegion().getName()
);
}
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session(),
cacheAccess,
rootEntityPersister,
put,
true,
JfrEventManager.CacheActionDescription.ENTITY_UPDATE
);
}
s.asEventSource().getActionQueue().registerProcess(
(success, session) -> {
cacheAccess.unlockItem( s, previousCacheKey, removalLock );
if (success) {
final boolean put12 = cacheAccess.afterUpdate(
boolean putAfterUpdate = false;
final CachePutEvent cachePutEventAfterUpdate = JfrEventManager.beginCachePutEvent();
try {
putAfterUpdate = cacheAccess.afterUpdate(
s,
cacheKey,
id,
lock
);
if ( put12 && statistics.isStatisticsEnabled() ) {
if ( putAfterUpdate && statistics.isStatisticsEnabled() ) {
statistics.naturalIdCachePut(
rootEntityDescriptor.getNavigableRole(),
cacheAccess.getRegion().getName()
);
}
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEventAfterUpdate,
session(),
cacheAccess,
rootEntityPersister,
putAfterUpdate,
true,
JfrEventManager.CacheActionDescription.ENTITY_AFTER_UPDATE
);
}
}
else {
cacheAccess.unlockItem( s, cacheKey, lock );
}
@ -567,7 +630,7 @@ public class NaturalIdResolutionsImpl implements NaturalIdResolutions, Serializa
final SharedSessionContractImplementor session = session();
final Object naturalIdCacheKey = naturalIdCacheAccessStrategy.generateCacheKey( naturalId, persister, session );
pk = CacheHelper.fromSharedCache( session, naturalIdCacheKey, naturalIdCacheAccessStrategy );
pk = CacheHelper.fromSharedCache( session, naturalIdCacheKey, persister, true, naturalIdCacheAccessStrategy );
// Found in second-level cache, store in session cache
final SessionFactoryImplementor factory = session.getFactory();

View File

@ -22,6 +22,8 @@ import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.event.jfr.JdbcBatchExecutionEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.resource.jdbc.spi.JdbcObserver;
import static org.hibernate.engine.jdbc.JdbcLogging.JDBC_MESSAGE_LOGGER;
@ -268,11 +270,13 @@ public class BatchImpl implements Batch {
try {
if ( statementDetails.getMutatingTableDetails().isIdentifierTable() ) {
final int[] rowCounts;
final JdbcBatchExecutionEvent jdbcBatchExecutionEvent = JfrEventManager.beginJdbcBatchExecutionEvent();
try {
observer.jdbcExecuteBatchStart();
rowCounts = statement.executeBatch();
}
finally {
JfrEventManager.completeJdbcBatchExecutionEvent( jdbcBatchExecutionEvent, sql );
observer.jdbcExecuteBatchEnd();
}
checkRowCounts( rowCounts, statementDetails );

View File

@ -14,6 +14,8 @@ import org.hibernate.AssertionFailure;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.MutationStatementPreparer;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.event.jfr.JdbcPreparedStatementCreationEvent;
import org.hibernate.resource.jdbc.spi.JdbcObserver;
import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
@ -95,12 +97,14 @@ public class MutationStatementPreparerImpl implements MutationStatementPreparer
final JdbcObserver observer = jdbcCoordinator.getJdbcSessionOwner()
.getJdbcSessionContext()
.getObserver();
final JdbcPreparedStatementCreationEvent jdbcPreparedStatementCreation = JfrEventManager.beginJdbcPreparedStatementCreationEvent();
try {
observer.jdbcPrepareStatementStart();
preparedStatement = doPrepare();
setStatementTimeout( preparedStatement );
}
finally {
JfrEventManager.completeJdbcPreparedStatementCreationEvent( jdbcPreparedStatementCreation, sql );
observer.jdbcPrepareStatementEnd();
}
postProcess( preparedStatement );

View File

@ -18,6 +18,8 @@ import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.ResultSetReturn;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.event.jfr.JdbcPreparedStatementExecutionEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
/**
@ -44,31 +46,6 @@ public class ResultSetReturnImpl implements ResultSetReturn {
this.sqlExceptionHelper = jdbcServices.getSqlExceptionHelper();
}
@Override
public ResultSet extract(PreparedStatement statement) {
// IMPL NOTE : SQL logged by caller
long executeStartNanos = 0;
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStartNanos = System.nanoTime();
}
try {
final ResultSet rs;
try {
jdbcExecuteStatementStart();
rs = statement.executeQuery();
}
finally {
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( statement, executeStartNanos, context() );
}
postExtract( rs, statement );
return rs;
}
catch (SQLException e) {
throw sqlExceptionHelper.convert( e, "could not extract ResultSet" );
}
}
@Override
public ResultSet extract(PreparedStatement statement, String sql) {
// IMPL NOTE : SQL logged by caller
@ -78,11 +55,13 @@ public class ResultSetReturnImpl implements ResultSetReturn {
}
try {
final ResultSet rs;
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try {
jdbcExecuteStatementStart();
rs = statement.executeQuery();
}
finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() );
}
@ -106,31 +85,6 @@ public class ResultSetReturnImpl implements ResultSetReturn {
jdbcCoordinator.getJdbcSessionOwner().getJdbcSessionContext().getObserver().jdbcExecuteStatementStart();
}
@Override
public ResultSet extract(CallableStatement callableStatement) {
// IMPL NOTE : SQL logged by caller
long executeStartNanos = 0;
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStartNanos = System.nanoTime();
}
try {
final ResultSet rs;
try {
jdbcExecuteStatementStart();
rs = dialect.getResultSet( callableStatement );
}
finally {
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( callableStatement, executeStartNanos, context() );
}
postExtract( rs, callableStatement );
return rs;
}
catch (SQLException e) {
throw sqlExceptionHelper.convert( e, "could not extract ResultSet" );
}
}
@Override
public ResultSet extract(Statement statement, String sql) {
sqlStatementLogger.logStatement( sql );
@ -140,11 +94,13 @@ public class ResultSetReturnImpl implements ResultSetReturn {
}
try {
final ResultSet rs;
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try {
jdbcExecuteStatementStart();
rs = statement.executeQuery( sql );
}
finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() );
}
@ -156,36 +112,6 @@ public class ResultSetReturnImpl implements ResultSetReturn {
}
}
@Override
public ResultSet execute(PreparedStatement statement) {
// sql logged by StatementPreparerImpl
long executeStartNanos = 0;
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStartNanos = System.nanoTime();
}
try {
final ResultSet rs;
try {
jdbcExecuteStatementStart();
if ( !statement.execute() ) {
while ( !statement.getMoreResults() && statement.getUpdateCount() != -1 ) {
// do nothing until we hit the resultset
}
}
rs = statement.getResultSet();
}
finally {
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( statement, executeStartNanos, context() );
}
postExtract( rs, statement );
return rs;
}
catch (SQLException e) {
throw sqlExceptionHelper.convert( e, "could not execute statement" );
}
}
@Override
public ResultSet execute(PreparedStatement statement, String sql) {
// sql logged by StatementPreparerImpl
@ -195,6 +121,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
}
try {
final ResultSet rs;
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try {
jdbcExecuteStatementStart();
if ( !statement.execute() ) {
@ -205,6 +132,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
rs = statement.getResultSet();
}
finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() );
}
@ -225,6 +153,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
}
try {
final ResultSet rs;
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try {
jdbcExecuteStatementStart();
if ( !statement.execute( sql ) ) {
@ -235,6 +164,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
rs = statement.getResultSet();
}
finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() );
}
@ -246,27 +176,6 @@ public class ResultSetReturnImpl implements ResultSetReturn {
}
}
@Override
public int executeUpdate(PreparedStatement statement) {
assert statement != null;
long executeStartNanos = 0;
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStartNanos = System.nanoTime();
}
try {
jdbcExecuteStatementStart();
return statement.executeUpdate();
}
catch (SQLException e) {
throw sqlExceptionHelper.convert( e, "could not execute statement" );
}
finally {
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( statement, executeStartNanos, context() );
}
}
@Override
public int executeUpdate(PreparedStatement statement, String sql) {
assert statement != null;
@ -275,6 +184,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStartNanos = System.nanoTime();
}
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try {
jdbcExecuteStatementStart();
return statement.executeUpdate();
@ -283,6 +193,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
throw sqlExceptionHelper.convert( e, "could not execute statement", sql );
}
finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() );
}
@ -295,6 +206,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStartNanos = System.nanoTime();
}
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try {
jdbcExecuteStatementStart();
return statement.executeUpdate( sql );
@ -303,6 +215,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
throw sqlExceptionHelper.convert( e, "could not execute statement", sql );
}
finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() );
}

View File

@ -17,6 +17,8 @@ import org.hibernate.ScrollMode;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.StatementPreparer;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.event.jfr.JdbcPreparedStatementCreationEvent;
import org.hibernate.resource.jdbc.spi.JdbcObserver;
import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
@ -172,12 +174,14 @@ class StatementPreparerImpl implements StatementPreparer {
final PreparedStatement preparedStatement;
final JdbcObserver observer = jdbcCoordinator.getJdbcSessionOwner().getJdbcSessionContext().getObserver();
final JdbcPreparedStatementCreationEvent jdbcPreparedStatementCreation = JfrEventManager.beginJdbcPreparedStatementCreationEvent();
try {
observer.jdbcPrepareStatementStart();
preparedStatement = doPrepare();
setStatementTimeout( preparedStatement );
}
finally {
JfrEventManager.completeJdbcPreparedStatementCreationEvent( jdbcPreparedStatementCreation, sql );
observer.jdbcPrepareStatementEnd();
}
postProcess( preparedStatement );

View File

@ -24,21 +24,6 @@ import java.sql.Statement;
*/
public interface ResultSetReturn {
/**
* Extract the {@link ResultSet} from the {@link PreparedStatement}.
* <p>
* If client passes {@link CallableStatement} reference, this method calls {@link #extract(CallableStatement)}
* internally. Otherwise, {@link PreparedStatement#executeQuery()} is called.
*
* @param statement The {@link PreparedStatement} from which to extract the {@link ResultSet}
*
* @return The extracted ResultSet
*
* @deprecated Use {@link #extract(PreparedStatement, String)} instead
*/
@Deprecated(forRemoval = true)
ResultSet extract(PreparedStatement statement);
/**
* Extract the {@link ResultSet} from the {@link PreparedStatement}.
* <p>
@ -51,20 +36,6 @@ public interface ResultSetReturn {
*/
ResultSet extract(PreparedStatement statement, String sql);
/**
* Extract the {@link ResultSet} from the {@link CallableStatement}. Note that this is the limited legacy
* form which delegates to {@link org.hibernate.dialect.Dialect#getResultSet}. Better option is to integrate
* {@link org.hibernate.procedure.ProcedureCall}-like hooks
*
* @param callableStatement The {@link CallableStatement} from which to extract the {@link ResultSet}
*
* @return The extracted {@link ResultSet}
*
* @deprecated Use {@link #extract(PreparedStatement, String)} instead
*/
@Deprecated(forRemoval = true)
ResultSet extract(CallableStatement callableStatement);
/**
* Performs the given SQL statement, expecting a {@link ResultSet} in return
*
@ -75,19 +46,6 @@ public interface ResultSetReturn {
*/
ResultSet extract(Statement statement, String sql);
/**
* Execute the {@link PreparedStatement} return its first {@link ResultSet}, if any.
* If there is no {@link ResultSet}, returns {@code null}
*
* @param statement The {@link PreparedStatement} to execute
*
* @return The extracted {@link ResultSet}, or {@code null}
*
* @deprecated Use {@link #execute(PreparedStatement, String)} instead
*/
@Deprecated(forRemoval = true)
ResultSet execute(PreparedStatement statement);
/**
* Execute the {@link PreparedStatement} return its first {@link ResultSet}, if any.
* If there is no {@link ResultSet}, returns {@code null}
@ -110,18 +68,6 @@ public interface ResultSetReturn {
*/
ResultSet execute(Statement statement, String sql);
/**
* Execute the {@link PreparedStatement}, returning its "affected row count".
*
* @param statement The {@link PreparedStatement} to execute
*
* @return The {@link PreparedStatement#executeUpdate()} result
*
* @deprecated Use {@link #executeUpdate(PreparedStatement, String)} instead
*/
@Deprecated(forRemoval = true)
int executeUpdate(PreparedStatement statement);
/**
* Execute the {@link PreparedStatement}, returning its "affected row count".
*

View File

@ -311,7 +311,7 @@ public class BatchFetchQueue {
session.getFactory(),
session.getTenantIdentifier()
);
return CacheHelper.fromSharedCache( session, key, cache ) != null;
return CacheHelper.fromSharedCache( session, key, persister, cache ) != null;
}
return false;
}
@ -529,7 +529,7 @@ public class BatchFetchQueue {
session.getFactory(),
session.getTenantIdentifier()
);
return CacheHelper.fromSharedCache( session, cacheKey, cache ) != null;
return CacheHelper.fromSharedCache( session, cacheKey, persister, cache ) != null;
}
return false;
}

View File

@ -11,6 +11,8 @@ import org.hibernate.HibernateException;
import org.hibernate.engine.spi.ActionQueue;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.event.jfr.PartialFlushEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.event.spi.AutoFlushEvent;
import org.hibernate.event.spi.AutoFlushEventListener;
import org.hibernate.event.spi.EventSource;
@ -37,6 +39,7 @@ public class DefaultAutoFlushEventListener extends AbstractFlushingEventListener
public void onAutoFlush(AutoFlushEvent event) throws HibernateException {
final EventSource source = event.getSession();
final SessionEventListenerManager eventListenerManager = source.getEventListenerManager();
final PartialFlushEvent partialFlushEvent = JfrEventManager.beginPartialFlushEvent();
try {
eventListenerManager.partialFlushStart();
@ -52,11 +55,16 @@ public class DefaultAutoFlushEventListener extends AbstractFlushingEventListener
// note: performExecutions() clears all collectionXxxxtion
// collections (the collection actions) in the session
final org.hibernate.event.jfr.FlushEvent jfrFlushEvent = JfrEventManager.beginFlushEvent();
try {
performExecutions( source );
postFlush( source );
postPostFlush( source );
}
finally {
JfrEventManager.completeFlushEvent( jfrFlushEvent, event, true );
}
final StatisticsImplementor statistics = source.getFactory().getStatistics();
if ( statistics.isStatisticsEnabled() ) {
statistics.flush();
@ -70,6 +78,7 @@ public class DefaultAutoFlushEventListener extends AbstractFlushingEventListener
}
}
finally {
JfrEventManager.completePartialFlushEvent( partialFlushEvent, event );
eventListenerManager.partialFlushEnd(
event.getNumberOfEntitiesProcessed(),
event.getNumberOfEntitiesProcessed()

View File

@ -24,6 +24,8 @@ import org.hibernate.engine.spi.SelfDirtinessTracker;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.event.jfr.DirtyCalculationEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.FlushEntityEvent;
import org.hibernate.event.spi.FlushEntityEventListener;
@ -482,11 +484,12 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
final SessionImplementor session = event.getSession();
boolean dirtyCheckPossible;
int[] dirtyProperties = null;
final DirtyCalculationEvent dirtyCalculationEvent = JfrEventManager.beginDirtyCalculationEvent();
final EntityEntry entry = event.getEntityEntry();
final EntityPersister persister = entry.getPersister();
try {
session.getEventListenerManager().dirtyCalculationStart();
// object loaded by update()
final EntityEntry entry = event.getEntityEntry();
final EntityPersister persister = entry.getPersister();
final Object[] values = event.getPropertyValues();
final Object[] loadedState = entry.getLoadedState();
final Object entity = event.getEntity();
@ -532,6 +535,7 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
event.setDirtyCheckPossible( dirtyCheckPossible );
}
finally {
JfrEventManager.completeDirtyCalculationEvent( dirtyCalculationEvent, session, persister, entry, dirtyProperties );
session.getEventListenerManager().dirtyCalculationEnd( dirtyProperties != null );
}
return dirtyProperties;

View File

@ -8,6 +8,7 @@ package org.hibernate.event.internal;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.FlushEvent;
import org.hibernate.event.spi.FlushEventListener;
@ -28,10 +29,9 @@ public class DefaultFlushEventListener extends AbstractFlushingEventListener imp
public void onFlush(FlushEvent event) throws HibernateException {
final EventSource source = event.getSession();
final PersistenceContext persistenceContext = source.getPersistenceContextInternal();
if ( persistenceContext.getNumberOfManagedEntities() > 0
|| persistenceContext.getCollectionEntriesSize() > 0 ) {
final org.hibernate.event.jfr.FlushEvent jfrFlushEvent = JfrEventManager.beginFlushEvent();
try {
source.getEventListenerManager().flushStart();
@ -40,6 +40,7 @@ public class DefaultFlushEventListener extends AbstractFlushingEventListener imp
postFlush( source );
}
finally {
JfrEventManager.completeFlushEvent( jfrFlushEvent, event );
source.getEventListenerManager().flushEnd(
event.getNumberOfEntitiesProcessed(),
event.getNumberOfCollectionsProcessed()

View File

@ -127,7 +127,7 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
final SessionFactoryImplementor factory = source.getFactory();
final CollectionDataAccess cacheAccessStrategy = persister.getCacheAccessStrategy();
final Object ck = cacheAccessStrategy.generateCacheKey( id, persister, factory, source.getTenantIdentifier() );
final Object ce = CacheHelper.fromSharedCache( source, ck, cacheAccessStrategy );
final Object ce = CacheHelper.fromSharedCache( source, ck, persister, cacheAccessStrategy );
final StatisticsImplementor statistics = factory.getStatistics();
if ( statistics.isStatisticsEnabled() ) {

View File

@ -0,0 +1,55 @@
/*
* 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.event.jfr;
import org.hibernate.internal.build.AllowNonPortable;
import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.StackTrace;
@Name( CacheGetEvent.NAME )
@Label( "Cache Get Executed" )
@Category( "Hibernate ORM" )
@Description( "Cache Get Executed" )
@StackTrace(false)
@AllowNonPortable
public class CacheGetEvent extends Event {
public static final String NAME = "org.hibernate.orm.CacheGet";
@Label( "Session Identifier" )
public String sessionIdentifier;
@Label( "Entity Name" )
public String entityName;
@Label( "Collection Name" )
public String collectionName;
@Label( "Used Natural Id" )
public boolean isNaturalId;
@Label( "Region Name" )
public String regionName;
@Label( "Cache Get Execution Time" )
public long executionTime;
@Label("Cache Hit")
public boolean hit;
@Override
public String toString() {
return NAME ;
}
public transient long startedAt;
}

View File

@ -0,0 +1,58 @@
/*
* 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.event.jfr;
import org.hibernate.internal.build.AllowNonPortable;
import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.StackTrace;
@Name( CachePutEvent.NAME )
@Label( "Cache Put Executed" )
@Category( "Hibernate ORM" )
@Description( "Cache Put Executed" )
@StackTrace(false)
@AllowNonPortable
public class CachePutEvent extends Event {
public static final String NAME = "org.hibernate.orm.CachePut";
@Label( "Session Identifier" )
public String sessionIdentifier;
@Label( "Region Name" )
public String regionName;
@Label( "Entity Name" )
public String entityName;
@Label( "Collection Name" )
public String collectionName;
@Label( "Used Natural Id" )
public boolean isNaturalId;
@Label( "Cache Put Execution Time" )
public long executionTime;
@Label( "Description" )
public String description;
@Label( "Cache Content Has Changed" )
public boolean cacheChanged;
@Override
public String toString() {
return NAME ;
}
public transient long startedAt;
}

View File

@ -0,0 +1,48 @@
/*
* 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.event.jfr;
import org.hibernate.internal.build.AllowNonPortable;
import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.StackTrace;
@Name( DirtyCalculationEvent.NAME )
@Label( "DirtyCalculationEvent Execution" )
@Category( "Hibernate ORM" )
@Description( "DirtyCalculationEvent Execution" )
@StackTrace(false)
@AllowNonPortable
public class DirtyCalculationEvent extends Event {
public static final String NAME = "org.hibernate.orm.DirtyCalculationEvent";
@Label( "Session Identifier" )
public String sessionIdentifier;
@Label( "PartialFlushEvent time" )
public long executionTime;
@Label( "Entity Name" )
public String entityName;
@Label( "Entity Status" )
public String entityStatus;
@Label( "Found properties" )
public boolean dirty;
@Override
public String toString() {
return NAME ;
}
public transient long startedAt;
}

View File

@ -0,0 +1,49 @@
/*
* 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.event.jfr;
import org.hibernate.internal.build.AllowNonPortable;
import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.StackTrace;
@Name( FlushEvent.NAME )
@Label( "Flush Execution" )
@Category( "Hibernate ORM" )
@Description( "Flush Execution" )
@StackTrace(false)
@AllowNonPortable
public class FlushEvent extends Event {
public static final String NAME = "org.hibernate.orm.FlushEvent";
@Label( "Session Identifier" )
public String sessionIdentifier;
@Label( "Number Of Processed Entities" )
public int numberOfEntitiesProcessed;
@Label( "Number Of Processed Collectionc" )
public int numberOfCollectionsProcessed;
@Label( "Flush time" )
public long executionTime;
@Label( "Auto Flush" )
public boolean isAutoFlush;
@Override
public String toString() {
return NAME ;
}
public transient long startedAt;
}

View File

@ -0,0 +1,41 @@
/*
* 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.event.jfr;
import org.hibernate.internal.build.AllowNonPortable;
import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.StackTrace;
@Name( JdbcBatchExecutionEvent.NAME )
@Label( "JDBC Batch Execution" )
@Category( "Hibernate ORM" )
@Description( "JDBC Batch Execution" )
@StackTrace(false)
@AllowNonPortable
public class JdbcBatchExecutionEvent extends Event {
public static final String NAME = "org.hibernate.orm.JdbcBatchExecution";
@Label("PreparedStatement SQL")
public String sql;
@Label( "Batch Execution time" )
public long executionTime;
@Override
public String toString() {
return NAME ;
}
public transient long startedAt;
}

View File

@ -0,0 +1,42 @@
/*
* 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.event.jfr;
import org.hibernate.internal.build.AllowNonPortable;
import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.StackTrace;
@Name(JdbcConnectionAcquisitionEvent.NAME )
@Label( "JDBC Connection Obtained" )
@Category( "Hibernate ORM" )
@Description( "JDBC Connection Obtained" )
@StackTrace(false)
@AllowNonPortable
public class JdbcConnectionAcquisitionEvent extends Event {
public static final String NAME = "org.hibernate.orm.JdbcConnectionAcquisition";
@Label("Session Identifier" )
public String sessionIdentifier;
@Label( "Tenant Identifier" )
public String tenantIdentifier;
@Label( "Connection Acquisition Time" )
public long executionTime;
@Override
public String toString() {
return NAME ;
}
public transient long startedAt;
}

View File

@ -0,0 +1,43 @@
/*
* 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.event.jfr;
import org.hibernate.internal.build.AllowNonPortable;
import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.StackTrace;
@Name(JdbcConnectionReleaseEvent.NAME )
@Label( "JDBC Connection Release" )
@Category( "Hibernate ORM" )
@Description( "JDBC Connection Released" )
@StackTrace(false)
@AllowNonPortable
public class JdbcConnectionReleaseEvent extends Event {
public static final String NAME = "org.hibernate.orm.JdbcConnectionRelease";
@Label("Session Identifier" )
public String sessionIdentifier;
@Label( "Tenant Identifier" )
public String tenantIdentifier;
@Label( "Connection Release Time" )
public long executionTime;
@Override
public String toString() {
return NAME ;
}
public transient long startedAt;
}

View File

@ -0,0 +1,40 @@
/*
* 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.event.jfr;
import org.hibernate.internal.build.AllowNonPortable;
import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.StackTrace;
@Name(JdbcPreparedStatementCreationEvent.NAME)
@Label("JDBC PreparedStatement Created")
@Category("Hibernate ORM")
@Description("JDBC PreparedStatement Created")
@StackTrace(false)
@AllowNonPortable
public class JdbcPreparedStatementCreationEvent extends Event {
public static final String NAME = "org.hibernate.orm.JdbcPreparedStatementCreation";
@Label("PreparedStatement SQL")
public String sql;
@Label("PreparedStatement Creation Time")
public long executionTime;
@Override
public String toString() {
return NAME;
}
public transient long startedAt;
}

View File

@ -0,0 +1,40 @@
/*
* 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.event.jfr;
import org.hibernate.internal.build.AllowNonPortable;
import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.StackTrace;
@Name(JdbcPreparedStatementExecutionEvent.NAME )
@Label( "JDBC PreparedStatement Executed" )
@Category( "Hibernate ORM" )
@Description( "JDBC PreparedStatement Executed" )
@StackTrace(false)
@AllowNonPortable
public class JdbcPreparedStatementExecutionEvent extends Event {
public static final String NAME = "org.hibernate.orm.JdbcPreparedStatementExecution";
@Label( "PreparedStatement SQL" )
public String sql;
@Label( "PreparedStatement Execution Time" )
public long executionTime;
@Override
public String toString() {
return NAME ;
}
public transient long startedAt;
}

View File

@ -0,0 +1,49 @@
/*
* 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.event.jfr;
import org.hibernate.internal.build.AllowNonPortable;
import jdk.jfr.Category;
import jdk.jfr.Description;
import jdk.jfr.Event;
import jdk.jfr.Label;
import jdk.jfr.Name;
import jdk.jfr.StackTrace;
@Name( PartialFlushEvent.NAME )
@Label( "PartialFlushEvent Execution" )
@Category( "Hibernate ORM" )
@Description( "PartialFlushEvent Execution" )
@StackTrace(false)
@AllowNonPortable
public class PartialFlushEvent extends Event {
public static final String NAME = "org.hibernate.orm.PartialFlushEvent";
@Label( "Session Identifier" )
public String sessionIdentifier;
@Label( "Number Of Processed Entities" )
public int numberOfEntitiesProcessed;
@Label( "Number Of Processed Collectionc" )
public int numberOfCollectionsProcessed;
@Label( "PartialFlushEvent time" )
public long executionTime;
@Label( "Auto Flush" )
public boolean isAutoFlush;
@Override
public String toString() {
return NAME ;
}
public transient long startedAt;
}

View File

@ -25,7 +25,7 @@ import jdk.jfr.StackTrace;
@StackTrace(false)
@AllowNonPortable
public class SessionOpenEvent extends Event {
public static final String NAME = "org.hibernate.orm.SessionOpened";
public static final String NAME = "org.hibernate.orm.SessionOpen";
@Label("Session Identifier" )
public String sessionIdentifier;

View File

@ -0,0 +1,479 @@
/*
* 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.event.jfr.internal;
import java.sql.PreparedStatement;
import org.hibernate.cache.spi.Region;
import org.hibernate.cache.spi.access.CachedDomainDataAccess;
import org.hibernate.engine.spi.EntityEntry;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.jfr.CacheGetEvent;
import org.hibernate.event.jfr.CachePutEvent;
import org.hibernate.event.jfr.DirtyCalculationEvent;
import org.hibernate.event.jfr.FlushEvent;
import org.hibernate.event.jfr.JdbcBatchExecutionEvent;
import org.hibernate.event.jfr.JdbcConnectionAcquisitionEvent;
import org.hibernate.event.jfr.JdbcConnectionReleaseEvent;
import org.hibernate.event.jfr.JdbcPreparedStatementCreationEvent;
import org.hibernate.event.jfr.JdbcPreparedStatementExecutionEvent;
import org.hibernate.event.jfr.PartialFlushEvent;
import org.hibernate.event.jfr.SessionClosedEvent;
import org.hibernate.event.jfr.SessionOpenEvent;
import org.hibernate.event.spi.AutoFlushEvent;
import org.hibernate.event.spi.EventSource;
import org.hibernate.internal.build.AllowNonPortable;
import org.hibernate.persister.collection.CollectionPersister;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.stat.internal.StatsHelper;
import static java.util.concurrent.TimeUnit.NANOSECONDS;
@AllowNonPortable
public class JfrEventManager {
public static SessionOpenEvent beginSessionOpenEvent() {
final SessionOpenEvent sessionOpenEvent = new SessionOpenEvent();
if ( sessionOpenEvent.isEnabled() ) {
sessionOpenEvent.begin();
}
return sessionOpenEvent;
}
public static void completeSessionOpenEvent(
SessionOpenEvent sessionOpenEvent,
SharedSessionContractImplementor session) {
if ( sessionOpenEvent.isEnabled() ) {
sessionOpenEvent.end();
if ( sessionOpenEvent.shouldCommit() ) {
sessionOpenEvent.sessionIdentifier = getSessionIdentifier( session );
sessionOpenEvent.commit();
}
}
}
public static SessionClosedEvent beginSessionClosedEvent() {
final SessionClosedEvent sessionClosedEvent = new SessionClosedEvent();
if ( sessionClosedEvent.isEnabled() ) {
sessionClosedEvent.begin();
}
return sessionClosedEvent;
}
public static void completeSessionClosedEvent(
SessionClosedEvent sessionClosedEvent,
SharedSessionContractImplementor session) {
if ( sessionClosedEvent.isEnabled() ) {
sessionClosedEvent.end();
if ( sessionClosedEvent.shouldCommit() ) {
sessionClosedEvent.sessionIdentifier = getSessionIdentifier( session );
sessionClosedEvent.commit();
}
}
}
public static JdbcConnectionAcquisitionEvent beginJdbcConnectionAcquisitionEvent() {
final JdbcConnectionAcquisitionEvent jdbcConnectionAcquisitionEvent = new JdbcConnectionAcquisitionEvent();
if ( jdbcConnectionAcquisitionEvent.isEnabled() ) {
jdbcConnectionAcquisitionEvent.begin();
jdbcConnectionAcquisitionEvent.startedAt = System.nanoTime();
}
return jdbcConnectionAcquisitionEvent;
}
public static void completeJdbcConnectionAcquisitionEvent(
JdbcConnectionAcquisitionEvent jdbcConnectionAcquisitionEvent,
SharedSessionContractImplementor session,
String tenantId) {
if ( jdbcConnectionAcquisitionEvent.isEnabled() ) {
jdbcConnectionAcquisitionEvent.end();
if ( jdbcConnectionAcquisitionEvent.shouldCommit() ) {
jdbcConnectionAcquisitionEvent.executionTime = getExecutionTime( jdbcConnectionAcquisitionEvent.startedAt );
jdbcConnectionAcquisitionEvent.sessionIdentifier = getSessionIdentifier( session );
jdbcConnectionAcquisitionEvent.tenantIdentifier = tenantId;
jdbcConnectionAcquisitionEvent.commit();
}
}
}
public static JdbcConnectionReleaseEvent beginJdbcConnectionReleaseEvent() {
final JdbcConnectionReleaseEvent jdbcConnectionReleaseEvent = new JdbcConnectionReleaseEvent();
if ( jdbcConnectionReleaseEvent.isEnabled() ) {
jdbcConnectionReleaseEvent.begin();
jdbcConnectionReleaseEvent.startedAt = System.nanoTime();
}
return jdbcConnectionReleaseEvent;
}
public static void completeJdbcConnectionReleaseEvent(
JdbcConnectionReleaseEvent jdbcConnectionReleaseEvent,
SharedSessionContractImplementor session,
String tenantId) {
if ( jdbcConnectionReleaseEvent.isEnabled() ) {
jdbcConnectionReleaseEvent.end();
if ( jdbcConnectionReleaseEvent.shouldCommit() ) {
jdbcConnectionReleaseEvent.executionTime = getExecutionTime( jdbcConnectionReleaseEvent.startedAt );
jdbcConnectionReleaseEvent.sessionIdentifier = getSessionIdentifier( session );
jdbcConnectionReleaseEvent.tenantIdentifier = tenantId;
jdbcConnectionReleaseEvent.commit();
}
}
}
public static JdbcPreparedStatementCreationEvent beginJdbcPreparedStatementCreationEvent() {
final JdbcPreparedStatementCreationEvent jdbcPreparedStatementCreation = new JdbcPreparedStatementCreationEvent();
if ( jdbcPreparedStatementCreation.isEnabled() ) {
jdbcPreparedStatementCreation.begin();
jdbcPreparedStatementCreation.startedAt = System.nanoTime();
}
return jdbcPreparedStatementCreation;
}
public static void completeJdbcPreparedStatementCreationEvent(
JdbcPreparedStatementCreationEvent jdbcPreparedStatementCreation,
String preparedStatementSql) {
if ( jdbcPreparedStatementCreation.isEnabled() ) {
jdbcPreparedStatementCreation.end();
if ( jdbcPreparedStatementCreation.shouldCommit() ) {
jdbcPreparedStatementCreation.executionTime = getExecutionTime( jdbcPreparedStatementCreation.startedAt );
jdbcPreparedStatementCreation.sql = preparedStatementSql;
jdbcPreparedStatementCreation.commit();
}
}
}
public static JdbcPreparedStatementExecutionEvent beginJdbcPreparedStatementExecutionEvent() {
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = new JdbcPreparedStatementExecutionEvent();
if ( jdbcPreparedStatementExecutionEvent.isEnabled() ) {
jdbcPreparedStatementExecutionEvent.begin();
jdbcPreparedStatementExecutionEvent.startedAt = System.nanoTime();
}
return jdbcPreparedStatementExecutionEvent;
}
public static void completeJdbcPreparedStatementExecutionEvent(
JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent,
String preparedStatementSql) {
if ( jdbcPreparedStatementExecutionEvent.isEnabled() ) {
jdbcPreparedStatementExecutionEvent.end();
if ( jdbcPreparedStatementExecutionEvent.shouldCommit() ) {
jdbcPreparedStatementExecutionEvent.executionTime = getExecutionTime(
jdbcPreparedStatementExecutionEvent.startedAt );
jdbcPreparedStatementExecutionEvent.sql = preparedStatementSql;
jdbcPreparedStatementExecutionEvent.commit();
}
}
}
public static JdbcBatchExecutionEvent beginJdbcBatchExecutionEvent() {
final JdbcBatchExecutionEvent jdbcBatchExecutionEvent = new JdbcBatchExecutionEvent();
if ( jdbcBatchExecutionEvent.isEnabled() ) {
jdbcBatchExecutionEvent.begin();
jdbcBatchExecutionEvent.startedAt = System.nanoTime();
}
return jdbcBatchExecutionEvent;
}
public static void completeJdbcBatchExecutionEvent(
JdbcBatchExecutionEvent jdbcBatchExecutionEvent,
String statementSql) {
if ( jdbcBatchExecutionEvent.isEnabled() ) {
jdbcBatchExecutionEvent.end();
if ( jdbcBatchExecutionEvent.shouldCommit() ) {
jdbcBatchExecutionEvent.executionTime = getExecutionTime( jdbcBatchExecutionEvent.startedAt );
jdbcBatchExecutionEvent.sql = statementSql;
jdbcBatchExecutionEvent.commit();
}
}
}
public static CachePutEvent beginCachePutEvent() {
final CachePutEvent cachePutEvent = new CachePutEvent();
if ( cachePutEvent.isEnabled() ) {
cachePutEvent.begin();
cachePutEvent.startedAt = System.nanoTime();
}
return cachePutEvent;
}
public static void completeCachePutEvent(
CachePutEvent cachePutEvent,
SharedSessionContractImplementor session,
Region region,
boolean cacheContentChanged,
CacheActionDescription description) {
if ( cachePutEvent.isEnabled() ) {
cachePutEvent.end();
if ( cachePutEvent.shouldCommit() ) {
cachePutEvent.executionTime = getExecutionTime( cachePutEvent.startedAt );
cachePutEvent.sessionIdentifier = getSessionIdentifier( session );
cachePutEvent.regionName = region.getName();
cachePutEvent.description = description.getText();
cachePutEvent.cacheChanged = cacheContentChanged;
cachePutEvent.commit();
}
}
}
public static void completeCachePutEvent(
CachePutEvent cachePutEvent,
SharedSessionContractImplementor session,
CachedDomainDataAccess cachedDomainDataAccess,
EntityPersister persister,
boolean cacheContentChanged,
CacheActionDescription description) {
completeCachePutEvent(
cachePutEvent,
session,
cachedDomainDataAccess,
persister,
cacheContentChanged,
false,
description
);
}
public static void completeCachePutEvent(
CachePutEvent cachePutEvent,
SharedSessionContractImplementor session,
CachedDomainDataAccess cachedDomainDataAccess,
EntityPersister persister,
boolean cacheContentChanged,
boolean isNatualId,
CacheActionDescription description) {
if ( cachePutEvent.isEnabled() ) {
cachePutEvent.end();
if ( cachePutEvent.shouldCommit() ) {
cachePutEvent.executionTime = getExecutionTime( cachePutEvent.startedAt );
cachePutEvent.sessionIdentifier = getSessionIdentifier( session );
cachePutEvent.regionName = cachedDomainDataAccess.getRegion().getName();
cachePutEvent.entityName = getEntityName( persister );
cachePutEvent.description = description.getText();
cachePutEvent.isNaturalId = isNatualId;
cachePutEvent.cacheChanged = cacheContentChanged;
cachePutEvent.commit();
}
}
}
public static void completeCachePutEvent(
CachePutEvent cachePutEvent,
SharedSessionContractImplementor session,
CachedDomainDataAccess cachedDomainDataAccess,
CollectionPersister persister,
boolean cacheContentChanged,
CacheActionDescription description) {
if ( cachePutEvent.isEnabled() ) {
cachePutEvent.end();
if ( cachePutEvent.shouldCommit() ) {
cachePutEvent.executionTime = getExecutionTime( cachePutEvent.startedAt );
cachePutEvent.sessionIdentifier = getSessionIdentifier( session );
cachePutEvent.regionName = cachedDomainDataAccess.getRegion().getName();
cachePutEvent.collectionName = persister.getNavigableRole().getFullPath();
cachePutEvent.description = description.getText();
cachePutEvent.cacheChanged = cacheContentChanged;
cachePutEvent.commit();
}
}
}
public static CacheGetEvent beginCacheGetEvent() {
final CacheGetEvent cacheGetEvent = new CacheGetEvent();
if ( cacheGetEvent.isEnabled() ) {
cacheGetEvent.begin();
cacheGetEvent.startedAt = System.nanoTime();
}
return cacheGetEvent;
}
public static void completeCacheGetEvent(
CacheGetEvent cacheGetEvent,
SharedSessionContractImplementor session,
Region region,
boolean hit) {
if ( cacheGetEvent.isEnabled() ) {
cacheGetEvent.end();
if ( cacheGetEvent.shouldCommit() ) {
cacheGetEvent.executionTime = getExecutionTime( cacheGetEvent.startedAt );
cacheGetEvent.sessionIdentifier = getSessionIdentifier( session );
cacheGetEvent.regionName = region.getName();
cacheGetEvent.hit = hit;
cacheGetEvent.commit();
}
}
}
public static void completeCacheGetEvent(
CacheGetEvent cacheGetEvent,
SharedSessionContractImplementor session,
Region region,
EntityPersister persister,
boolean isNaturalKey,
boolean hit) {
if ( cacheGetEvent.isEnabled() ) {
cacheGetEvent.end();
if ( cacheGetEvent.shouldCommit() ) {
cacheGetEvent.executionTime = getExecutionTime( cacheGetEvent.startedAt );
cacheGetEvent.sessionIdentifier = getSessionIdentifier( session );
cacheGetEvent.entityName = getEntityName( persister );
cacheGetEvent.regionName = region.getName();
cacheGetEvent.isNaturalId = isNaturalKey;
cacheGetEvent.hit = hit;
cacheGetEvent.commit();
}
}
}
public static void completeCacheGetEvent(
CacheGetEvent cacheGetEvent,
SharedSessionContractImplementor session,
Region region,
CollectionPersister persister,
boolean hit) {
if ( cacheGetEvent.isEnabled() ) {
cacheGetEvent.end();
if ( cacheGetEvent.shouldCommit() ) {
cacheGetEvent.executionTime = getExecutionTime( cacheGetEvent.startedAt );
cacheGetEvent.sessionIdentifier = getSessionIdentifier( session );
cacheGetEvent.collectionName = persister.getNavigableRole().getFullPath();
cacheGetEvent.regionName = region.getName();
cacheGetEvent.hit = hit;
cacheGetEvent.commit();
}
}
}
public static FlushEvent beginFlushEvent() {
final FlushEvent flushEvent = new FlushEvent();
if ( flushEvent.isEnabled() ) {
flushEvent.begin();
flushEvent.startedAt = System.nanoTime();
}
return flushEvent;
}
public static void completeFlushEvent(
FlushEvent flushEvent,
org.hibernate.event.spi.FlushEvent event) {
completeFlushEvent( flushEvent, event, false );
}
public static void completeFlushEvent(
FlushEvent flushEvent,
org.hibernate.event.spi.FlushEvent event,
boolean autoFlush) {
if ( flushEvent.isEnabled() ) {
flushEvent.end();
if ( flushEvent.shouldCommit() ) {
flushEvent.executionTime = getExecutionTime( flushEvent.startedAt );
EventSource session = event.getSession();
flushEvent.sessionIdentifier = getSessionIdentifier( session );
flushEvent.numberOfEntitiesProcessed = event.getNumberOfEntitiesProcessed();
flushEvent.numberOfCollectionsProcessed = event.getNumberOfCollectionsProcessed();
flushEvent.isAutoFlush = autoFlush;
flushEvent.commit();
}
}
}
public static PartialFlushEvent beginPartialFlushEvent() {
final PartialFlushEvent partialFlushEvent = new PartialFlushEvent();
if ( partialFlushEvent.isEnabled() ) {
partialFlushEvent.startedAt = System.nanoTime();
partialFlushEvent.begin();
}
return partialFlushEvent;
}
public static void completePartialFlushEvent(
PartialFlushEvent flushEvent,
AutoFlushEvent event) {
if ( flushEvent.isEnabled() ) {
flushEvent.end();
if ( flushEvent.shouldCommit() ) {
flushEvent.executionTime = getExecutionTime( flushEvent.startedAt );
EventSource session = event.getSession();
flushEvent.sessionIdentifier = getSessionIdentifier( session );
flushEvent.numberOfEntitiesProcessed = event.getNumberOfEntitiesProcessed();
flushEvent.numberOfCollectionsProcessed = event.getNumberOfCollectionsProcessed();
flushEvent.isAutoFlush = true;
flushEvent.commit();
}
}
}
public static DirtyCalculationEvent beginDirtyCalculationEvent() {
final DirtyCalculationEvent dirtyCalculationEvent = new DirtyCalculationEvent();
if ( dirtyCalculationEvent.isEnabled() ) {
dirtyCalculationEvent.startedAt = System.nanoTime();
dirtyCalculationEvent.begin();
}
return dirtyCalculationEvent;
}
public static void completeDirtyCalculationEvent(
DirtyCalculationEvent dirtyCalculationEvent,
SharedSessionContractImplementor session,
EntityPersister persister,
EntityEntry entry,
int[] dirtyProperties) {
if ( dirtyCalculationEvent.isEnabled() ) {
dirtyCalculationEvent.end();
if ( dirtyCalculationEvent.shouldCommit() ) {
dirtyCalculationEvent.executionTime = getExecutionTime( dirtyCalculationEvent.startedAt );
dirtyCalculationEvent.sessionIdentifier = getSessionIdentifier( session );
dirtyCalculationEvent.entityName = getEntityName( persister );
dirtyCalculationEvent.entityStatus = entry.getStatus().name();
dirtyCalculationEvent.dirty = dirtyProperties != null;
dirtyCalculationEvent.commit();
}
}
}
public enum CacheActionDescription {
ENTITY_INSERT( "Entity Insert" ),
ENTITY_AFTER_INSERT( "Entity After Insert" ),
ENTITY_UPDATE( "Entity Update" ),
ENTITY_LOAD( "Entity Load" ),
ENTITY_AFTER_UPDATE( "Entity After Update" ),
TIMESTAMP_PRE_INVALIDATE( "Timestamp Pre Invalidate" ),
TIMESTAMP_INVALIDATE( "Timestamp Invalidate" ),
COLLECTION_INSERT( "Collection Insert" ),
QUERY_RESULT( "Query Result" );
private final String text;
CacheActionDescription(String text) {
this.text = text;
}
@Override
public String toString() {
return text;
}
public String getText() {
return text;
}
}
private static long getExecutionTime(Long startTime) {
return NANOSECONDS.convert( System.nanoTime() - startTime, NANOSECONDS );
}
private static String getSessionIdentifier(SharedSessionContractImplementor session) {
if ( session == null ) {
return null;
}
return session.getSessionIdentifier().toString();
}
private static String getEntityName(EntityPersister persister) {
return StatsHelper.INSTANCE.getRootEntityRole( persister ).getFullPath();
}
}

View File

@ -34,6 +34,9 @@ import org.hibernate.engine.jdbc.internal.FormatStyle;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.jfr.JdbcPreparedStatementExecutionEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.event.jfr.JdbcPreparedStatementCreationEvent;
import org.hibernate.id.ExportableColumn;
import org.hibernate.id.IdentifierGeneratorHelper;
import org.hibernate.id.IntegralDataTypeHolder;
@ -593,7 +596,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
try ( PreparedStatement selectPS = prepareStatement( connection, selectQuery, logger, listener ) ) {
selectPS.setString( 1, segmentValue );
final ResultSet selectRS = executeQuery( selectPS, listener );
final ResultSet selectRS = executeQuery( selectPS, listener, selectQuery );
if ( !selectRS.next() ) {
long initializationValue;
if ( storeLastUsedValue ) {
@ -608,7 +611,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
LOG.tracef( "binding parameter [%s] - [%s]", 1, segmentValue );
statement.setString( 1, segmentValue );
value.bind( statement, 2 );
executeUpdate( statement, listener);
executeUpdate( statement, listener, insertQuery);
}
}
else {
@ -640,7 +643,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
updateValue.bind( statement, 1 );
value.bind( statement, 2 );
statement.setString( 3, segmentValue );
rows = executeUpdate( statement, listener );
rows = executeUpdate( statement, listener, updateQuery );
}
catch (SQLException e) {
LOG.unableToUpdateQueryHiValue( physicalTableName.render(), e );
@ -664,32 +667,37 @@ public class TableGenerator implements PersistentIdentifierGenerator {
SqlStatementLogger logger,
SessionEventListenerManager listener) throws SQLException {
logger.logStatement( sql, FormatStyle.BASIC.getFormatter() );
final JdbcPreparedStatementCreationEvent jdbcPreparedStatementCreation = JfrEventManager.beginJdbcPreparedStatementCreationEvent();
try {
listener.jdbcPrepareStatementStart();
return connection.prepareStatement( sql );
}
finally {
JfrEventManager.completeJdbcPreparedStatementCreationEvent( jdbcPreparedStatementCreation, sql );
listener.jdbcPrepareStatementEnd();
}
}
private int executeUpdate(PreparedStatement ps, SessionEventListenerManager listener) throws SQLException {
private int executeUpdate(PreparedStatement ps, SessionEventListenerManager listener, String sql ) throws SQLException {
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try {
listener.jdbcExecuteStatementStart();
return ps.executeUpdate();
}
finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
listener.jdbcExecuteStatementEnd();
}
}
private ResultSet executeQuery(PreparedStatement ps, SessionEventListenerManager listener) throws SQLException {
private ResultSet executeQuery(PreparedStatement ps, SessionEventListenerManager listener, String sql ) throws SQLException {
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try {
listener.jdbcExecuteStatementStart();
return ps.executeQuery();
}
finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
listener.jdbcExecuteStatementEnd();
}
}

View File

@ -26,6 +26,9 @@ import org.hibernate.engine.jdbc.internal.FormatStyle;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.jfr.JdbcPreparedStatementExecutionEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.event.jfr.JdbcPreparedStatementCreationEvent;
import org.hibernate.id.ExportableColumn;
import org.hibernate.id.IdentifierGenerationException;
import org.hibernate.id.IdentifierGeneratorHelper;
@ -143,7 +146,7 @@ public class TableStructure implements DatabaseStructure {
statementLogger,
statsCollector
)) {
final ResultSet selectRS = executeQuery( selectStatement, statsCollector );
final ResultSet selectRS = executeQuery( selectStatement, statsCollector, selectQuery );
if ( !selectRS.next() ) {
final String err = "could not read a hi value - you need to populate the table: " + physicalTableName;
LOG.error( err );
@ -168,7 +171,7 @@ public class TableStructure implements DatabaseStructure {
final IntegralDataTypeHolder updateValue = value.copy().add( increment );
updateValue.bind( updatePS, 1 );
value.bind( updatePS, 2 );
rows = executeUpdate( updatePS, statsCollector );
rows = executeUpdate( updatePS, statsCollector, updateQuery );
}
catch (SQLException e) {
LOG.unableToUpdateQueryHiValue( physicalTableName.render(), e );
@ -198,32 +201,38 @@ public class TableStructure implements DatabaseStructure {
SqlStatementLogger statementLogger,
SessionEventListenerManager statsCollector) throws SQLException {
statementLogger.logStatement( sql, FormatStyle.BASIC.getFormatter() );
final JdbcPreparedStatementCreationEvent jdbcPreparedStatementCreation = JfrEventManager.beginJdbcPreparedStatementCreationEvent();
try {
statsCollector.jdbcPrepareStatementStart();
return connection.prepareStatement( sql );
}
finally {
JfrEventManager.completeJdbcPreparedStatementCreationEvent( jdbcPreparedStatementCreation, sql );
statsCollector.jdbcPrepareStatementEnd();
}
}
private int executeUpdate(PreparedStatement ps, SessionEventListenerManager statsCollector) throws SQLException {
private int executeUpdate(PreparedStatement ps, SessionEventListenerManager statsCollector, String sql ) throws SQLException {
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try {
statsCollector.jdbcExecuteStatementStart();
return ps.executeUpdate();
}
finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
statsCollector.jdbcExecuteStatementEnd();
}
}
private ResultSet executeQuery(PreparedStatement ps, SessionEventListenerManager statsCollector) throws SQLException {
private ResultSet executeQuery(PreparedStatement ps, SessionEventListenerManager statsCollector, String sql ) throws SQLException {
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try {
statsCollector.jdbcExecuteStatementStart();
return ps.executeQuery();
}
finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
statsCollector.jdbcExecuteStatementEnd();
}
}

View File

@ -602,14 +602,16 @@ public abstract class AbstractSharedSessionContract implements SharedSessionCont
if ( ! fastSessionServices.requiresMultiTenantConnectionProvider ) {
jdbcConnectionAccess = new NonContextualJdbcConnectionAccess(
getEventListenerManager(),
fastSessionServices.connectionProvider
fastSessionServices.connectionProvider,
this
);
}
else {
jdbcConnectionAccess = new ContextualJdbcConnectionAccess(
getTenantIdentifier(),
getEventListenerManager(),
fastSessionServices.multiTenantConnectionProvider
fastSessionServices.multiTenantConnectionProvider,
this
);
}
}

View File

@ -14,6 +14,10 @@ import org.hibernate.HibernateException;
import org.hibernate.SessionEventListener;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.connections.spi.MultiTenantConnectionProvider;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.event.jfr.JdbcConnectionAcquisitionEvent;
import org.hibernate.event.jfr.JdbcConnectionReleaseEvent;
/**
* @author Steve Ebersole
@ -22,14 +26,18 @@ public class ContextualJdbcConnectionAccess implements JdbcConnectionAccess, Ser
private final String tenantIdentifier;
private final SessionEventListener listener;
private final MultiTenantConnectionProvider connectionProvider;
private final SharedSessionContractImplementor session;
public ContextualJdbcConnectionAccess(
String tenantIdentifier,
SessionEventListener listener,
MultiTenantConnectionProvider connectionProvider) {
MultiTenantConnectionProvider connectionProvider,
SharedSessionContractImplementor session) {
this.tenantIdentifier = tenantIdentifier;
this.listener = listener;
this.connectionProvider = connectionProvider;
this.session = session;
}
@Override
@ -38,11 +46,17 @@ public class ContextualJdbcConnectionAccess implements JdbcConnectionAccess, Ser
throw new HibernateException( "Tenant identifier required" );
}
final JdbcConnectionAcquisitionEvent jdbcConnectionAcquisitionEvent = JfrEventManager.beginJdbcConnectionAcquisitionEvent();
try {
listener.jdbcConnectionAcquisitionStart();
return connectionProvider.getConnection( tenantIdentifier );
}
finally {
JfrEventManager.completeJdbcConnectionAcquisitionEvent(
jdbcConnectionAcquisitionEvent,
session,
tenantIdentifier
);
listener.jdbcConnectionAcquisitionEnd();
}
}
@ -53,11 +67,13 @@ public class ContextualJdbcConnectionAccess implements JdbcConnectionAccess, Ser
throw new HibernateException( "Tenant identifier required" );
}
final JdbcConnectionReleaseEvent jdbcConnectionReleaseEvent = JfrEventManager.beginJdbcConnectionReleaseEvent();
try {
listener.jdbcConnectionReleaseStart();
connectionProvider.releaseConnection( tenantIdentifier, connection );
}
finally {
JfrEventManager.completeJdbcConnectionReleaseEvent( jdbcConnectionReleaseEvent, session, tenantIdentifier );
listener.jdbcConnectionReleaseEnd();
}
}

View File

@ -14,6 +14,10 @@ import java.util.Objects;
import org.hibernate.SessionEventListener;
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.event.jfr.JdbcConnectionAcquisitionEvent;
import org.hibernate.event.jfr.JdbcConnectionReleaseEvent;
/**
* @author Steve Ebersole
@ -21,34 +25,45 @@ import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
public class NonContextualJdbcConnectionAccess implements JdbcConnectionAccess, Serializable {
private final SessionEventListener listener;
private final ConnectionProvider connectionProvider;
private final SharedSessionContractImplementor session;
public NonContextualJdbcConnectionAccess(
SessionEventListener listener,
ConnectionProvider connectionProvider) {
ConnectionProvider connectionProvider,
SharedSessionContractImplementor session) {
Objects.requireNonNull( listener );
Objects.requireNonNull( connectionProvider );
this.listener = listener;
this.connectionProvider = connectionProvider;
this.session = session;
}
@Override
public Connection obtainConnection() throws SQLException {
final JdbcConnectionAcquisitionEvent jdbcConnectionAcquisitionEvent = JfrEventManager.beginJdbcConnectionAcquisitionEvent();
try {
listener.jdbcConnectionAcquisitionStart();
return connectionProvider.getConnection();
}
finally {
JfrEventManager.completeJdbcConnectionAcquisitionEvent(
jdbcConnectionAcquisitionEvent,
session,
null
);
listener.jdbcConnectionAcquisitionEnd();
}
}
@Override
public void releaseConnection(Connection connection) throws SQLException {
final JdbcConnectionReleaseEvent jdbcConnectionReleaseEvent = JfrEventManager.beginJdbcConnectionReleaseEvent();
try {
listener.jdbcConnectionReleaseStart();
connectionProvider.closeConnection( connection );
}
finally {
JfrEventManager.completeJdbcConnectionReleaseEvent( jdbcConnectionReleaseEvent, session, null );
listener.jdbcConnectionReleaseEnd();
}
}

View File

@ -18,7 +18,6 @@ import java.sql.Connection;
import java.sql.NClob;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@ -69,6 +68,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.engine.transaction.spi.TransactionImplementor;
import org.hibernate.engine.transaction.spi.TransactionObserver;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.event.jfr.SessionClosedEvent;
import org.hibernate.event.jfr.SessionOpenEvent;
import org.hibernate.event.spi.AutoFlushEvent;
@ -108,9 +108,7 @@ import org.hibernate.event.spi.ResolveNaturalIdEventListener;
import org.hibernate.event.spi.SaveOrUpdateEvent;
import org.hibernate.event.spi.SaveOrUpdateEventListener;
import org.hibernate.graph.GraphSemantic;
import org.hibernate.graph.internal.RootGraphImpl;
import org.hibernate.graph.spi.RootGraphImplementor;
import org.hibernate.internal.build.AllowNonPortable;
import org.hibernate.internal.util.ExceptionHelper;
import org.hibernate.jpa.internal.LegacySpecHelper;
import org.hibernate.jpa.internal.util.ConfigurationHelper;
@ -141,7 +139,6 @@ import org.hibernate.type.descriptor.WrapperOptions;
import jakarta.persistence.CacheRetrieveMode;
import jakarta.persistence.CacheStoreMode;
import jakarta.persistence.EntityGraph;
import jakarta.persistence.EntityManager;
import jakarta.persistence.EntityNotFoundException;
import jakarta.persistence.FlushModeType;
@ -228,14 +225,10 @@ public class SessionImpl
// TODO: this is unused and can be removed
private transient boolean isEnforcingFetchGraph;
@AllowNonPortable
public SessionImpl(SessionFactoryImpl factory, SessionCreationOptions options) {
super( factory, options );
final SessionOpenEvent sessionOpenEvent = new SessionOpenEvent();
if ( sessionOpenEvent.isEnabled() ) {
sessionOpenEvent.begin();
}
final SessionOpenEvent sessionOpenEvent = JfrEventManager.beginSessionOpenEvent();
persistenceContext = createPersistenceContext();
actionQueue = createActionQueue();
@ -282,13 +275,7 @@ public class SessionImpl
log.tracef( "Opened Session [%s] at timestamp: %s", getSessionIdentifier(), currentTimeMillis() );
}
if ( sessionOpenEvent.isEnabled() ) {
sessionOpenEvent.end();
if ( sessionOpenEvent.shouldCommit() ) {
sessionOpenEvent.sessionIdentifier = getSessionIdentifier().toString();
sessionOpenEvent.commit();
}
}
JfrEventManager.completeSessionOpenEvent( sessionOpenEvent, this );
}
private FlushMode getInitialFlushMode() {
@ -425,16 +412,12 @@ public class SessionImpl
closeWithoutOpenChecks();
}
@AllowNonPortable
public void closeWithoutOpenChecks() throws HibernateException {
if ( log.isTraceEnabled() ) {
log.tracef( "Closing session [%s]", getSessionIdentifier() );
}
final SessionClosedEvent sessionClosedEvent = new SessionClosedEvent();
if ( sessionClosedEvent.isEnabled() ) {
sessionClosedEvent.begin();
}
final SessionClosedEvent sessionClosedEvent = JfrEventManager.beginSessionClosedEvent();
// todo : we want this check if usage is JPA, but not native Hibernate usage
final SessionFactoryImplementor sessionFactory = getSessionFactory();
@ -459,13 +442,7 @@ public class SessionImpl
statistics.closeSession();
}
if ( sessionClosedEvent.isEnabled() ) {
sessionClosedEvent.end();
if ( sessionClosedEvent.shouldCommit() ) {
sessionClosedEvent.sessionIdentifier = getSessionIdentifier().toString();
sessionClosedEvent.commit();
}
}
JfrEventManager.completeSessionClosedEvent( sessionClosedEvent, this );
}
private boolean isTransactionInProgressAndNotMarkedForRollback() {

View File

@ -273,7 +273,7 @@ public class CacheEntityLoaderHelper {
source.getTenantIdentifier()
);
final Object ce = CacheHelper.fromSharedCache( source, ck, persister.getCacheAccessStrategy() );
final Object ce = CacheHelper.fromSharedCache( source, ck, persister, persister.getCacheAccessStrategy() );
final StatisticsImplementor statistics = factory.getStatistics();
if ( statistics.isStatisticsEnabled() ) {
if ( ce == null ) {

View File

@ -1537,7 +1537,7 @@ public abstract class AbstractEntityPersister
if ( session.getCacheMode().isGetEnabled() && canReadFromCache() && isLazyPropertiesCacheable() ) {
final EntityDataAccess cacheAccess = getCacheAccessStrategy();
final Object cacheKey = cacheAccess.generateCacheKey(id, this, session.getFactory(), session.getTenantIdentifier() );
final Object ce = CacheHelper.fromSharedCache( session, cacheKey, cacheAccess );
final Object ce = CacheHelper.fromSharedCache( session, cacheKey, this, cacheAccess );
if ( ce != null ) {
final CacheEntry cacheEntry = (CacheEntry) getCacheEntryStructure().destructure( ce, factory );
final Object initializedValue = initializeLazyPropertiesFromCache( fieldName, entity, session, entry, cacheEntry );
@ -4148,7 +4148,7 @@ public abstract class AbstractEntityPersister
final EntityDataAccess cache = getCacheAccessStrategy();
final String tenantId = session.getTenantIdentifier();
final Object ck = cache.generateCacheKey( id, this, session.getFactory(), tenantId );
final Object ce = CacheHelper.fromSharedCache( session, ck, getCacheAccessStrategy() );
final Object ce = CacheHelper.fromSharedCache( session, ck, this, getCacheAccessStrategy() );
if ( ce != null ) {
return false;
}

View File

@ -13,6 +13,8 @@ import java.util.function.Function;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.jfr.JdbcPreparedStatementExecutionEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.query.spi.QueryOptions;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
import org.hibernate.sql.exec.spi.ExecutionContext;
@ -79,12 +81,14 @@ public class StandardJdbcMutationExecutor implements JdbcMutationExecutor {
}
session.getEventListenerManager().jdbcExecuteStatementStart();
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try {
int rows = preparedStatement.executeUpdate();
expectationCheck.accept( rows, preparedStatement );
return rows;
}
finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, finalSql );
session.getEventListenerManager().jdbcExecuteStatementEnd();
}
}

View File

@ -28,6 +28,8 @@ import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.Status;
import org.hibernate.event.jfr.CachePutEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.event.spi.PreLoadEvent;
import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.internal.util.StringHelper;
@ -977,7 +979,10 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
//
// we need to be careful not to clobber the lock here in the cache so that it can be rolled back if need be
if ( persistenceContext.wasInsertedDuringTransaction( concreteDescriptor, entityIdentifier) ) {
cacheAccess.update(
boolean update = false;
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
try {
update = cacheAccess.update(
session,
cacheKey,
concreteDescriptor.getCacheEntryStructure().structure( cacheEntry ),
@ -985,11 +990,24 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
version
);
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cacheAccess,
concreteDescriptor,
update,
JfrEventManager.CacheActionDescription.ENTITY_UPDATE
);
}
}
else {
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
boolean put = false;
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
try {
eventListenerManager.cachePutStart();
final boolean put = cacheAccess.putFromLoad(
put = cacheAccess.putFromLoad(
session,
cacheKey,
concreteDescriptor.getCacheEntryStructure().structure( cacheEntry ),
@ -997,13 +1015,20 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
//useMinimalPuts( session, entityEntry )
false
);
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cacheAccess,
concreteDescriptor,
put,
JfrEventManager.CacheActionDescription.ENTITY_LOAD
);
final StatisticsImplementor statistics = factory.getStatistics();
if ( put && statistics.isStatisticsEnabled() ) {
statistics.entityCachePut( rootEntityDescriptor.getNavigableRole(), cacheAccess.getRegion().getName() );
}
}
finally {
eventListenerManager.cachePutEnd();
}
}

View File

@ -22,6 +22,8 @@ import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.event.jfr.CachePutEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.metamodel.mapping.ModelPart;
@ -286,9 +288,11 @@ public class ResultsHelper {
// CollectionRegionAccessStrategy has no update, so avoid putting uncommitted data via putFromLoad
if ( isPutFromLoad ) {
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
boolean put = false;
try {
eventListenerManager.cachePutStart();
final boolean put = cacheAccess.putFromLoad(
put = cacheAccess.putFromLoad(
session,
cacheKey,
collectionDescriptor.getCacheEntryStructure().structure( entry ),
@ -296,6 +300,17 @@ public class ResultsHelper {
factory.getSessionFactoryOptions().isMinimalPutsEnabled()
&& session.getCacheMode()!= CacheMode.REFRESH
);
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cacheAccess,
collectionDescriptor,
put,
JfrEventManager.CacheActionDescription.COLLECTION_INSERT
);
eventListenerManager.cachePutEnd();
final StatisticsImplementor statistics = factory.getStatistics();
if ( put && statistics.isStatisticsEnabled() ) {
@ -304,9 +319,7 @@ public class ResultsHelper {
collectionDescriptor.getCacheAccessStrategy().getRegion().getName()
);
}
}
finally {
eventListenerManager.cachePutEnd();
}
}
}

View File

@ -20,6 +20,8 @@ import org.hibernate.dialect.pagination.NoopLimitHandler;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger;
import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.event.jfr.JdbcPreparedStatementExecutionEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.query.spi.Limit;
@ -235,11 +237,13 @@ public class DeferredResultSetAccess extends AbstractResultSetAccess {
if ( sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStartNanos = System.nanoTime();
}
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try {
eventListenerManager.jdbcExecuteStatementStart();
resultSet = wrapResultSet( preparedStatement.executeQuery() );
}
finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, finalSql );
eventListenerManager.jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( finalSql, executeStartNanos, context() );
}

View File

@ -124,11 +124,12 @@ public class AggressiveReleaseTest extends BaseSessionFactoryFunctionalTest {
JdbcCoordinatorImpl jdbcCoord = (JdbcCoordinatorImpl) session.getJdbcCoordinator();
ResourceRegistry resourceRegistry = jdbcCoord.getLogicalConnection().getResourceRegistry();
try {
String sql = "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )";
PreparedStatement ps = jdbcCoord.getStatementPreparer().prepareStatement(
"insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )" );
sql );
ps.setLong( 1, 1 );
ps.setString( 2, "name" );
jdbcCoord.getResultSetReturn().execute( ps );
jdbcCoord.getResultSetReturn().execute( ps, sql );
assertTrue( jdbcCoord.getLogicalConnection().getResourceRegistry().hasRegisteredResources() );
assertEquals( 1, connectionProvider.getAcquiredConnections().size() );
assertEquals( 0, connectionProvider.getReleasedConnections().size() );
@ -161,11 +162,12 @@ public class AggressiveReleaseTest extends BaseSessionFactoryFunctionalTest {
ResourceRegistry resourceRegistry = jdbcCoord.getLogicalConnection().getResourceRegistry();
try {
String sql = "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )";
PreparedStatement ps = jdbcCoord.getStatementPreparer().prepareStatement(
"insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )" );
sql );
ps.setLong( 1, 1 );
ps.setString( 2, "name" );
jdbcCoord.getResultSetReturn().execute( ps );
jdbcCoord.getResultSetReturn().execute( ps , sql);
assertTrue( resourceRegistry.hasRegisteredResources() );
assertEquals( 1, connectionProvider.getAcquiredConnections().size() );
assertEquals( 0, connectionProvider.getReleasedConnections().size() );
@ -177,7 +179,7 @@ public class AggressiveReleaseTest extends BaseSessionFactoryFunctionalTest {
assertEquals( 1, connectionProvider.getReleasedConnections().size() );
// open a result set and hold it open...
final String sql = "select * from SANDBOX_JDBC_TST";
sql = "select * from SANDBOX_JDBC_TST";
ps = jdbcCoord.getStatementPreparer().prepareStatement( sql );
jdbcCoord.getResultSetReturn().extract( ps, sql );
assertTrue( resourceRegistry.hasRegisteredResources() );
@ -225,11 +227,12 @@ public class AggressiveReleaseTest extends BaseSessionFactoryFunctionalTest {
ResourceRegistry resourceRegistry = jdbcCoord.getLogicalConnection().getResourceRegistry();
try {
String sql = "insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )";
PreparedStatement ps = jdbcCoord.getStatementPreparer().prepareStatement(
"insert into SANDBOX_JDBC_TST( ID, NAME ) values ( ?, ? )" );
sql );
ps.setLong( 1, 1 );
ps.setString( 2, "name" );
jdbcCoord.getResultSetReturn().execute( ps );
jdbcCoord.getResultSetReturn().execute( ps , sql);
assertTrue( resourceRegistry.hasRegisteredResources() );
assertEquals( 1, connectionProvider.getAcquiredConnections().size() );
assertEquals( 0, connectionProvider.getReleasedConnections().size() );
@ -243,7 +246,7 @@ public class AggressiveReleaseTest extends BaseSessionFactoryFunctionalTest {
jdbcCoord.disableReleases();
// open a result set...
final String sql = "select * from SANDBOX_JDBC_TST";
sql = "select * from SANDBOX_JDBC_TST";
ps = jdbcCoord.getStatementPreparer().prepareStatement( sql );
jdbcCoord.getResultSetReturn().extract( ps, sql );
assertTrue( resourceRegistry.hasRegisteredResources() );

View File

@ -38,9 +38,10 @@ public class BasicConnectionTest extends BaseCoreFunctionalTestCase {
SessionImplementor sessionImpl = (SessionImplementor) session;
boolean caught = false;
try {
String sql = "select count(*) from NON_EXISTENT";
PreparedStatement ps = sessionImpl.getJdbcCoordinator().getStatementPreparer()
.prepareStatement( "select count(*) from NON_EXISTENT" );
sessionImpl.getJdbcCoordinator().getResultSetReturn().execute( ps );
.prepareStatement( sql );
sessionImpl.getJdbcCoordinator().getResultSetReturn().execute( ps, sql );
}
catch ( JDBCException ok ) {
caught = true;

View File

@ -116,7 +116,7 @@ public class CursorFromCallableTest extends BaseCoreFunctionalTestCase {
PreparedStatement preparedStatement = null;
try {
preparedStatement = statementPreparer.prepareStatement( sql );
resultSetReturn.execute( preparedStatement );
resultSetReturn.execute( preparedStatement, sql );
}
finally {
if ( preparedStatement != null ) {

View File

@ -0,0 +1,96 @@
package org.hibernate.orm.test.event.jfr;
import java.util.List;
import org.hibernate.engine.spi.Status;
import org.hibernate.event.jfr.DirtyCalculationEvent;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jdk.jfr.consumer.RecordedEvent;
import org.moditect.jfrunit.EnableEvent;
import org.moditect.jfrunit.JfrEventTest;
import org.moditect.jfrunit.JfrEvents;
import static org.assertj.core.api.Assertions.assertThat;
@JfrEventTest
@DomainModel(annotatedClasses = {
DirtyCalculationEventTests.TestEntity.class,
})
@SessionFactory
public class DirtyCalculationEventTests {
public JfrEvents jfrEvents = new JfrEvents();
@BeforeAll
public void setUp(SessionFactoryScope scope){
scope.inTransaction(
session ->{
TestEntity entity = new TestEntity( 1, "name_1" );
session.persist( entity );
}
);
}
@Test
@EnableEvent(DirtyCalculationEvent.NAME)
public void testFlushEvent(SessionFactoryScope scope) {
jfrEvents.reset();
String sessionId = scope.fromTransaction(
session -> {
TestEntity testEntity = session.load( TestEntity.class, 1 );
testEntity.setName( "new name" );
return session.getSessionIdentifier().toString();
}
);
List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( DirtyCalculationEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 1 );
RecordedEvent event = events.get( 0 );
assertThat( event.getEventType().getName() )
.isEqualTo( DirtyCalculationEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( sessionId );
assertThat( event.getString( "entityName" ) )
.isEqualTo( TestEntity.class.getName() );
assertThat( event.getString( "entityStatus" ) )
.isEqualTo( Status.MANAGED.name() );
assertThat( event.getBoolean( "dirty" ) )
.isTrue();
}
@Entity(name = "TestEntity")
public static class TestEntity {
@Id
private Integer id;
private String name;
public TestEntity() {
}
public TestEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
public void setName(String name) {
this.name = name;
}
}
}

View File

@ -0,0 +1,112 @@
package org.hibernate.orm.test.event.jfr;
import java.util.List;
import java.util.Locale;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.event.jfr.JdbcBatchExecutionEvent;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jdk.jfr.consumer.RecordedEvent;
import org.moditect.jfrunit.EnableEvent;
import org.moditect.jfrunit.JfrEventTest;
import org.moditect.jfrunit.JfrEvents;
import static org.assertj.core.api.Assertions.assertThat;
@JfrEventTest
@DomainModel(annotatedClasses = {
JdbcBatchExecutionEventTests.TestEntity.class
})
@SessionFactory
@ServiceRegistry(
settings = @Setting(name = AvailableSettings.STATEMENT_BATCH_SIZE, value = "5")
)
public class JdbcBatchExecutionEventTests {
public JfrEvents jfrEvents = new JfrEvents();
@Test
@EnableEvent(JdbcBatchExecutionEvent.NAME)
public void testJdbcBatchExecutionEvent(SessionFactoryScope scope) {
jfrEvents.reset();
scope.inTransaction(
session -> {
for ( int i = 2; i < 10; i++ ) {
TestEntity entity = new TestEntity( i, "name_" + i );
session.persist( entity );
}
session.flush();
final List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( JdbcBatchExecutionEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 2 );
RecordedEvent jdbcBatchExecutionEvent = events.get( 0 );
assertThat( jdbcBatchExecutionEvent.getEventType().getName() )
.isEqualTo( JdbcBatchExecutionEvent.NAME );
assertThat( jdbcBatchExecutionEvent.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( jdbcBatchExecutionEvent.getString( "sql" ).toLowerCase( Locale.ROOT ) )
.contains( "insert into " );
jdbcBatchExecutionEvent = events.get( 1 );
assertThat( jdbcBatchExecutionEvent.getEventType().getName() )
.isEqualTo( JdbcBatchExecutionEvent.NAME );
assertThat( jdbcBatchExecutionEvent.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( jdbcBatchExecutionEvent.getString( "sql" ).toLowerCase( Locale.ROOT ) )
.contains( "insert into " );
}
);
}
@Test
@EnableEvent(JdbcBatchExecutionEvent.NAME)
public void testJdbcBatchExecutionEventNoFired(SessionFactoryScope scope) {
jfrEvents.reset();
scope.inTransaction(
session -> {
}
);
final List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( JdbcBatchExecutionEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 0 );
}
@Entity(name = "TestEntity")
public static class TestEntity {
@Id
private Integer id;
private String name;
public TestEntity() {
}
public TestEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
}
}

View File

@ -0,0 +1,108 @@
package org.hibernate.orm.test.event.jfr;
import java.util.List;
import org.hibernate.event.jfr.JdbcConnectionAcquisitionEvent;
import org.hibernate.event.jfr.JdbcConnectionReleaseEvent;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test;
import jdk.jfr.consumer.RecordedEvent;
import org.moditect.jfrunit.EnableEvent;
import org.moditect.jfrunit.JfrEventTest;
import org.moditect.jfrunit.JfrEvents;
import static org.assertj.core.api.Assertions.assertThat;
@JfrEventTest
@DomainModel
@SessionFactory
public class JdbcConnectionEventTests {
public JfrEvents jfrEvents = new JfrEvents();
@Test
@EnableEvent(JdbcConnectionAcquisitionEvent.NAME)
@EnableEvent(JdbcConnectionReleaseEvent.NAME)
public void testJdbcConnectionAcquisition(SessionFactoryScope scope) {
// starting a transaction should trigger the acquisition of the connection
String expectedSessionId = scope.fromTransaction(
session -> {
final List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( JdbcConnectionAcquisitionEvent.NAME )
|| eventName.equals( JdbcConnectionReleaseEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 1 );
RecordedEvent event = events.get( 0 );
assertThat( event.getEventType().getName() )
.isEqualTo( JdbcConnectionAcquisitionEvent.NAME );
String sessionId = session.getSessionIdentifier().toString();
assertThat( event.getString( "sessionIdentifier" ) ).isEqualTo( sessionId );
jfrEvents.reset();
return sessionId;
}
);
final List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( JdbcConnectionAcquisitionEvent.NAME )
|| eventName.equals( JdbcConnectionReleaseEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 1 );
RecordedEvent event = events.get( 0 );
assertThat( event.getEventType().getName() ).isEqualTo( JdbcConnectionReleaseEvent.NAME );
/*
Disabled the following check, not sure why but the retrieved `sessionIdentifier` is null,
checked with Flight Recorder and the value is correctly set to the session id value
*/
// assertThat( event.getString( "sessionIdentifier" ) ).isEqualTo( expectedSessionId );
}
@Test
@EnableEvent(JdbcConnectionAcquisitionEvent.NAME)
@EnableEvent(JdbcConnectionReleaseEvent.NAME)
public void testJdbcConnectionAcquisitionNoFired(SessionFactoryScope scope) {
jfrEvents.reset();
// starting a session should not trigger the acquisition/release of the connection
scope.inSession(
session -> {
final List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( JdbcConnectionAcquisitionEvent.NAME )
|| eventName.equals( JdbcConnectionReleaseEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 0 );
jfrEvents.reset();
}
);
final List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( JdbcConnectionAcquisitionEvent.NAME )
|| eventName.equals( JdbcConnectionReleaseEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 0 );
}
}

View File

@ -0,0 +1,95 @@
package org.hibernate.orm.test.event.jfr;
import java.util.List;
import java.util.Locale;
import org.hibernate.event.jfr.JdbcPreparedStatementCreationEvent;
import org.hibernate.event.jfr.JdbcPreparedStatementExecutionEvent;
import org.hibernate.testing.orm.junit.DomainModel;
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 jdk.jfr.consumer.RecordedEvent;
import org.moditect.jfrunit.EnableEvent;
import org.moditect.jfrunit.JfrEventTest;
import org.moditect.jfrunit.JfrEvents;
import static org.assertj.core.api.Assertions.assertThat;
@JfrEventTest
@DomainModel(annotatedClasses = JdbcPreparedStatementEventTests.TestEntity.class)
@SessionFactory
public class JdbcPreparedStatementEventTests {
public JfrEvents jfrEvents = new JfrEvents();
@Test
@EnableEvent(JdbcPreparedStatementCreationEvent.NAME)
@EnableEvent(JdbcPreparedStatementExecutionEvent.NAME)
public void testJdbcPreparedStatementEvent(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
session.createQuery( "select t from TestEntity t" ).list();
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( "select " );
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" ) );
}
);
}
@Test
@EnableEvent(JdbcPreparedStatementCreationEvent.NAME)
@EnableEvent(JdbcPreparedStatementExecutionEvent.NAME)
public void testJdbcPreparedStatementEventNoFired(SessionFactoryScope scope) {
jfrEvents.reset();
scope.inTransaction(
session -> {
}
);
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( 0 );
}
@Entity(name = "TestEntity")
public static class TestEntity {
@Id
private Long id;
private String name;
}
}

View File

@ -0,0 +1,125 @@
package org.hibernate.orm.test.event.jfr.cache;
import java.util.List;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.event.jfr.CacheGetEvent;
import org.hibernate.event.jfr.JdbcBatchExecutionEvent;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Cacheable;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jdk.jfr.consumer.RecordedEvent;
import org.moditect.jfrunit.EnableEvent;
import org.moditect.jfrunit.JfrEventTest;
import org.moditect.jfrunit.JfrEvents;
import static org.assertj.core.api.Assertions.assertThat;
@JfrEventTest
@DomainModel(annotatedClasses = {
CacheGetEventTests.TestEntity.class,
})
@SessionFactory
@ServiceRegistry(
settings = {
@Setting(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true"),
}
)
public class CacheGetEventTests {
public JfrEvents jfrEvents = new JfrEvents();
@BeforeAll
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
TestEntity entity = new TestEntity( 1, "name_1" );
session.persist( entity );
}
);
}
@Test
@EnableEvent(JdbcBatchExecutionEvent.NAME)
public void testCacheGetEvent(SessionFactoryScope scope) {
jfrEvents.reset();
scope.inTransaction(
session -> {
TestEntity testEntity = session.find( TestEntity.class, 1 );
List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( CacheGetEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 1 );
RecordedEvent event = events.get( 0 );
assertThat( event.getEventType().getName() )
.isEqualTo( CacheGetEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( session.getSessionIdentifier().toString() );
assertThat( event.getString( "entityName" ) )
.isEqualTo( TestEntity.class.getName() );
assertThat( event.getBoolean( "isNaturalId" ) ).isFalse();
assertThat( event.getBoolean( "hit" ) ).isTrue();
assertThat( event.getString( "regionName" ) ).isNotNull();
}
);
}
@Test
@EnableEvent(JdbcBatchExecutionEvent.NAME)
public void testCacheGetEventNoFired(SessionFactoryScope scope) {
jfrEvents.reset();
scope.inTransaction(
session -> {
}
);
List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( CacheGetEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 0 );
}
@Entity(name = "TestEntity")
@Cacheable
public static class TestEntity {
@Id
private Integer id;
private String name;
public TestEntity() {
}
public TestEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
public void setName(String name) {
this.name = name;
}
}
}

View File

@ -0,0 +1,168 @@
package org.hibernate.orm.test.event.jfr.cache;
import java.util.List;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.event.jfr.CachePutEvent;
import org.hibernate.event.jfr.JdbcBatchExecutionEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.orm.test.cache.CacheRegionStatisticsTest;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Cacheable;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jdk.jfr.consumer.RecordedEvent;
import org.moditect.jfrunit.EnableEvent;
import org.moditect.jfrunit.JfrEventTest;
import org.moditect.jfrunit.JfrEvents;
import static org.assertj.core.api.Assertions.assertThat;
@JfrEventTest
@DomainModel(annotatedClasses = {
EntityInsertCachePutEventTests.TestEntity.class,
EntityInsertCachePutEventTests.AnotherTestEntity.class,
})
@SessionFactory
@ServiceRegistry(
settings =
{
@Setting(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true"),
}
)
public class EntityInsertCachePutEventTests {
public JfrEvents jfrEvents = new JfrEvents();
@Test
@EnableEvent(JdbcBatchExecutionEvent.NAME)
public void testCachePutEvent(SessionFactoryScope scope) {
jfrEvents.reset();
scope.inTransaction(
session -> {
TestEntity entity = new TestEntity( 1, "name_1" );
session.persist( entity );
session.flush();
List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( CachePutEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 1 );
RecordedEvent event = events.get( 0 );
assertThat( event.getEventType().getName() )
.isEqualTo( CachePutEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( session.getSessionIdentifier().toString() );
assertThat( event.getString( "entityName" ) ).isEqualTo( TestEntity.class.getName() );
// cache strategy is READ_WRITE so no cache insert happened
assertThat( event.getBoolean( "cacheChanged" ) ).isFalse();
assertThat( event.getString( "regionName" ) ).isNotNull();
assertThat( event.getString( "description" ) ).isEqualTo( JfrEventManager.CacheActionDescription.ENTITY_INSERT.getText() );
jfrEvents.reset();
AnotherTestEntity anotherTestEntity = new AnotherTestEntity( 1, "name_1" );
session.persist( anotherTestEntity );
session.flush();
events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( CachePutEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 1 );
event = events.get( 0 );
assertThat( event.getEventType().getName() )
.isEqualTo( CachePutEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( session.getSessionIdentifier().toString() );
assertThat( event.getString( "entityName" ) ).isEqualTo( AnotherTestEntity.class.getName() );
// cache strategy is TRANSACTIONAL so cache insert should happen
assertThat( event.getBoolean( "cacheChanged" ) ).isTrue();
assertThat( event.getString( "regionName" ) ).isNotNull();
assertThat( event.getBoolean( "isNaturalId" ) ).isFalse();
assertThat( event.getString( "description" ) ).isEqualTo( JfrEventManager.CacheActionDescription.ENTITY_INSERT.getText() );
}
);
}
@Test
@EnableEvent(JdbcBatchExecutionEvent.NAME)
public void testJdbcBatchExecutionEventNoFired(SessionFactoryScope scope) {
jfrEvents.reset();
scope.inTransaction(
session -> {
session.createQuery(
"from TestEntity",
CacheRegionStatisticsTest.Dog.class
).setCacheable( false ).getResultList();
}
);
final List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( CachePutEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 0 );
}
@Entity(name = "TestEntity")
@Cacheable
public static class TestEntity {
@Id
private Integer id;
private String name;
public TestEntity() {
}
public TestEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
}
@Entity(name = "AnotherTestEntity")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
public static class AnotherTestEntity {
@Id
private Integer id;
private String name;
public AnotherTestEntity() {
}
public AnotherTestEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
}
}

View File

@ -0,0 +1,167 @@
package org.hibernate.orm.test.event.jfr.cache;
import java.util.List;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.event.jfr.CachePutEvent;
import org.hibernate.event.jfr.JdbcBatchExecutionEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Cacheable;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jdk.jfr.consumer.RecordedEvent;
import org.moditect.jfrunit.EnableEvent;
import org.moditect.jfrunit.JfrEventTest;
import org.moditect.jfrunit.JfrEvents;
import static org.assertj.core.api.Assertions.assertThat;
@JfrEventTest
@DomainModel(annotatedClasses = {
EntityUpdateCachePutEventTests.TestEntity.class,
EntityUpdateCachePutEventTests.AnotherTestEntity.class,
})
@SessionFactory
@ServiceRegistry(
settings = {
@Setting(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true"),
}
)
public class EntityUpdateCachePutEventTests {
public JfrEvents jfrEvents = new JfrEvents();
@BeforeAll
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
TestEntity entity = new TestEntity( 1, "name_1" );
session.persist( entity );
AnotherTestEntity anotherTestEntity = new AnotherTestEntity( 1, "name_1" );
session.persist( anotherTestEntity );
}
);
}
@Test
@EnableEvent(JdbcBatchExecutionEvent.NAME)
public void testCachePutEvent(SessionFactoryScope scope) {
jfrEvents.reset();
scope.inTransaction(
session -> {
TestEntity testEntity = session.find( TestEntity.class, 1 );
testEntity.setName( "Another name" );
session.flush();
List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( CachePutEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 1 );
RecordedEvent event = events.get( 0 );
assertThat( event.getEventType().getName() )
.isEqualTo( CachePutEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( session.getSessionIdentifier().toString() );
assertThat( event.getString( "entityName" ) ).isEqualTo( TestEntity.class.getName() );
// cache strategy is READ_WRITE so no cache insert happened
assertThat( event.getBoolean( "cacheChanged" ) ).isFalse();
assertThat( event.getBoolean( "isNaturalId" ) ).isFalse();
assertThat( event.getString( "regionName" ) ).isNotNull();
assertThat( event.getString( "description" ) ).isEqualTo( JfrEventManager.CacheActionDescription.ENTITY_UPDATE.getText() );
jfrEvents.reset();
AnotherTestEntity anotherTestEntity = session.find( AnotherTestEntity.class, 1 );
anotherTestEntity.setName( "Another name" );
session.flush();
events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( CachePutEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 1 );
event = events.get( 0 );
assertThat( event.getEventType().getName() )
.isEqualTo( CachePutEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( session.getSessionIdentifier().toString() );
assertThat( event.getString( "entityName" ) ).isEqualTo( AnotherTestEntity.class.getName() );
// cache strategy is TRANSACTIONAL so cache insert should happen
assertThat( event.getBoolean( "cacheChanged" ) ).isTrue();
assertThat( event.getString( "regionName" ) ).isNotNull();
assertThat( event.getBoolean( "isNaturalId" ) ).isFalse();
assertThat( event.getString( "description" ) ).isEqualTo( JfrEventManager.CacheActionDescription.ENTITY_UPDATE.getText() );
}
);
}
@Entity(name = "TestEntity")
@Cacheable
public static class TestEntity {
@Id
private Integer id;
private String name;
public TestEntity() {
}
public TestEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
public void setName(String name) {
this.name = name;
}
}
@Entity(name = "AnotherTestEntity")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
public static class AnotherTestEntity {
@Id
private Integer id;
private String name;
public AnotherTestEntity() {
}
public AnotherTestEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
public void setName(String name) {
this.name = name;
}
}
}

View File

@ -0,0 +1,128 @@
package org.hibernate.orm.test.event.jfr.cache;
import java.util.List;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.NaturalIdCache;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.event.jfr.CacheGetEvent;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Cacheable;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jdk.jfr.consumer.RecordedEvent;
import org.moditect.jfrunit.EnableEvent;
import org.moditect.jfrunit.JfrEventTest;
import org.moditect.jfrunit.JfrEvents;
import static org.assertj.core.api.Assertions.assertThat;
@JfrEventTest
@DomainModel(annotatedClasses = {
NaturalIdGetCacheTests.TestEntity.class
})
@SessionFactory
@ServiceRegistry(
settings = {
@Setting(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true"),
}
)
public class NaturalIdGetCacheTests {
public JfrEvents jfrEvents = new JfrEvents();
@Test
@EnableEvent(CacheGetEvent.NAME)
public void testCacheGetEvent(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
TestEntity testEntity = new TestEntity( 2, 4, 5 );
session.persist( testEntity );
}
);
scope.inTransaction(
session -> {
jfrEvents.reset();
TestEntity load = session.byNaturalId( TestEntity.class )
.using( "code", 4 )
.using( "item", 5 )
.load();
List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( CacheGetEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 2 );
RecordedEvent event = events.get( 0 );
assertThat( event.getEventType().getName() )
.isEqualTo( CacheGetEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( session.getSessionIdentifier().toString() );
assertThat( event.getString( "entityName" ) )
.isEqualTo( TestEntity.class.getName() );
assertThat( event.getBoolean( "isNaturalId" ) ).isTrue();
assertThat( event.getBoolean( "hit" ) ).isTrue();
assertThat( event.getString( "regionName" ) ).isNotNull();
event = events.get( 1 );
assertThat( event.getEventType().getName() )
.isEqualTo( CacheGetEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( session.getSessionIdentifier().toString() );
assertThat( event.getString( "entityName" ) )
.isEqualTo( TestEntity.class.getName() );
assertThat( event.getBoolean( "isNaturalId" ) ).isFalse();
assertThat( event.getBoolean( "hit" ) ).isTrue();
assertThat( event.getString( "regionName" ) ).isNotNull();
}
);
}
@Entity(name = "TestEntity")
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
@Cacheable
@NaturalIdCache
public static class TestEntity {
@Id
private Integer id;
@NaturalId
private Integer code;
@NaturalId
private Integer item;
private String description = "A description ...";
protected TestEntity() {
}
public TestEntity(Integer id, Integer code, Integer item) {
this.id = id;
this.code = code;
this.item = item;
}
}
}

View File

@ -0,0 +1,115 @@
package org.hibernate.orm.test.event.jfr.cache;
import java.util.List;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import org.hibernate.annotations.NaturalId;
import org.hibernate.annotations.NaturalIdCache;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.event.jfr.CachePutEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Cacheable;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jdk.jfr.consumer.RecordedEvent;
import org.moditect.jfrunit.EnableEvent;
import org.moditect.jfrunit.JfrEventTest;
import org.moditect.jfrunit.JfrEvents;
import static org.assertj.core.api.Assertions.assertThat;
@JfrEventTest
@DomainModel(annotatedClasses = {
NaturalIdPutCacheTests.TestEntity.class
})
@SessionFactory
@ServiceRegistry(
settings = {
@Setting(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true"),
}
)
public class NaturalIdPutCacheTests {
public JfrEvents jfrEvents = new JfrEvents();
@Test
@EnableEvent(CachePutEvent.NAME)
public void testCachePutEvent(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
TestEntity testEntity = new TestEntity( 1, 2, 3 );
session.persist( testEntity );
session.flush();
List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( CachePutEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 2 );
RecordedEvent event = events.get( 0 );
assertThat( event.getEventType().getName() )
.isEqualTo( CachePutEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( session.getSessionIdentifier().toString() );
assertThat( event.getString( "entityName" ) ).isEqualTo( TestEntity.class.getName() );
assertThat( event.getBoolean( "cacheChanged" ) ).isTrue();
assertThat( event.getBoolean( "isNaturalId" ) ).isFalse();
assertThat( event.getString( "regionName" ) ).isNotNull();
assertThat( event.getString( "description" ) ).isEqualTo( JfrEventManager.CacheActionDescription.ENTITY_INSERT.getText() );
event = events.get( 1 );
assertThat( event.getEventType().getName() )
.isEqualTo( CachePutEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( session.getSessionIdentifier().toString() );
assertThat( event.getString( "entityName" ) ).isEqualTo( TestEntity.class.getName() );
// cache strategy is READ_WRITE so no cache insert happened
assertThat( event.getBoolean( "cacheChanged" ) ).isTrue();
assertThat( event.getBoolean( "isNaturalId" ) ).isTrue();
assertThat( event.getString( "regionName" ) ).isNotNull();
assertThat( event.getString( "description" ) ).isEqualTo( JfrEventManager.CacheActionDescription.ENTITY_INSERT.getText() );
}
);
}
@Entity(name = "TestEntity")
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
@Cacheable
@NaturalIdCache
public static class TestEntity {
@Id
private Integer id;
@NaturalId
private Integer code;
@NaturalId
private Integer item;
private String description = "A description ...";
protected TestEntity() {
}
public TestEntity(Integer id, Integer code, Integer item) {
this.id = id;
this.code = code;
this.item = item;
}
}
}

View File

@ -0,0 +1,131 @@
package org.hibernate.orm.test.event.jfr.cache;
import java.util.List;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.event.jfr.CachePutEvent;
import org.hibernate.event.jfr.JdbcBatchExecutionEvent;
import org.hibernate.event.jfr.internal.JfrEventManager;
import org.hibernate.orm.test.cache.CacheRegionStatisticsTest;
import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.ServiceRegistry;
import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import jdk.jfr.consumer.RecordedEvent;
import org.moditect.jfrunit.EnableEvent;
import org.moditect.jfrunit.JfrEventTest;
import org.moditect.jfrunit.JfrEvents;
import static org.assertj.core.api.Assertions.assertThat;
@JfrEventTest
@DomainModel(annotatedClasses = {
QueryCachePutEventTests.TestEntity.class,
})
@SessionFactory
@ServiceRegistry(
settings =
{
@Setting(name = AvailableSettings.USE_SECOND_LEVEL_CACHE, value = "true"),
@Setting(name = AvailableSettings.USE_QUERY_CACHE, value = "true")
}
)
public class QueryCachePutEventTests {
public JfrEvents jfrEvents = new JfrEvents();
@BeforeAll
public void setUp(SessionFactoryScope scope) {
scope.inTransaction(
session -> {
for ( int i = 2; i < 10; i++ ) {
TestEntity entity = new TestEntity( i, "name_" + i );
session.persist( entity );
}
}
);
}
@Test
@EnableEvent(JdbcBatchExecutionEvent.NAME)
public void testCachePutEvent(SessionFactoryScope scope) {
jfrEvents.reset();
scope.inTransaction(
session -> {
List<CacheRegionStatisticsTest.Dog> dogs = session.createQuery(
"from TestEntity",
CacheRegionStatisticsTest.Dog.class
).setCacheable( true ).getResultList();
final List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( CachePutEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 1 );
RecordedEvent event = events.get( 0 );
assertThat( event.getEventType().getName() )
.isEqualTo( CachePutEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( session.getSessionIdentifier().toString() );
assertThat( event.getBoolean( "cacheChanged" ) ).isTrue();
assertThat( event.getString( "regionName" ) ).isNotNull();
assertThat( event.getBoolean( "isNaturalId" ) ).isFalse();
assertThat( event.getString( "description" ) ).isEqualTo( JfrEventManager.CacheActionDescription.QUERY_RESULT.getText() );
}
);
}
@Test
@EnableEvent(JdbcBatchExecutionEvent.NAME)
public void testJdbcBatchExecutionEventNoFired(SessionFactoryScope scope) {
jfrEvents.reset();
scope.inTransaction(
session -> {
session.createQuery(
"from TestEntity",
CacheRegionStatisticsTest.Dog.class
).setCacheable( false ).getResultList();
}
);
final List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( CachePutEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 0 );
}
@Entity(name = "TestEntity")
public static class TestEntity {
@Id
private Integer id;
private String name;
public TestEntity() {
}
public TestEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
}
}

View File

@ -0,0 +1,103 @@
package org.hibernate.orm.test.event.jfr.flush;
import java.util.List;
import org.hibernate.event.jfr.FlushEvent;
import org.hibernate.event.jfr.PartialFlushEvent;
import org.hibernate.testing.orm.junit.DomainModel;
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 jdk.jfr.consumer.RecordedEvent;
import org.moditect.jfrunit.EnableEvent;
import org.moditect.jfrunit.JfrEventTest;
import org.moditect.jfrunit.JfrEvents;
import static org.assertj.core.api.Assertions.assertThat;
@JfrEventTest
@DomainModel(annotatedClasses = {
AutoFlushTests.TestEntity.class,
})
@SessionFactory
public class AutoFlushTests {
public JfrEvents jfrEvents = new JfrEvents();
@Test
@EnableEvent(FlushEvent.NAME)
@EnableEvent(PartialFlushEvent.NAME)
public void testFlushEvent(SessionFactoryScope scope) {
jfrEvents.reset();
scope.inTransaction(
session -> {
TestEntity entity = new TestEntity( 1, "name_1" );
session.persist( entity );
session.createQuery( "select t from TestEntity t" ).list();
List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( FlushEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 1 );
RecordedEvent event = events.get( 0 );
assertThat( event.getEventType().getName() )
.isEqualTo( FlushEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( session.getSessionIdentifier().toString() );
assertThat( event.getInt( "numberOfEntitiesProcessed" ) )
.isEqualTo( 1 );
assertThat( event.getInt( "numberOfCollectionsProcessed" ) ).isEqualTo( 0 );
assertThat( event.getBoolean( "isAutoFlush" ) ).isTrue();
events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( PartialFlushEvent.NAME );
}
).toList();
event = events.get( 0 );
assertThat( event.getEventType().getName() )
.isEqualTo( PartialFlushEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( session.getSessionIdentifier().toString() );
assertThat( event.getInt( "numberOfEntitiesProcessed" ) )
.isEqualTo( 1 );
assertThat( event.getInt( "numberOfCollectionsProcessed" ) ).isEqualTo( 0 );
assertThat( event.getBoolean( "isAutoFlush" ) ).isTrue();
}
);
}
@Entity(name = "TestEntity")
public static class TestEntity {
@Id
private Integer id;
private String name;
public TestEntity() {
}
public TestEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
public void setName(String name) {
this.name = name;
}
}
}

View File

@ -0,0 +1,82 @@
package org.hibernate.orm.test.event.jfr.flush;
import java.util.List;
import org.hibernate.event.jfr.FlushEvent;
import org.hibernate.testing.orm.junit.DomainModel;
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 jdk.jfr.consumer.RecordedEvent;
import org.moditect.jfrunit.EnableEvent;
import org.moditect.jfrunit.JfrEventTest;
import org.moditect.jfrunit.JfrEvents;
import static org.assertj.core.api.Assertions.assertThat;
@JfrEventTest
@DomainModel(annotatedClasses = {
ExplicitFlushTests.TestEntity.class,
})
@SessionFactory
public class ExplicitFlushTests {
public JfrEvents jfrEvents = new JfrEvents();
@Test
@EnableEvent(FlushEvent.NAME)
public void testFlushEvent(SessionFactoryScope scope) {
jfrEvents.reset();
scope.inTransaction(
session -> {
TestEntity entity = new TestEntity( 1, "name_1" );
session.persist( entity );
session.flush();
List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( FlushEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 1 );
RecordedEvent event = events.get( 0 );
assertThat( event.getEventType().getName() )
.isEqualTo( FlushEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( session.getSessionIdentifier().toString() );
assertThat( event.getInt( "numberOfEntitiesProcessed" ) )
.isEqualTo( 1 );
assertThat( event.getInt( "numberOfCollectionsProcessed" ) ).isEqualTo( 0 );
assertThat( event.getBoolean( "isAutoFlush" ) ).isFalse();
}
);
}
@Entity(name = "TestEntity")
public static class TestEntity {
@Id
private Integer id;
private String name;
public TestEntity() {
}
public TestEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
public void setName(String name) {
this.name = name;
}
}
}

View File

@ -0,0 +1,104 @@
package org.hibernate.orm.test.event.jfr.flush;
import java.util.List;
import org.hibernate.event.jfr.FlushEvent;
import org.hibernate.event.jfr.JdbcBatchExecutionEvent;
import org.hibernate.testing.orm.junit.DomainModel;
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 jdk.jfr.consumer.RecordedEvent;
import org.moditect.jfrunit.EnableEvent;
import org.moditect.jfrunit.JfrEventTest;
import org.moditect.jfrunit.JfrEvents;
import static org.assertj.core.api.Assertions.assertThat;
@JfrEventTest
@DomainModel(annotatedClasses = {
FlushTests.TestEntity.class,
})
@SessionFactory
public class FlushTests {
public JfrEvents jfrEvents = new JfrEvents();
@Test
@EnableEvent(FlushEvent.NAME)
public void testFlushEvent(SessionFactoryScope scope) {
jfrEvents.reset();
String sessionId = scope.fromTransaction(
session -> {
TestEntity entity = new TestEntity( 1, "name_1" );
session.persist( entity );
return session.getSessionIdentifier().toString();
}
);
List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( FlushEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 1 );
RecordedEvent event = events.get( 0 );
assertThat( event.getEventType().getName() )
.isEqualTo( FlushEvent.NAME );
assertThat( event.getLong( "executionTime" ) ).isGreaterThan( 0 );
assertThat( event.getString( "sessionIdentifier" ) )
.isEqualTo( sessionId );
assertThat( event.getInt( "numberOfEntitiesProcessed" ) )
.isEqualTo( 1 );
assertThat( event.getInt( "numberOfCollectionsProcessed" ) ).isEqualTo( 0 );
assertThat( event.getBoolean( "isAutoFlush" ) ).isFalse();
}
@Test
@EnableEvent(JdbcBatchExecutionEvent.NAME)
public void testFlushNoFired(SessionFactoryScope scope) {
jfrEvents.reset();
scope.inTransaction(
session -> {
}
);
List<RecordedEvent> events = jfrEvents.events()
.filter(
recordedEvent ->
{
String eventName = recordedEvent.getEventType().getName();
return eventName.equals( FlushEvent.NAME );
}
).toList();
assertThat( events ).hasSize( 0 );
}
@Entity(name = "TestEntity")
public static class TestEntity {
@Id
private Integer id;
private String name;
public TestEntity() {
}
public TestEntity(Integer id, String name) {
this.id = id;
this.name = name;
}
public void setName(String name) {
this.name = name;
}
}
}