Skip to content

Commit 2d28b90

Browse files
committed
maintain statistics on removal from the second-level cache
1 parent 84ab8be commit 2d28b90

File tree

8 files changed

+83
-6
lines changed

8 files changed

+83
-6
lines changed

hibernate-core/src/main/java/org/hibernate/action/internal/EntityDeleteAction.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.hibernate.event.spi.PreDeleteEventListener;
2424
import org.hibernate.metamodel.mapping.NaturalIdMapping;
2525
import org.hibernate.persister.entity.EntityPersister;
26+
import org.hibernate.stat.internal.StatsHelper;
2627
import org.hibernate.stat.spi.StatisticsImplementor;
2728

2829
/**
@@ -297,6 +298,14 @@ protected void removeCacheItem(Object ck) {
297298
final EntityPersister persister = getPersister();
298299
if ( persister.canWriteToCache() ) {
299300
persister.getCacheAccessStrategy().remove( getSession(), ck );
301+
302+
final StatisticsImplementor statistics = getSession().getFactory().getStatistics();
303+
if ( statistics.isStatisticsEnabled() ) {
304+
statistics.entityCacheRemove(
305+
StatsHelper.getRootEntityRole( persister ),
306+
getPersister().getCacheAccessStrategy().getRegion().getName()
307+
);
308+
}
300309
}
301310
}
302311
}

hibernate-core/src/main/java/org/hibernate/stat/CacheRegionStatistics.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ public interface CacheRegionStatistics extends Serializable {
3939
*/
4040
long getMissCount();
4141

42+
/**
43+
* The number of removals since the last Statistics clearing
44+
*/
45+
long getRemoveCount();
46+
4247
/**
4348
* The number of elements currently in memory within the cache provider.
4449
* <p>

hibernate-core/src/main/java/org/hibernate/stat/CacheableDataStatistics.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,10 @@ public interface CacheableDataStatistics extends Serializable {
3636
* configured cache region since the last Statistics clearing
3737
*/
3838
long getCacheMissCount();
39+
40+
/**
41+
* The number of evictions from the configured cache region since
42+
* the last Statistics clearing
43+
*/
44+
long getCacheRemoveCount();
3945
}

hibernate-core/src/main/java/org/hibernate/stat/internal/AbstractCacheableDataStatistics.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ public abstract class AbstractCacheableDataStatistics implements CacheableDataSt
2121
private final @Nullable LongAdder cacheHitCount;
2222
private final @Nullable LongAdder cacheMissCount;
2323
private final @Nullable LongAdder cachePutCount;
24+
private final @Nullable LongAdder cacheRemoveCount;
2425

2526
public AbstractCacheableDataStatistics(Supplier<@Nullable Region> regionSupplier) {
2627
final Region region = regionSupplier.get();
@@ -29,12 +30,14 @@ public AbstractCacheableDataStatistics(Supplier<@Nullable Region> regionSupplier
2930
this.cacheHitCount = null;
3031
this.cacheMissCount = null;
3132
this.cachePutCount = null;
33+
this.cacheRemoveCount = null;
3234
}
3335
else {
3436
this.cacheRegionName = region.getName();
3537
this.cacheHitCount = new LongAdder();
3638
this.cacheMissCount = new LongAdder();
3739
this.cachePutCount = new LongAdder();
40+
this.cacheRemoveCount = new LongAdder();
3841
}
3942
}
4043

@@ -43,6 +46,7 @@ public AbstractCacheableDataStatistics(Supplier<@Nullable Region> regionSupplier
4346
return cacheRegionName;
4447
}
4548

