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.SessionEventListenerManager;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; 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.service.spi.EventListenerGroup;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.PostCommitInsertEventListener; import org.hibernate.event.spi.PostCommitInsertEventListener;
@ -161,11 +164,23 @@ public class EntityInsertAction extends AbstractEntityInsertAction {
protected boolean cacheInsert(EntityPersister persister, Object ck) { protected boolean cacheInsert(EntityPersister persister, Object ck) {
SharedSessionContractImplementor session = getSession(); SharedSessionContractImplementor session = getSession();
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
final EntityDataAccess cacheAccessStrategy = persister.getCacheAccessStrategy();
boolean insert = false;
try { try {
session.getEventListenerManager().cachePutStart(); session.getEventListenerManager().cachePutStart();
return persister.getCacheAccessStrategy().insert( session, ck, cacheEntry, version ); insert = cacheAccessStrategy.insert( session, ck, cacheEntry, version );
return insert;
} }
finally { finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cacheAccessStrategy,
getPersister(),
insert,
CacheActionDescription.ENTITY_INSERT
);
session.getEventListenerManager().cachePutEnd(); session.getEventListenerManager().cachePutEnd();
} }
} }
@ -240,11 +255,22 @@ public class EntityInsertAction extends AbstractEntityInsertAction {
protected boolean cacheAfterInsert(EntityDataAccess cache, Object ck) { protected boolean cacheAfterInsert(EntityDataAccess cache, Object ck) {
SharedSessionContractImplementor session = getSession(); SharedSessionContractImplementor session = getSession();
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager(); final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
boolean afterInsert = false;
try { try {
eventListenerManager.cachePutStart(); eventListenerManager.cachePutStart();
return cache.afterInsert( session, ck, cacheEntry, version ); afterInsert = cache.afterInsert( session, ck, cacheEntry, version );
return afterInsert;
} }
finally { finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cache,
getPersister(),
afterInsert,
CacheActionDescription.ENTITY_AFTER_INSERT
);
eventListenerManager.cachePutEnd(); 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.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.Status; 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.service.spi.EventListenerGroup;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
import org.hibernate.event.spi.PostCommitUpdateEventListener; import org.hibernate.event.spi.PostCommitUpdateEventListener;
@ -307,11 +309,23 @@ public class EntityUpdateAction extends EntityAction {
protected boolean updateCache(EntityPersister persister, Object previousVersion, Object ck) { protected boolean updateCache(EntityPersister persister, Object previousVersion, Object ck) {
final SharedSessionContractImplementor session = getSession(); final SharedSessionContractImplementor session = getSession();
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
final EntityDataAccess cacheAccessStrategy = persister.getCacheAccessStrategy();
boolean update = false;
try { try {
session.getEventListenerManager().cachePutStart(); session.getEventListenerManager().cachePutStart();
return persister.getCacheAccessStrategy().update( session, ck, cacheEntry, nextVersion, previousVersion ); update = cacheAccessStrategy.update( session, ck, cacheEntry, nextVersion, previousVersion );
return update;
} }
finally { finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cacheAccessStrategy,
getPersister(),
update,
JfrEventManager.CacheActionDescription.ENTITY_UPDATE
);
session.getEventListenerManager().cachePutEnd(); session.getEventListenerManager().cachePutEnd();
} }
} }
@ -420,10 +434,21 @@ public class EntityUpdateAction extends EntityAction {
protected void cacheAfterUpdate(EntityDataAccess cache, Object ck, SharedSessionContractImplementor session) { protected void cacheAfterUpdate(EntityDataAccess cache, Object ck, SharedSessionContractImplementor session) {
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager(); final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
boolean put = false;
try { try {
eventListenerManager.cachePutStart(); 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(); final StatisticsImplementor statistics = session.getFactory().getStatistics();
if ( put && statistics.isStatisticsEnabled() ) { if ( put && statistics.isStatisticsEnabled() ) {
statistics.entityCachePut( statistics.entityCachePut(
@ -431,8 +456,6 @@ public class EntityUpdateAction extends EntityAction {
cache.getRegion().getName() cache.getRegion().getName()
); );
} }
}
finally {
eventListenerManager.cachePutEnd(); 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.QueryResultsRegion;
import org.hibernate.cache.spi.TimestampsCache; import org.hibernate.cache.spi.TimestampsCache;
import org.hibernate.engine.spi.SharedSessionContractImplementor; 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; import static org.hibernate.cache.spi.SecondLevelCacheLogger.L2CACHE_LOGGER;
@ -61,11 +64,19 @@ public class QueryResultsCacheImpl implements QueryResultsCache {
deepCopy( results ) deepCopy( results )
); );
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
try { try {
session.getEventListenerManager().cachePutStart(); session.getEventListenerManager().cachePutStart();
cacheRegion.putIntoCache( key, cacheItem, session ); cacheRegion.putIntoCache( key, cacheItem, session );
} }
finally { finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cacheRegion,
true,
JfrEventManager.CacheActionDescription.QUERY_RESULT
);
session.getEventListenerManager().cachePutEnd(); session.getEventListenerManager().cachePutEnd();
} }
@ -142,11 +153,18 @@ public class QueryResultsCacheImpl implements QueryResultsCache {
private CacheItem getCachedData(QueryKey key, SharedSessionContractImplementor session) { private CacheItem getCachedData(QueryKey key, SharedSessionContractImplementor session) {
CacheItem cachedItem = null; CacheItem cachedItem = null;
final CacheGetEvent cacheGetEvent = JfrEventManager.beginCacheGetEvent();
try { try {
session.getEventListenerManager().cacheGetStart(); session.getEventListenerManager().cacheGetStart();
cachedItem = (CacheItem) cacheRegion.getFromCache( key, session ); cachedItem = (CacheItem) cacheRegion.getFromCache( key, session );
} }
finally { finally {
JfrEventManager.completeCacheGetEvent(
cacheGetEvent,
session,
cacheRegion,
cachedItem != null
);
session.getEventListenerManager().cacheGetEnd( cachedItem != null ); session.getEventListenerManager().cacheGetEnd( cachedItem != null );
} }
return cachedItem; 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.SessionEventListenerManager;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; 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.hibernate.stat.spi.StatisticsImplementor;
import org.jboss.logging.Logger; import org.jboss.logging.Logger;
@ -58,7 +61,7 @@ public class TimestampsCacheEnabledImpl implements TimestampsCache {
if ( debugEnabled ) { if ( debugEnabled ) {
log.debugf( "Pre-invalidating space [%s], timestamp: %s", space, ts ); log.debugf( "Pre-invalidating space [%s], timestamp: %s", space, ts );
} }
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
try { try {
eventListenerManager.cachePutStart(); eventListenerManager.cachePutStart();
@ -67,6 +70,13 @@ public class TimestampsCacheEnabledImpl implements TimestampsCache {
timestampsRegion.putIntoCache( space, ts, session ); timestampsRegion.putIntoCache( space, ts, session );
} }
finally { finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
timestampsRegion,
true,
JfrEventManager.CacheActionDescription.TIMESTAMP_PRE_INVALIDATE
);
eventListenerManager.cachePutEnd(); eventListenerManager.cachePutEnd();
} }
@ -92,11 +102,19 @@ public class TimestampsCacheEnabledImpl implements TimestampsCache {
} }
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager(); final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
try { try {
eventListenerManager.cachePutStart(); eventListenerManager.cachePutStart();
timestampsRegion.putIntoCache( space, ts, session ); timestampsRegion.putIntoCache( space, ts, session );
} }
finally { finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
timestampsRegion,
true,
JfrEventManager.CacheActionDescription.TIMESTAMP_INVALIDATE
);
eventListenerManager.cachePutEnd(); eventListenerManager.cachePutEnd();
if ( stats ) { if ( stats ) {
@ -175,11 +193,18 @@ public class TimestampsCacheEnabledImpl implements TimestampsCache {
private Long getLastUpdateTimestampForSpace(String space, SharedSessionContractImplementor session) { private Long getLastUpdateTimestampForSpace(String space, SharedSessionContractImplementor session) {
Long ts = null; Long ts = null;
final CacheGetEvent cacheGetEvent = JfrEventManager.beginCacheGetEvent();
try { try {
session.getEventListenerManager().cacheGetStart(); session.getEventListenerManager().cacheGetStart();
ts = (Long) timestampsRegion.getFromCache( space, session ); ts = (Long) timestampsRegion.getFromCache( space, session );
} }
finally { finally {
JfrEventManager.completeCacheGetEvent(
cacheGetEvent,
session,
timestampsRegion,
ts != null
);
session.getEventListenerManager().cacheGetEnd( ts != null ); session.getEventListenerManager().cacheGetEnd( ts != null );
} }
return ts; return ts;

View File

@ -12,7 +12,11 @@ import org.hibernate.cache.MutableCacheKeyBuilder;
import org.hibernate.cache.spi.access.CachedDomainDataAccess; import org.hibernate.cache.spi.access.CachedDomainDataAccess;
import org.hibernate.engine.spi.SessionEventListenerManager; import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SharedSessionContractImplementor; 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.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.converter.spi.BasicValueConverter;
import org.hibernate.type.descriptor.java.JavaType; import org.hibernate.type.descriptor.java.JavaType;
@ -28,14 +32,58 @@ public final class CacheHelper {
public static Object fromSharedCache( public static Object fromSharedCache(
SharedSessionContractImplementor session, SharedSessionContractImplementor session,
Object cacheKey, 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) { CachedDomainDataAccess cacheAccess) {
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager(); final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
Object cachedValue = null; Object cachedValue = null;
eventListenerManager.cacheGetStart(); eventListenerManager.cacheGetStart();
final CacheGetEvent cacheGetEvent = JfrEventManager.beginCacheGetEvent();
try { try {
cachedValue = cacheAccess.get( session, cacheKey ); cachedValue = cacheAccess.get( session, cacheKey );
} }
finally { 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 ); eventListenerManager.cacheGetEnd( cachedValue != null );
} }
return cachedValue; 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.Resolution;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; 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.EntityMappingType;
import org.hibernate.metamodel.mapping.NaturalIdLogging; import org.hibernate.metamodel.mapping.NaturalIdLogging;
import org.hibernate.metamodel.mapping.NaturalIdMapping; import org.hibernate.metamodel.mapping.NaturalIdMapping;
@ -268,11 +270,14 @@ public class NaturalIdResolutionsImpl implements NaturalIdResolutions, Serializa
switch ( source ) { switch ( source ) {
case LOAD: { case LOAD: {
if ( CacheHelper.fromSharedCache( s, cacheKey, cacheAccess ) != null ) { if ( CacheHelper.fromSharedCache( s, cacheKey, persister, cacheAccess ) != null ) {
// prevent identical re-cachings // prevent identical re-cachings
return; return;
} }
final boolean put = cacheAccess.putFromLoad( boolean put = false;
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
try {
put = cacheAccess.putFromLoad(
s, s,
cacheKey, cacheKey,
id, id,
@ -285,17 +290,45 @@ public class NaturalIdResolutionsImpl implements NaturalIdResolutions, Serializa
cacheAccess.getRegion().getName() cacheAccess.getRegion().getName()
); );
} }
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session(),
cacheAccess,
rootEntityPersister,
put,
true,
JfrEventManager.CacheActionDescription.ENTITY_LOAD
);
}
break; break;
} }
case INSERT: { 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() ) { if ( put && statistics.isStatisticsEnabled() ) {
statistics.naturalIdCachePut( statistics.naturalIdCachePut(
rootEntityDescriptor.getNavigableRole(), rootEntityDescriptor.getNavigableRole(),
cacheAccess.getRegion().getName() cacheAccess.getRegion().getName()
); );
} }
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session(),
cacheAccess,
rootEntityPersister,
put,
true,
JfrEventManager.CacheActionDescription.ENTITY_INSERT
);
}
s.asEventSource().getActionQueue().registerProcess( s.asEventSource().getActionQueue().registerProcess(
(success, session) -> { (success, session) -> {
@ -326,32 +359,62 @@ public class NaturalIdResolutionsImpl implements NaturalIdResolutions, Serializa
cacheAccess.remove( s, previousCacheKey); cacheAccess.remove( s, previousCacheKey);
final SoftLock lock = cacheAccess.lockItem( s, cacheKey, null ); 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() ) { if ( put && statistics.isStatisticsEnabled() ) {
statistics.naturalIdCachePut( statistics.naturalIdCachePut(
rootEntityDescriptor.getNavigableRole(), rootEntityDescriptor.getNavigableRole(),
cacheAccess.getRegion().getName() cacheAccess.getRegion().getName()
); );
} }
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session(),
cacheAccess,
rootEntityPersister,
put,
true,
JfrEventManager.CacheActionDescription.ENTITY_UPDATE
);
}
s.asEventSource().getActionQueue().registerProcess( s.asEventSource().getActionQueue().registerProcess(
(success, session) -> { (success, session) -> {
cacheAccess.unlockItem( s, previousCacheKey, removalLock ); cacheAccess.unlockItem( s, previousCacheKey, removalLock );
if (success) { if (success) {
final boolean put12 = cacheAccess.afterUpdate( boolean putAfterUpdate = false;
final CachePutEvent cachePutEventAfterUpdate = JfrEventManager.beginCachePutEvent();
try {
putAfterUpdate = cacheAccess.afterUpdate(
s, s,
cacheKey, cacheKey,
id, id,
lock lock
); );
if ( put12 && statistics.isStatisticsEnabled() ) { if ( putAfterUpdate && statistics.isStatisticsEnabled() ) {
statistics.naturalIdCachePut( statistics.naturalIdCachePut(
rootEntityDescriptor.getNavigableRole(), rootEntityDescriptor.getNavigableRole(),
cacheAccess.getRegion().getName() cacheAccess.getRegion().getName()
); );
} }
} }
finally {
JfrEventManager.completeCachePutEvent(
cachePutEventAfterUpdate,
session(),
cacheAccess,
rootEntityPersister,
putAfterUpdate,
true,
JfrEventManager.CacheActionDescription.ENTITY_AFTER_UPDATE
);
}
}
else { else {
cacheAccess.unlockItem( s, cacheKey, lock ); cacheAccess.unlockItem( s, cacheKey, lock );
} }
@ -567,7 +630,7 @@ public class NaturalIdResolutionsImpl implements NaturalIdResolutions, Serializa
final SharedSessionContractImplementor session = session(); final SharedSessionContractImplementor session = session();
final Object naturalIdCacheKey = naturalIdCacheAccessStrategy.generateCacheKey( naturalId, persister, 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 // Found in second-level cache, store in session cache
final SessionFactoryImplementor factory = session.getFactory(); 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.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger; 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 org.hibernate.resource.jdbc.spi.JdbcObserver;
import static org.hibernate.engine.jdbc.JdbcLogging.JDBC_MESSAGE_LOGGER; import static org.hibernate.engine.jdbc.JdbcLogging.JDBC_MESSAGE_LOGGER;
@ -268,11 +270,13 @@ public class BatchImpl implements Batch {
try { try {
if ( statementDetails.getMutatingTableDetails().isIdentifierTable() ) { if ( statementDetails.getMutatingTableDetails().isIdentifierTable() ) {
final int[] rowCounts; final int[] rowCounts;
final JdbcBatchExecutionEvent jdbcBatchExecutionEvent = JfrEventManager.beginJdbcBatchExecutionEvent();
try { try {
observer.jdbcExecuteBatchStart(); observer.jdbcExecuteBatchStart();
rowCounts = statement.executeBatch(); rowCounts = statement.executeBatch();
} }
finally { finally {
JfrEventManager.completeJdbcBatchExecutionEvent( jdbcBatchExecutionEvent, sql );
observer.jdbcExecuteBatchEnd(); observer.jdbcExecuteBatchEnd();
} }
checkRowCounts( rowCounts, statementDetails ); 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.JdbcServices;
import org.hibernate.engine.jdbc.spi.MutationStatementPreparer; import org.hibernate.engine.jdbc.spi.MutationStatementPreparer;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; 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.JdbcObserver;
import org.hibernate.resource.jdbc.spi.JdbcSessionContext; import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor; import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
@ -95,12 +97,14 @@ public class MutationStatementPreparerImpl implements MutationStatementPreparer
final JdbcObserver observer = jdbcCoordinator.getJdbcSessionOwner() final JdbcObserver observer = jdbcCoordinator.getJdbcSessionOwner()
.getJdbcSessionContext() .getJdbcSessionContext()
.getObserver(); .getObserver();
final JdbcPreparedStatementCreationEvent jdbcPreparedStatementCreation = JfrEventManager.beginJdbcPreparedStatementCreationEvent();
try { try {
observer.jdbcPrepareStatementStart(); observer.jdbcPrepareStatementStart();
preparedStatement = doPrepare(); preparedStatement = doPrepare();
setStatementTimeout( preparedStatement ); setStatementTimeout( preparedStatement );
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementCreationEvent( jdbcPreparedStatementCreation, sql );
observer.jdbcPrepareStatementEnd(); observer.jdbcPrepareStatementEnd();
} }
postProcess( preparedStatement ); 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.ResultSetReturn;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.SqlStatementLogger; 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; import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
/** /**
@ -44,31 +46,6 @@ public class ResultSetReturnImpl implements ResultSetReturn {
this.sqlExceptionHelper = jdbcServices.getSqlExceptionHelper(); 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 @Override
public ResultSet extract(PreparedStatement statement, String sql) { public ResultSet extract(PreparedStatement statement, String sql) {
// IMPL NOTE : SQL logged by caller // IMPL NOTE : SQL logged by caller
@ -78,11 +55,13 @@ public class ResultSetReturnImpl implements ResultSetReturn {
} }
try { try {
final ResultSet rs; final ResultSet rs;
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try { try {
jdbcExecuteStatementStart(); jdbcExecuteStatementStart();
rs = statement.executeQuery(); rs = statement.executeQuery();
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
jdbcExecuteStatementEnd(); jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() ); sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() );
} }
@ -106,31 +85,6 @@ public class ResultSetReturnImpl implements ResultSetReturn {
jdbcCoordinator.getJdbcSessionOwner().getJdbcSessionContext().getObserver().jdbcExecuteStatementStart(); 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 @Override
public ResultSet extract(Statement statement, String sql) { public ResultSet extract(Statement statement, String sql) {
sqlStatementLogger.logStatement( sql ); sqlStatementLogger.logStatement( sql );
@ -140,11 +94,13 @@ public class ResultSetReturnImpl implements ResultSetReturn {
} }
try { try {
final ResultSet rs; final ResultSet rs;
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try { try {
jdbcExecuteStatementStart(); jdbcExecuteStatementStart();
rs = statement.executeQuery( sql ); rs = statement.executeQuery( sql );
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
jdbcExecuteStatementEnd(); jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() ); 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 @Override
public ResultSet execute(PreparedStatement statement, String sql) { public ResultSet execute(PreparedStatement statement, String sql) {
// sql logged by StatementPreparerImpl // sql logged by StatementPreparerImpl
@ -195,6 +121,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
} }
try { try {
final ResultSet rs; final ResultSet rs;
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try { try {
jdbcExecuteStatementStart(); jdbcExecuteStatementStart();
if ( !statement.execute() ) { if ( !statement.execute() ) {
@ -205,6 +132,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
rs = statement.getResultSet(); rs = statement.getResultSet();
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
jdbcExecuteStatementEnd(); jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() ); sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() );
} }
@ -225,6 +153,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
} }
try { try {
final ResultSet rs; final ResultSet rs;
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try { try {
jdbcExecuteStatementStart(); jdbcExecuteStatementStart();
if ( !statement.execute( sql ) ) { if ( !statement.execute( sql ) ) {
@ -235,6 +164,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
rs = statement.getResultSet(); rs = statement.getResultSet();
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
jdbcExecuteStatementEnd(); jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() ); 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 @Override
public int executeUpdate(PreparedStatement statement, String sql) { public int executeUpdate(PreparedStatement statement, String sql) {
assert statement != null; assert statement != null;
@ -275,6 +184,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) { if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStartNanos = System.nanoTime(); executeStartNanos = System.nanoTime();
} }
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try { try {
jdbcExecuteStatementStart(); jdbcExecuteStatementStart();
return statement.executeUpdate(); return statement.executeUpdate();
@ -283,6 +193,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
throw sqlExceptionHelper.convert( e, "could not execute statement", sql ); throw sqlExceptionHelper.convert( e, "could not execute statement", sql );
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
jdbcExecuteStatementEnd(); jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() ); sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() );
} }
@ -295,6 +206,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) { if ( this.sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStartNanos = System.nanoTime(); executeStartNanos = System.nanoTime();
} }
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try { try {
jdbcExecuteStatementStart(); jdbcExecuteStatementStart();
return statement.executeUpdate( sql ); return statement.executeUpdate( sql );
@ -303,6 +215,7 @@ public class ResultSetReturnImpl implements ResultSetReturn {
throw sqlExceptionHelper.convert( e, "could not execute statement", sql ); throw sqlExceptionHelper.convert( e, "could not execute statement", sql );
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
jdbcExecuteStatementEnd(); jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( sql, executeStartNanos, context() ); 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.JdbcServices;
import org.hibernate.engine.jdbc.spi.SqlExceptionHelper; import org.hibernate.engine.jdbc.spi.SqlExceptionHelper;
import org.hibernate.engine.jdbc.spi.StatementPreparer; 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.JdbcObserver;
import org.hibernate.resource.jdbc.spi.JdbcSessionContext; import org.hibernate.resource.jdbc.spi.JdbcSessionContext;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor; import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
@ -172,12 +174,14 @@ class StatementPreparerImpl implements StatementPreparer {
final PreparedStatement preparedStatement; final PreparedStatement preparedStatement;
final JdbcObserver observer = jdbcCoordinator.getJdbcSessionOwner().getJdbcSessionContext().getObserver(); final JdbcObserver observer = jdbcCoordinator.getJdbcSessionOwner().getJdbcSessionContext().getObserver();
final JdbcPreparedStatementCreationEvent jdbcPreparedStatementCreation = JfrEventManager.beginJdbcPreparedStatementCreationEvent();
try { try {
observer.jdbcPrepareStatementStart(); observer.jdbcPrepareStatementStart();
preparedStatement = doPrepare(); preparedStatement = doPrepare();
setStatementTimeout( preparedStatement ); setStatementTimeout( preparedStatement );
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementCreationEvent( jdbcPreparedStatementCreation, sql );
observer.jdbcPrepareStatementEnd(); observer.jdbcPrepareStatementEnd();
} }
postProcess( preparedStatement ); postProcess( preparedStatement );

View File

@ -24,21 +24,6 @@ import java.sql.Statement;
*/ */
public interface ResultSetReturn { 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}. * Extract the {@link ResultSet} from the {@link PreparedStatement}.
* <p> * <p>
@ -51,20 +36,6 @@ public interface ResultSetReturn {
*/ */
ResultSet extract(PreparedStatement statement, String sql); 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 * Performs the given SQL statement, expecting a {@link ResultSet} in return
* *
@ -75,19 +46,6 @@ public interface ResultSetReturn {
*/ */
ResultSet extract(Statement statement, String sql); 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. * Execute the {@link PreparedStatement} return its first {@link ResultSet}, if any.
* If there is no {@link ResultSet}, returns {@code null} * If there is no {@link ResultSet}, returns {@code null}
@ -110,18 +68,6 @@ public interface ResultSetReturn {
*/ */
ResultSet execute(Statement statement, String sql); 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". * Execute the {@link PreparedStatement}, returning its "affected row count".
* *

View File

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

View File

@ -11,6 +11,8 @@ import org.hibernate.HibernateException;
import org.hibernate.engine.spi.ActionQueue; import org.hibernate.engine.spi.ActionQueue;
import org.hibernate.engine.spi.PersistenceContext; import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionEventListenerManager; 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.AutoFlushEvent;
import org.hibernate.event.spi.AutoFlushEventListener; import org.hibernate.event.spi.AutoFlushEventListener;
import org.hibernate.event.spi.EventSource; import org.hibernate.event.spi.EventSource;
@ -37,6 +39,7 @@ public class DefaultAutoFlushEventListener extends AbstractFlushingEventListener
public void onAutoFlush(AutoFlushEvent event) throws HibernateException { public void onAutoFlush(AutoFlushEvent event) throws HibernateException {
final EventSource source = event.getSession(); final EventSource source = event.getSession();
final SessionEventListenerManager eventListenerManager = source.getEventListenerManager(); final SessionEventListenerManager eventListenerManager = source.getEventListenerManager();
final PartialFlushEvent partialFlushEvent = JfrEventManager.beginPartialFlushEvent();
try { try {
eventListenerManager.partialFlushStart(); eventListenerManager.partialFlushStart();
@ -52,11 +55,16 @@ public class DefaultAutoFlushEventListener extends AbstractFlushingEventListener
// note: performExecutions() clears all collectionXxxxtion // note: performExecutions() clears all collectionXxxxtion
// collections (the collection actions) in the session // collections (the collection actions) in the session
final org.hibernate.event.jfr.FlushEvent jfrFlushEvent = JfrEventManager.beginFlushEvent();
try {
performExecutions( source ); performExecutions( source );
postFlush( source ); postFlush( source );
postPostFlush( source ); postPostFlush( source );
}
finally {
JfrEventManager.completeFlushEvent( jfrFlushEvent, event, true );
}
final StatisticsImplementor statistics = source.getFactory().getStatistics(); final StatisticsImplementor statistics = source.getFactory().getStatistics();
if ( statistics.isStatisticsEnabled() ) { if ( statistics.isStatisticsEnabled() ) {
statistics.flush(); statistics.flush();
@ -70,6 +78,7 @@ public class DefaultAutoFlushEventListener extends AbstractFlushingEventListener
} }
} }
finally { finally {
JfrEventManager.completePartialFlushEvent( partialFlushEvent, event );
eventListenerManager.partialFlushEnd( eventListenerManager.partialFlushEnd(
event.getNumberOfEntitiesProcessed(), event.getNumberOfEntitiesProcessed(),
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.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor; import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.spi.Status; 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.EventSource;
import org.hibernate.event.spi.FlushEntityEvent; import org.hibernate.event.spi.FlushEntityEvent;
import org.hibernate.event.spi.FlushEntityEventListener; import org.hibernate.event.spi.FlushEntityEventListener;
@ -482,11 +484,12 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
final SessionImplementor session = event.getSession(); final SessionImplementor session = event.getSession();
boolean dirtyCheckPossible; boolean dirtyCheckPossible;
int[] dirtyProperties = null; int[] dirtyProperties = null;
final DirtyCalculationEvent dirtyCalculationEvent = JfrEventManager.beginDirtyCalculationEvent();
final EntityEntry entry = event.getEntityEntry();
final EntityPersister persister = entry.getPersister();
try { try {
session.getEventListenerManager().dirtyCalculationStart(); session.getEventListenerManager().dirtyCalculationStart();
// object loaded by update() // object loaded by update()
final EntityEntry entry = event.getEntityEntry();
final EntityPersister persister = entry.getPersister();
final Object[] values = event.getPropertyValues(); final Object[] values = event.getPropertyValues();
final Object[] loadedState = entry.getLoadedState(); final Object[] loadedState = entry.getLoadedState();
final Object entity = event.getEntity(); final Object entity = event.getEntity();
@ -532,6 +535,7 @@ public class DefaultFlushEntityEventListener implements FlushEntityEventListener
event.setDirtyCheckPossible( dirtyCheckPossible ); event.setDirtyCheckPossible( dirtyCheckPossible );
} }
finally { finally {
JfrEventManager.completeDirtyCalculationEvent( dirtyCalculationEvent, session, persister, entry, dirtyProperties );
session.getEventListenerManager().dirtyCalculationEnd( dirtyProperties != null ); session.getEventListenerManager().dirtyCalculationEnd( dirtyProperties != null );
} }
return dirtyProperties; return dirtyProperties;

View File

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

View File

@ -127,7 +127,7 @@ public class DefaultInitializeCollectionEventListener implements InitializeColle
final SessionFactoryImplementor factory = source.getFactory(); final SessionFactoryImplementor factory = source.getFactory();
final CollectionDataAccess cacheAccessStrategy = persister.getCacheAccessStrategy(); final CollectionDataAccess cacheAccessStrategy = persister.getCacheAccessStrategy();
final Object ck = cacheAccessStrategy.generateCacheKey( id, persister, factory, source.getTenantIdentifier() ); 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(); final StatisticsImplementor statistics = factory.getStatistics();
if ( statistics.isStatisticsEnabled() ) { 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) @StackTrace(false)
@AllowNonPortable @AllowNonPortable
public class SessionOpenEvent extends Event { 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" ) @Label("Session Identifier" )
public String sessionIdentifier; 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.jdbc.spi.SqlStatementLogger;
import org.hibernate.engine.spi.SessionEventListenerManager; import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SharedSessionContractImplementor; 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.ExportableColumn;
import org.hibernate.id.IdentifierGeneratorHelper; import org.hibernate.id.IdentifierGeneratorHelper;
import org.hibernate.id.IntegralDataTypeHolder; import org.hibernate.id.IntegralDataTypeHolder;
@ -593,7 +596,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
try ( PreparedStatement selectPS = prepareStatement( connection, selectQuery, logger, listener ) ) { try ( PreparedStatement selectPS = prepareStatement( connection, selectQuery, logger, listener ) ) {
selectPS.setString( 1, segmentValue ); selectPS.setString( 1, segmentValue );
final ResultSet selectRS = executeQuery( selectPS, listener ); final ResultSet selectRS = executeQuery( selectPS, listener, selectQuery );
if ( !selectRS.next() ) { if ( !selectRS.next() ) {
long initializationValue; long initializationValue;
if ( storeLastUsedValue ) { if ( storeLastUsedValue ) {
@ -608,7 +611,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
LOG.tracef( "binding parameter [%s] - [%s]", 1, segmentValue ); LOG.tracef( "binding parameter [%s] - [%s]", 1, segmentValue );
statement.setString( 1, segmentValue ); statement.setString( 1, segmentValue );
value.bind( statement, 2 ); value.bind( statement, 2 );
executeUpdate( statement, listener); executeUpdate( statement, listener, insertQuery);
} }
} }
else { else {
@ -640,7 +643,7 @@ public class TableGenerator implements PersistentIdentifierGenerator {
updateValue.bind( statement, 1 ); updateValue.bind( statement, 1 );
value.bind( statement, 2 ); value.bind( statement, 2 );
statement.setString( 3, segmentValue ); statement.setString( 3, segmentValue );
rows = executeUpdate( statement, listener ); rows = executeUpdate( statement, listener, updateQuery );
} }
catch (SQLException e) { catch (SQLException e) {
LOG.unableToUpdateQueryHiValue( physicalTableName.render(), e ); LOG.unableToUpdateQueryHiValue( physicalTableName.render(), e );
@ -664,32 +667,37 @@ public class TableGenerator implements PersistentIdentifierGenerator {
SqlStatementLogger logger, SqlStatementLogger logger,
SessionEventListenerManager listener) throws SQLException { SessionEventListenerManager listener) throws SQLException {
logger.logStatement( sql, FormatStyle.BASIC.getFormatter() ); logger.logStatement( sql, FormatStyle.BASIC.getFormatter() );
final JdbcPreparedStatementCreationEvent jdbcPreparedStatementCreation = JfrEventManager.beginJdbcPreparedStatementCreationEvent();
try { try {
listener.jdbcPrepareStatementStart(); listener.jdbcPrepareStatementStart();
return connection.prepareStatement( sql ); return connection.prepareStatement( sql );
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementCreationEvent( jdbcPreparedStatementCreation, sql );
listener.jdbcPrepareStatementEnd(); 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 { try {
listener.jdbcExecuteStatementStart(); listener.jdbcExecuteStatementStart();
return ps.executeUpdate(); return ps.executeUpdate();
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
listener.jdbcExecuteStatementEnd(); 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 { try {
listener.jdbcExecuteStatementStart(); listener.jdbcExecuteStatementStart();
return ps.executeQuery(); return ps.executeQuery();
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
listener.jdbcExecuteStatementEnd(); 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.jdbc.spi.SqlStatementLogger;
import org.hibernate.engine.spi.SessionEventListenerManager; import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SharedSessionContractImplementor; 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.ExportableColumn;
import org.hibernate.id.IdentifierGenerationException; import org.hibernate.id.IdentifierGenerationException;
import org.hibernate.id.IdentifierGeneratorHelper; import org.hibernate.id.IdentifierGeneratorHelper;
@ -143,7 +146,7 @@ public class TableStructure implements DatabaseStructure {
statementLogger, statementLogger,
statsCollector statsCollector
)) { )) {
final ResultSet selectRS = executeQuery( selectStatement, statsCollector ); final ResultSet selectRS = executeQuery( selectStatement, statsCollector, selectQuery );
if ( !selectRS.next() ) { if ( !selectRS.next() ) {
final String err = "could not read a hi value - you need to populate the table: " + physicalTableName; final String err = "could not read a hi value - you need to populate the table: " + physicalTableName;
LOG.error( err ); LOG.error( err );
@ -168,7 +171,7 @@ public class TableStructure implements DatabaseStructure {
final IntegralDataTypeHolder updateValue = value.copy().add( increment ); final IntegralDataTypeHolder updateValue = value.copy().add( increment );
updateValue.bind( updatePS, 1 ); updateValue.bind( updatePS, 1 );
value.bind( updatePS, 2 ); value.bind( updatePS, 2 );
rows = executeUpdate( updatePS, statsCollector ); rows = executeUpdate( updatePS, statsCollector, updateQuery );
} }
catch (SQLException e) { catch (SQLException e) {
LOG.unableToUpdateQueryHiValue( physicalTableName.render(), e ); LOG.unableToUpdateQueryHiValue( physicalTableName.render(), e );
@ -198,32 +201,38 @@ public class TableStructure implements DatabaseStructure {
SqlStatementLogger statementLogger, SqlStatementLogger statementLogger,
SessionEventListenerManager statsCollector) throws SQLException { SessionEventListenerManager statsCollector) throws SQLException {
statementLogger.logStatement( sql, FormatStyle.BASIC.getFormatter() ); statementLogger.logStatement( sql, FormatStyle.BASIC.getFormatter() );
final JdbcPreparedStatementCreationEvent jdbcPreparedStatementCreation = JfrEventManager.beginJdbcPreparedStatementCreationEvent();
try { try {
statsCollector.jdbcPrepareStatementStart(); statsCollector.jdbcPrepareStatementStart();
return connection.prepareStatement( sql ); return connection.prepareStatement( sql );
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementCreationEvent( jdbcPreparedStatementCreation, sql );
statsCollector.jdbcPrepareStatementEnd(); 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 { try {
statsCollector.jdbcExecuteStatementStart(); statsCollector.jdbcExecuteStatementStart();
return ps.executeUpdate(); return ps.executeUpdate();
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
statsCollector.jdbcExecuteStatementEnd(); 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 { try {
statsCollector.jdbcExecuteStatementStart(); statsCollector.jdbcExecuteStatementStart();
return ps.executeQuery(); return ps.executeQuery();
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, sql );
statsCollector.jdbcExecuteStatementEnd(); statsCollector.jdbcExecuteStatementEnd();
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

@ -273,7 +273,7 @@ public class CacheEntityLoaderHelper {
source.getTenantIdentifier() 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(); final StatisticsImplementor statistics = factory.getStatistics();
if ( statistics.isStatisticsEnabled() ) { if ( statistics.isStatisticsEnabled() ) {
if ( ce == null ) { if ( ce == null ) {

View File

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

View File

@ -13,6 +13,8 @@ import java.util.function.Function;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SharedSessionContractImplementor; 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.query.spi.QueryOptions;
import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor; import org.hibernate.resource.jdbc.spi.LogicalConnectionImplementor;
import org.hibernate.sql.exec.spi.ExecutionContext; import org.hibernate.sql.exec.spi.ExecutionContext;
@ -79,12 +81,14 @@ public class StandardJdbcMutationExecutor implements JdbcMutationExecutor {
} }
session.getEventListenerManager().jdbcExecuteStatementStart(); session.getEventListenerManager().jdbcExecuteStatementStart();
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try { try {
int rows = preparedStatement.executeUpdate(); int rows = preparedStatement.executeUpdate();
expectationCheck.accept( rows, preparedStatement ); expectationCheck.accept( rows, preparedStatement );
return rows; return rows;
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, finalSql );
session.getEventListenerManager().jdbcExecuteStatementEnd(); 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.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.engine.spi.Status; 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.PreLoadEvent;
import org.hibernate.event.spi.PreLoadEventListener; import org.hibernate.event.spi.PreLoadEventListener;
import org.hibernate.internal.util.StringHelper; 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 // 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) ) { if ( persistenceContext.wasInsertedDuringTransaction( concreteDescriptor, entityIdentifier) ) {
cacheAccess.update( boolean update = false;
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
try {
update = cacheAccess.update(
session, session,
cacheKey, cacheKey,
concreteDescriptor.getCacheEntryStructure().structure( cacheEntry ), concreteDescriptor.getCacheEntryStructure().structure( cacheEntry ),
@ -985,11 +990,24 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
version version
); );
} }
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cacheAccess,
concreteDescriptor,
update,
JfrEventManager.CacheActionDescription.ENTITY_UPDATE
);
}
}
else { else {
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager(); final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
boolean put = false;
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
try { try {
eventListenerManager.cachePutStart(); eventListenerManager.cachePutStart();
final boolean put = cacheAccess.putFromLoad( put = cacheAccess.putFromLoad(
session, session,
cacheKey, cacheKey,
concreteDescriptor.getCacheEntryStructure().structure( cacheEntry ), concreteDescriptor.getCacheEntryStructure().structure( cacheEntry ),
@ -997,13 +1015,20 @@ public abstract class AbstractEntityInitializer extends AbstractFetchParentAcces
//useMinimalPuts( session, entityEntry ) //useMinimalPuts( session, entityEntry )
false false
); );
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cacheAccess,
concreteDescriptor,
put,
JfrEventManager.CacheActionDescription.ENTITY_LOAD
);
final StatisticsImplementor statistics = factory.getStatistics(); final StatisticsImplementor statistics = factory.getStatistics();
if ( put && statistics.isStatisticsEnabled() ) { if ( put && statistics.isStatisticsEnabled() ) {
statistics.entityCachePut( rootEntityDescriptor.getNavigableRole(), cacheAccess.getRegion().getName() ); statistics.entityCachePut( rootEntityDescriptor.getNavigableRole(), cacheAccess.getRegion().getName() );
} }
}
finally {
eventListenerManager.cachePutEnd(); 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.SessionEventListenerManager;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; 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.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
@ -286,9 +288,11 @@ public class ResultsHelper {
// CollectionRegionAccessStrategy has no update, so avoid putting uncommitted data via putFromLoad // CollectionRegionAccessStrategy has no update, so avoid putting uncommitted data via putFromLoad
if ( isPutFromLoad ) { if ( isPutFromLoad ) {
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager(); final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
final CachePutEvent cachePutEvent = JfrEventManager.beginCachePutEvent();
boolean put = false;
try { try {
eventListenerManager.cachePutStart(); eventListenerManager.cachePutStart();
final boolean put = cacheAccess.putFromLoad( put = cacheAccess.putFromLoad(
session, session,
cacheKey, cacheKey,
collectionDescriptor.getCacheEntryStructure().structure( entry ), collectionDescriptor.getCacheEntryStructure().structure( entry ),
@ -296,6 +300,17 @@ public class ResultsHelper {
factory.getSessionFactoryOptions().isMinimalPutsEnabled() factory.getSessionFactoryOptions().isMinimalPutsEnabled()
&& session.getCacheMode()!= CacheMode.REFRESH && session.getCacheMode()!= CacheMode.REFRESH
); );
}
finally {
JfrEventManager.completeCachePutEvent(
cachePutEvent,
session,
cacheAccess,
collectionDescriptor,
put,
JfrEventManager.CacheActionDescription.COLLECTION_INSERT
);
eventListenerManager.cachePutEnd();
final StatisticsImplementor statistics = factory.getStatistics(); final StatisticsImplementor statistics = factory.getStatistics();
if ( put && statistics.isStatisticsEnabled() ) { if ( put && statistics.isStatisticsEnabled() ) {
@ -304,9 +319,7 @@ public class ResultsHelper {
collectionDescriptor.getCacheAccessStrategy().getRegion().getName() 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.jdbc.spi.SqlStatementLogger;
import org.hibernate.engine.spi.SessionEventListenerManager; import org.hibernate.engine.spi.SessionEventListenerManager;
import org.hibernate.engine.spi.SessionFactoryImplementor; 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.CoreLogging;
import org.hibernate.internal.CoreMessageLogger; import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.query.spi.Limit; import org.hibernate.query.spi.Limit;
@ -235,11 +237,13 @@ public class DeferredResultSetAccess extends AbstractResultSetAccess {
if ( sqlStatementLogger.getLogSlowQuery() > 0 ) { if ( sqlStatementLogger.getLogSlowQuery() > 0 ) {
executeStartNanos = System.nanoTime(); executeStartNanos = System.nanoTime();
} }
final JdbcPreparedStatementExecutionEvent jdbcPreparedStatementExecutionEvent = JfrEventManager.beginJdbcPreparedStatementExecutionEvent();
try { try {
eventListenerManager.jdbcExecuteStatementStart(); eventListenerManager.jdbcExecuteStatementStart();
resultSet = wrapResultSet( preparedStatement.executeQuery() ); resultSet = wrapResultSet( preparedStatement.executeQuery() );
} }
finally { finally {
JfrEventManager.completeJdbcPreparedStatementExecutionEvent( jdbcPreparedStatementExecutionEvent, finalSql );
eventListenerManager.jdbcExecuteStatementEnd(); eventListenerManager.jdbcExecuteStatementEnd();
sqlStatementLogger.logSlowQuery( finalSql, executeStartNanos, context() ); sqlStatementLogger.logSlowQuery( finalSql, executeStartNanos, context() );
} }

View File

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

View File

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

View File

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