HHH-17984 StatelessSession statistics for collections

Signed-off-by: Gavin King <gavin@hibernate.org>
This commit is contained in:
Gavin King 2024-04-21 15:51:01 +02:00
parent 62132594eb
commit 8df8fd37be
2 changed files with 78 additions and 18 deletions

View File

@ -151,7 +151,13 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
}
persister.setIdentifier( entity, id, this );
forEachOwnedCollection( entity, id, persister,
(descriptor, collection) -> descriptor.recreate( collection, id, this) );
(descriptor, collection) -> {
descriptor.recreate( collection, id, this);
final StatisticsImplementor statistics = getFactory().getStatistics();
if ( statistics.isStatisticsEnabled() ) {
statistics.recreateCollection( descriptor.getRole() );
}
} );
firePostInsert(entity, id, state, persister);
final StatisticsImplementor statistics = getFactory().getStatistics();
if ( statistics.isStatisticsEnabled() ) {
@ -178,7 +184,13 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
getInterceptor()
.onDelete( entity, id, persister.getPropertyNames(), persister.getPropertyTypes() );
forEachOwnedCollection( entity, id, persister,
(descriptor, collection) -> descriptor.remove(id, this) );
(descriptor, collection) -> {
descriptor.remove( id, this );
final StatisticsImplementor statistics = getFactory().getStatistics();
if ( statistics.isStatisticsEnabled() ) {
statistics.removeCollection( descriptor.getRole() );
}
} );
persister.getDeleteCoordinator().delete( entity, id, version, this );
firePostDelete(entity, id, persister);
final StatisticsImplementor statistics = getFactory().getStatistics();
@ -223,11 +235,16 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
getInterceptor()
.onUpdate( entity, id, state, persister.getPropertyNames(), persister.getPropertyTypes() );
persister.getUpdateCoordinator().update( entity, id, null, state, oldVersion, null, null, false, this );
// TODO: can we do better here?
forEachOwnedCollection( entity, id, persister,
(descriptor, collection) -> descriptor.remove(id, this) );
forEachOwnedCollection( entity, id, persister,
(descriptor, collection) -> descriptor.recreate( collection, id, this) );
(descriptor, collection) -> {
// TODO: can we do better here?
descriptor.remove( id, this );
descriptor.recreate( collection, id, this );
final StatisticsImplementor statistics = getFactory().getStatistics();
if ( statistics.isStatisticsEnabled() ) {
statistics.updateCollection( descriptor.getRole() );
}
} );
firePostUpdate(entity, id, state, persister);
final StatisticsImplementor statistics = getFactory().getStatistics();
if ( statistics.isStatisticsEnabled() ) {
@ -247,11 +264,17 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
.onUpsert( entity, id, state, persister.getPropertyNames(), persister.getPropertyTypes() );
final Object oldVersion = versionToUpsert( entity, persister, state );
persister.getMergeCoordinator().update( entity, id, null, state, oldVersion, null, null, false, this );
// TODO: can we do better here?
// TODO: statistics for upsert!
forEachOwnedCollection( entity, id, persister,
(descriptor, collection) -> descriptor.remove(id, this) );
forEachOwnedCollection( entity, id, persister,
(descriptor, collection) -> descriptor.recreate( collection, id, this) );
(descriptor, collection) -> {
// TODO: can we do better here?
descriptor.remove( id, this );
descriptor.recreate( collection, id, this );
final StatisticsImplementor statistics = getFactory().getStatistics();
if ( statistics.isStatisticsEnabled() ) {
statistics.updateCollection( descriptor.getRole() );
}
} );
firePostUpsert(entity, id, state, persister);
}
}
@ -562,11 +585,10 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
if ( LOG.isTraceEnabled() ) {
LOG.trace( "Collection initialized" );
}
//TODO: statistics!
// final StatisticsImplementor statistics = getFactory().getStatistics();
// if ( statistics.isStatisticsEnabled() ) {
// statistics.fetchCollection( loadedPersister.getRole() );
// }
final StatisticsImplementor statistics = getFactory().getStatistics();
if ( statistics.isStatisticsEnabled() ) {
statistics.fetchCollection( loadedPersister.getRole() );
}
}
}
@ -710,6 +732,7 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
proxyInterceptor.setSession( this );
try {
proxyInterceptor.forceInitialize( association, null );
// TODO: statistics?? call statistics.fetchEntity()
}
finally {
proxyInterceptor.unsetSession();
@ -731,6 +754,10 @@ public class StatelessSessionImpl extends AbstractSharedSessionContract implemen
collectionDescriptor.initialize( key, this );
handlePotentiallyEmptyCollection( persistentCollection, getPersistenceContextInternal(), key,
collectionDescriptor );
final StatisticsImplementor statistics = getFactory().getStatistics();
if ( statistics.isStatisticsEnabled() ) {
statistics.fetchCollection( collectionDescriptor.getRole() );
}
}
finally {
persistentCollection.unsetSession( this );

View File

@ -1,7 +1,9 @@
package org.hibernate.orm.test.stateless;
import jakarta.persistence.Basic;
import jakarta.persistence.ElementCollection;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.Id;
import org.hibernate.stat.spi.StatisticsImplementor;
@ -12,7 +14,12 @@ import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.hibernate.testing.orm.junit.Setting;
import org.junit.jupiter.api.Test;
import java.util.ArrayList;
import java.util.List;
import static org.hibernate.cfg.StatisticsSettings.GENERATE_STATISTICS;
import static org.hibernate.graph.GraphSemantic.FETCH;
import static org.hibernate.graph.GraphSemantic.LOAD;
import static org.junit.jupiter.api.Assertions.assertEquals;
@SessionFactory
@ -28,25 +35,51 @@ public class StatelessSessionStatisticsTest {
assertEquals(0, statistics.getEntityLoadCount());
Person person = new Person();
person.name = "Gavin";
person.handles.add("@1ovthafew");
scope.inStatelessTransaction(s -> s.insert(person));
assertEquals(1, statistics.getEntityInsertCount());
assertEquals(1, statistics.getCollectionRecreateCount());
scope.inStatelessSession(s -> s.get(Person.class, person.id));
assertEquals(1, statistics.getEntityLoadCount());
assertEquals(0, statistics.getEntityFetchCount());
assertEquals(1, statistics.getCollectionLoadCount());
assertEquals(0, statistics.getCollectionFetchCount());
person.name = "Gavin King";
scope.inStatelessTransaction(s -> s.update(person));
assertEquals(1, statistics.getEntityUpdateCount());
scope.inStatelessSession(s -> s.get(Person.class, person.id));
assertEquals(1, statistics.getCollectionUpdateCount());
scope.inStatelessSession(s -> s.get(s.createEntityGraph(Person.class), LOAD, person.id));
assertEquals(2, statistics.getEntityLoadCount());
assertEquals(2, statistics.getCollectionLoadCount());
assertEquals(0, statistics.getCollectionFetchCount());
scope.inStatelessSession(s -> s.get(s.createEntityGraph(Person.class), FETCH, person.id));
assertEquals(3, statistics.getEntityLoadCount());
assertEquals(2, statistics.getCollectionLoadCount());
assertEquals(0, statistics.getCollectionFetchCount());
scope.inStatelessSession(s -> s.fetch(s.get(s.createEntityGraph(Person.class), FETCH, person.id).handles));
assertEquals(4, statistics.getEntityLoadCount());
assertEquals(3, statistics.getCollectionLoadCount());
assertEquals(1, statistics.getCollectionFetchCount());
scope.inStatelessSession(s -> s.createQuery("from Person", Person.class).getSingleResult());
assertEquals(5, statistics.getEntityLoadCount());
assertEquals(4, statistics.getCollectionLoadCount());
assertEquals(2, statistics.getCollectionFetchCount());
person.handles.add("hello world");
scope.inStatelessTransaction(s -> s.upsert(person));
assertEquals(2, statistics.getCollectionUpdateCount());
scope.inStatelessTransaction(s -> s.delete(person));
assertEquals(1, statistics.getEntityDeleteCount());
assertEquals(3, statistics.getTransactionCount());
assertEquals(1, statistics.getCollectionRemoveCount());
assertEquals(4, statistics.getTransactionCount());
}
@Entity(name="Entity")
@Entity(name="Person")
static class Person {
@Id @GeneratedValue
long id;
@Basic(optional = false)
String name;
@ElementCollection(fetch = FetchType.EAGER)
List<String> handles = new ArrayList<>();
}
}