49+
@Override
4650
public long getCacheHitCount() {
4751
if ( cacheRegionName == null ) {
4852
return NOT_CACHED_COUNT;
@@ -51,6 +55,7 @@ public long getCacheHitCount() {
5155
return NullnessUtil.castNonNull( cacheHitCount ).sum();
5256
}
5357

58+
@Override
5459
public long getCachePutCount() {
5560
if ( cacheRegionName == null ) {
5661
return NOT_CACHED_COUNT;
@@ -59,6 +64,7 @@ public long getCachePutCount() {
5964
return NullnessUtil.castNonNull( cachePutCount ).sum();
6065
}
6166

67+
@Override
6268
public long getCacheMissCount() {
6369
if ( cacheRegionName == null ) {
6470
return NOT_CACHED_COUNT;
@@ -67,6 +73,15 @@ public long getCacheMissCount() {
6773
return NullnessUtil.castNonNull( cacheMissCount ).sum();
6874
}
6975

76+
@Override
77+
public long getCacheRemoveCount() {
78+
if ( cacheRegionName == null ) {
79+
return NOT_CACHED_COUNT;
80+
}
81+
82+
return NullnessUtil.castNonNull( cacheRemoveCount ).sum();
83+
}
84+
7085
public void incrementCacheHitCount() {
7186
if ( cacheRegionName == null ) {
7287
throw new IllegalStateException( "Illegal attempt to increment cache hit count for non-cached data" );
@@ -91,6 +106,14 @@ public void incrementCachePutCount() {
91106
NullnessUtil.castNonNull( cachePutCount ).increment();
92107
}
93108

109+
public void incrementCacheRemoveCount() {
110+
if ( cacheRegionName == null ) {
111+
throw new IllegalStateException( "Illegal attempt to increment cache put count for non-cached data" );
112+
}
113+
114+
NullnessUtil.castNonNull( cacheRemoveCount ).increment();
115+
}
116+
94117
protected void appendCacheStats(StringBuilder buf) {
95118
buf.append( ",cacheRegion=" ).append( cacheRegionName );
96119

@@ -100,7 +123,8 @@ protected void appendCacheStats(StringBuilder buf) {
100123

101124
buf.append( ",cacheHitCount=" ).append( getCacheHitCount() )
102125
.append( ",cacheMissCount=" ).append( getCacheMissCount() )
103-
.append( ",cachePutCount=" ).append( getCachePutCount() );
126+
.append( ",cachePutCount=" ).append( getCachePutCount() )
127+
.append( ",cacheRemoveCount=" ).append( getCacheRemoveCount() );
104128

105129
}
106130
}

hibernate-core/src/main/java/org/hibernate/stat/internal/CacheRegionStatisticsImpl.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ public class CacheRegionStatisticsImpl implements CacheRegionStatistics, Seriali
2222
private final LongAdder hitCount = new LongAdder();
2323
private final LongAdder missCount = new LongAdder();
2424
private final LongAdder putCount = new LongAdder();
25+
private final LongAdder removeCount = new LongAdder();
2526

2627
CacheRegionStatisticsImpl(Region region) {
2728
this.region = region;
@@ -47,6 +48,11 @@ public long getPutCount() {
4748
return putCount.sum();
4849
}
4950

51+
@Override
52+
public long getRemoveCount() {
53+
return removeCount.sum();
54+
}
55+
5056
@Override
5157
public long getElementCountInMemory() {
5258
return region instanceof ExtendedStatisticsSupport extended
@@ -80,13 +86,19 @@ void incrementPutCount() {
8086
putCount.increment();
8187
}
8288

89+
90+
public void incrementRemoveCount() {
91+
removeCount.increment();
92+
}
93+
8394
@Override
8495
public String toString() {
8596
String buf = "CacheRegionStatistics" +
8697
"[region=" + region.getName() +
8798
",hitCount=" + this.hitCount +
8899
",missCount=" + this.missCount +
89100
",putCount=" + this.putCount +
101+
",removeCount=" + this.removeCount +
90102
",elementCountInMemory=" + this.getElementCountInMemory() +
91103
",elementCountOnDisk=" + this.getElementCountOnDisk() +
92104
",sizeInMemory=" + this.getSizeInMemory() +

hibernate-core/src/main/java/org/hibernate/stat/internal/StatisticsImpl.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,13 @@ public void entityCacheMiss(NavigableRole entityName, String regionName) {
355355
getEntityStatistics( entityName.getFullPath() ).incrementCacheMissCount();
356356
}
357357

358+
@Override
359+
public void entityCacheRemove(NavigableRole entityName, String regionName) {
360+
secondLevelCacheMissCount.increment();
361+
getDomainDataRegionStatistics( regionName ).incrementRemoveCount();
362+
getEntityStatistics( entityName.getFullPath() ).incrementCacheRemoveCount();
363+
}
364+
358365

359366
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
360367
// Collection stats

hibernate-core/src/main/java/org/hibernate/stat/spi/StatisticsImplementor.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,24 +148,31 @@ public interface StatisticsImplementor extends Statistics, Service {
148148
/**
149149
* Callback indicating a put into second level cache.
150150
*
151-
* @apiNote `entityName` should be the root entity name
151+
* @apiNote {@code entityName} should be the root entity name
152152
*/
153153
void entityCachePut(NavigableRole entityName, String regionName);
154154

155155
/**
156156
* Callback indicating a get from second level cache resulted in a hit.
157157
*
158-
* @apiNote `entityName` should be the root entity name
158+
* @apiNote {@code entityName} should be the root entity name
159159
*/
160160
void entityCacheHit(NavigableRole entityName, String regionName);
161161

162162
/**
163163
* Callback indicating a get from second level cache resulted in a miss.
164164
*
165-
* @apiNote `entityName` should be the root entity name
165+
* @apiNote {@code entityName} should be the root entity name
166166
*/
167167
void entityCacheMiss(NavigableRole entityName, String regionName);
168168

169+
/**
170+
* Callback indicating a removal from second level cache.
171+
*
172+
* @apiNote {@code entityName} should be the root entity name
173+
*/
174+
void entityCacheRemove(NavigableRole rootEntityRole, String name);
175+
169176
/**
170177
* Callback indicating a put into second level cache.
171178
*

hibernate-core/src/test/java/org/hibernate/orm/test/ondeletecascade/OnDeleteCascadeRemoveTest.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*/
55
package org.hibernate.orm.test.ondeletecascade;
66

7+
import jakarta.persistence.Cacheable;
78
import jakarta.persistence.CascadeType;
89
import jakarta.persistence.Entity;
910
import jakarta.persistence.Id;
@@ -15,6 +16,7 @@
1516
import org.hibernate.annotations.OnDeleteAction;
1617
import org.hibernate.annotations.SQLDelete;
1718
import org.hibernate.engine.spi.SessionImplementor;
19+
import org.hibernate.stat.EntityStatistics;
1820
import org.hibernate.stat.Statistics;
1921
import org.hibernate.testing.orm.junit.EntityManagerFactoryScope;
2022
import org.hibernate.testing.orm.junit.Jpa;
@@ -54,7 +56,9 @@ void testOnDeleteCascadeRemove1(EntityManagerFactoryScope scope) {
5456
// note: ideally we would skip the initialization here
5557
assertTrue( Hibernate.isInitialized( parent.children ) );
5658
});
57-
assertEquals( 1L,statistics.getEntityStatistics(Child.class.getName()).getDeleteCount() );
59+
EntityStatistics entityStatistics = statistics.getEntityStatistics( Child.class.getName() );
60+
assertEquals( 1L, entityStatistics.getDeleteCount() );
61+
assertEquals( 1L, entityStatistics.getCacheRemoveCount() );
5862
assertEquals( 5, scope.getCollectingStatementInspector().getSqlQueries().size() );
5963
long children =
6064
scope.fromTransaction( em -> em.createQuery( "select count(*) from CascadeChild", Long.class )
@@ -86,7 +90,9 @@ void testOnDeleteCascadeRemove2(EntityManagerFactoryScope scope) {
8690
.getEntry( parent.children.iterator().next() )
8791
.getStatus().isDeletedOrGone() );
8892
});
89-
assertEquals( 1L, statistics.getEntityStatistics(Child.class.getName()).getDeleteCount() );
93+
EntityStatistics entityStatistics = statistics.getEntityStatistics( Child.class.getName() );
94+
assertEquals( 1L, entityStatistics.getDeleteCount() );
95+
assertEquals( 1L, entityStatistics.getCacheRemoveCount() );
9096
assertEquals( 5, scope.getCollectingStatementInspector().getSqlQueries().size() );
9197
long children =
9298
scope.fromTransaction( em -> em.createQuery( "select count(*) from CascadeChild", Long.class )
@@ -104,6 +110,7 @@ static class Parent {
104110
Set<Child> children = new HashSet<>();
105111
}
106112
@Entity(name="CascadeChild")
113+
@Cacheable
107114
@SQLDelete( sql = "should never happen" )
108115
static class Child {
109116
@Id

0 commit comments

Comments
 (0)