HHH-11356 - Adjust the 2nd-Cache SPIs to better reflect supported uses
Adding tests on 5.2 branch asserting specific expectations of Cache and Statistics API and SPI to ensure we maintain seamless upgradeability to 5.3 in terms of region name expectations (region-name-prefix handling) * RegionNameTest - old API/SPI methods expected prefixed region name - make sure we continue to support that * ConcurrentStatisticsTest - added cache prefix * RefreshUpdatedDataTest - removed inaccurate assertions
This commit is contained in:
parent
097112353e
commit
0c7e29b4d3
|
@ -7,6 +7,8 @@
|
|||
package org.hibernate.stat.internal;
|
||||
|
||||
import org.hibernate.SessionFactory;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.cfg.Configuration;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
||||
import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase;
|
||||
|
@ -34,6 +36,13 @@ public class ConcurrentStatisticsTest extends BaseCoreFunctionalTestCase {
|
|||
statistics = new ConcurrentStatisticsImpl( (SessionFactoryImplementor) sessionFactory );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(Configuration configuration) {
|
||||
super.configure( configuration );
|
||||
|
||||
configuration.setProperty( AvailableSettings.CACHE_REGION_PREFIX, "my-app" );
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
sessionFactory.close();
|
||||
|
|
|
@ -41,8 +41,6 @@ public class RefreshUpdatedDataTest extends BaseCoreFunctionalTestCase {
|
|||
return new Class[] {
|
||||
ReadWriteCacheableItem.class,
|
||||
ReadWriteVersionedCacheableItem.class,
|
||||
NonStrictReadWriteCacheableItem.class,
|
||||
NonStrictReadWriteVersionedCacheableItem.class,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -77,16 +75,6 @@ public class RefreshUpdatedDataTest extends BaseCoreFunctionalTestCase {
|
|||
readWriteVersionedCacheableItem.getTags().add( "ORM" );
|
||||
s.persist( readWriteVersionedCacheableItem );
|
||||
|
||||
NonStrictReadWriteCacheableItem nonStrictReadWriteCacheableItem = new NonStrictReadWriteCacheableItem( BEFORE );
|
||||
nonStrictReadWriteCacheableItem.getTags().add( "Hibernate" );
|
||||
nonStrictReadWriteCacheableItem.getTags().add( "ORM" );
|
||||
s.persist( nonStrictReadWriteCacheableItem );
|
||||
|
||||
NonStrictReadWriteVersionedCacheableItem nonStrictReadWriteVersionedCacheableItem = new NonStrictReadWriteVersionedCacheableItem( BEFORE );
|
||||
nonStrictReadWriteVersionedCacheableItem.getTags().add( "Hibernate" );
|
||||
nonStrictReadWriteVersionedCacheableItem.getTags().add( "ORM" );
|
||||
s.persist( nonStrictReadWriteVersionedCacheableItem );
|
||||
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
|
||||
|
@ -103,28 +91,14 @@ public class RefreshUpdatedDataTest extends BaseCoreFunctionalTestCase {
|
|||
readWriteVersionedCacheableItem1.setName( AFTER );
|
||||
readWriteVersionedCacheableItem1.getTags().remove("ORM");
|
||||
|
||||
NonStrictReadWriteCacheableItem nonStrictReadWriteCacheableItem1 = s1.get( NonStrictReadWriteCacheableItem.class, nonStrictReadWriteCacheableItem.getId() );
|
||||
nonStrictReadWriteCacheableItem1.setName( AFTER );
|
||||
nonStrictReadWriteCacheableItem1.getTags().remove("ORM");
|
||||
|
||||
NonStrictReadWriteVersionedCacheableItem nonStrictReadWriteVersionedCacheableItem1 = s1.get( NonStrictReadWriteVersionedCacheableItem.class, nonStrictReadWriteVersionedCacheableItem.getId() );
|
||||
nonStrictReadWriteVersionedCacheableItem1.setName( AFTER );
|
||||
nonStrictReadWriteVersionedCacheableItem1.getTags().remove("ORM");
|
||||
|
||||
s1.flush();
|
||||
s1.refresh( readWriteCacheableItem1 );
|
||||
s1.refresh( readWriteVersionedCacheableItem1 );
|
||||
s1.refresh( nonStrictReadWriteCacheableItem1 );
|
||||
s1.refresh( nonStrictReadWriteVersionedCacheableItem1 );
|
||||
|
||||
assertEquals( AFTER, readWriteCacheableItem1.getName() );
|
||||
assertEquals( 1, readWriteCacheableItem1.getTags().size() );
|
||||
assertEquals( AFTER, readWriteVersionedCacheableItem1.getName() );
|
||||
assertEquals( 1, readWriteVersionedCacheableItem1.getTags().size() );
|
||||
assertEquals( AFTER, nonStrictReadWriteCacheableItem1.getName() );
|
||||
assertEquals( 1, nonStrictReadWriteCacheableItem1.getTags().size() );
|
||||
assertEquals( AFTER, nonStrictReadWriteVersionedCacheableItem1.getName() );
|
||||
assertEquals( 1, nonStrictReadWriteVersionedCacheableItem1.getTags().size() );
|
||||
|
||||
// open another session
|
||||
Session s2 = sessionFactory().openSession();
|
||||
|
@ -132,21 +106,12 @@ public class RefreshUpdatedDataTest extends BaseCoreFunctionalTestCase {
|
|||
s2.beginTransaction();
|
||||
ReadWriteCacheableItem readWriteCacheableItem2 = s2.get( ReadWriteCacheableItem.class, readWriteCacheableItem.getId() );
|
||||
ReadWriteVersionedCacheableItem readWriteVersionedCacheableItem2 = s2.get( ReadWriteVersionedCacheableItem.class, readWriteVersionedCacheableItem.getId() );
|
||||
NonStrictReadWriteCacheableItem nonStrictReadWriteCacheableItem2 = s2.get( NonStrictReadWriteCacheableItem.class, nonStrictReadWriteCacheableItem.getId() );
|
||||
NonStrictReadWriteVersionedCacheableItem nonStrictReadWriteVersionedCacheableItem2 = s2.get( NonStrictReadWriteVersionedCacheableItem.class, nonStrictReadWriteVersionedCacheableItem.getId() );
|
||||
|
||||
assertEquals( BEFORE, readWriteCacheableItem2.getName() );
|
||||
assertEquals( 2, readWriteCacheableItem2.getTags().size() );
|
||||
assertEquals( BEFORE, readWriteVersionedCacheableItem2.getName() );
|
||||
assertEquals( 2, readWriteVersionedCacheableItem2.getTags().size() );
|
||||
|
||||
//READ_UNCOMMITTED because there is no locking to prevent collections from being cached in the first Session
|
||||
|
||||
assertEquals( BEFORE, nonStrictReadWriteCacheableItem2.getName() );
|
||||
assertEquals( 1, nonStrictReadWriteCacheableItem2.getTags().size());
|
||||
assertEquals( BEFORE, nonStrictReadWriteVersionedCacheableItem2.getName() );
|
||||
assertEquals( 1, nonStrictReadWriteVersionedCacheableItem2.getTags().size() );
|
||||
|
||||
s2.getTransaction().commit();
|
||||
}
|
||||
finally {
|
||||
|
@ -163,8 +128,6 @@ public class RefreshUpdatedDataTest extends BaseCoreFunctionalTestCase {
|
|||
s.beginTransaction();
|
||||
s.delete( readWriteCacheableItem );
|
||||
s.delete( readWriteVersionedCacheableItem );
|
||||
s.delete( nonStrictReadWriteCacheableItem );
|
||||
s.delete( nonStrictReadWriteVersionedCacheableItem );
|
||||
s.getTransaction().commit();
|
||||
s.close();
|
||||
}
|
||||
|
@ -255,91 +218,4 @@ public class RefreshUpdatedDataTest extends BaseCoreFunctionalTestCase {
|
|||
return tags;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "NonStrictReadWriteCacheableItem")
|
||||
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region = "item")
|
||||
public static class NonStrictReadWriteCacheableItem {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
|
||||
@ElementCollection
|
||||
private List<String> tags = new ArrayList<>();
|
||||
|
||||
public NonStrictReadWriteCacheableItem() {
|
||||
}
|
||||
|
||||
public NonStrictReadWriteCacheableItem(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
}
|
||||
|
||||
@Entity(name = "NonStrictReadWriteVersionedCacheableItem")
|
||||
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region = "item")
|
||||
public static class NonStrictReadWriteVersionedCacheableItem {
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
|
||||
@ElementCollection
|
||||
private List<String> tags = new ArrayList<>();
|
||||
|
||||
@Version
|
||||
private int version;
|
||||
|
||||
public NonStrictReadWriteVersionedCacheableItem() {
|
||||
}
|
||||
|
||||
public NonStrictReadWriteVersionedCacheableItem(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public List<String> getTags() {
|
||||
return tags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ import org.hibernate.annotations.NaturalIdCache;
|
|||
import org.hibernate.boot.MetadataSources;
|
||||
import org.hibernate.cfg.AvailableSettings;
|
||||
import org.hibernate.engine.spi.CacheImplementor;
|
||||
import org.hibernate.internal.util.compare.EqualsHelper;
|
||||
import org.hibernate.stat.NaturalIdCacheStatistics;
|
||||
import org.hibernate.stat.SecondLevelCacheStatistics;
|
||||
import org.hibernate.stat.Statistics;
|
||||
|
@ -29,6 +30,9 @@ import org.hibernate.stat.spi.StatisticsImplementor;
|
|||
import org.hibernate.testing.junit4.BaseNonConfigCoreFunctionalTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
/**
|
||||
* Test API and SPI expectation wrt region names - whether they expect the
|
||||
* prefixed or un-prefixed name
|
||||
|
@ -43,11 +47,13 @@ public class RegionNameTest extends BaseNonConfigCoreFunctionalTestCase {
|
|||
}
|
||||
|
||||
private final String cachePrefix = "app1";
|
||||
private final String localName = "a.b.c";
|
||||
|
||||
@Override
|
||||
protected void addSettings(Map settings) {
|
||||
super.addSettings( settings );
|
||||
settings.put( AvailableSettings.USE_SECOND_LEVEL_CACHE, "true" );
|
||||
settings.put( AvailableSettings.USE_QUERY_CACHE, "true" );
|
||||
settings.put( AvailableSettings.CACHE_REGION_PREFIX, cachePrefix );
|
||||
settings.put( AvailableSettings.GENERATE_STATISTICS, "true" );
|
||||
settings.put( AvailableSettings.HBM2DDL_AUTO, "create-drop" );
|
||||
|
@ -57,10 +63,9 @@ public class RegionNameTest extends BaseNonConfigCoreFunctionalTestCase {
|
|||
// todo (6.0) : same ^^, maintain API compatibility
|
||||
|
||||
@Test
|
||||
public void testStatsApi() {
|
||||
//this needs to be the prefixed name :(
|
||||
//final String regionName = "a.b.c";
|
||||
final String regionName = cachePrefix + ".a.b.c";
|
||||
public void testLegacyStatsApi() {
|
||||
// these references need to be the prefixed name
|
||||
final String regionName = cachePrefix + '.' + localName;
|
||||
|
||||
final Statistics stats = sessionFactory().getStatistics();
|
||||
|
||||
|
@ -75,12 +80,12 @@ public class RegionNameTest extends BaseNonConfigCoreFunctionalTestCase {
|
|||
// todo (6.0) : same ^^, maintain API compatibility
|
||||
|
||||
@Test
|
||||
public void testStatsSpi() {
|
||||
//this needs to be the prefixed name :(
|
||||
//final String regionName = "a.b.c";
|
||||
final String regionName = cachePrefix + ".a.b.c";
|
||||
public void testLegacyStatsSpi() {
|
||||
// these need to be the prefixed name
|
||||
final String regionName = cachePrefix + '.' + localName;
|
||||
|
||||
final StatisticsImplementor statistics = sessionFactory().getStatistics();
|
||||
statistics.clear();
|
||||
|
||||
statistics.naturalIdCacheHit( regionName );
|
||||
statistics.naturalIdCacheMiss( regionName );
|
||||
|
@ -90,36 +95,56 @@ public class RegionNameTest extends BaseNonConfigCoreFunctionalTestCase {
|
|||
statistics.secondLevelCacheMiss( regionName );
|
||||
statistics.secondLevelCachePut( regionName );
|
||||
|
||||
statistics.getNaturalIdCacheStatistics( regionName );
|
||||
|
||||
// stats for queries cannot be accessed second level cache regions map
|
||||
// final String queryString = "select p from Person p";
|
||||
// final String queryCacheRegionName = "x.y.z";
|
||||
//
|
||||
// inTransaction(
|
||||
// session -> session.createQuery( queryString ).setCacheable( true ).setCacheRegion( queryCacheRegionName ).list()
|
||||
// );
|
||||
// // note that
|
||||
// statistics.queryCacheHit( "select ...", queryCacheRegionName );
|
||||
// statistics.queryCacheMiss( "select ...", queryCacheRegionName );
|
||||
// statistics.queryCachePut( "select ...", queryCacheRegionName );
|
||||
final String queryString = "select p from Person p";
|
||||
final String queryCacheRegionName = "x.y.z";
|
||||
final String prefixedQueryCacheRegionName = cachePrefix + '.' + queryCacheRegionName;
|
||||
|
||||
inTransaction(
|
||||
// Only way to generate query region (to be accessible via stats) is to execute the query
|
||||
session -> session.createQuery( queryString ).setCacheable( true ).setCacheRegion( queryCacheRegionName ).list()
|
||||
);
|
||||
|
||||
final SecondLevelCacheStatistics queryCacheStats = statistics.getSecondLevelCacheStatistics( regionName );
|
||||
assert queryCacheStats != null;
|
||||
|
||||
// note that
|
||||
statistics.queryCacheHit( queryString, prefixedQueryCacheRegionName );
|
||||
statistics.queryCacheMiss( queryString, prefixedQueryCacheRegionName );
|
||||
statistics.queryCachePut( queryString, prefixedQueryCacheRegionName );
|
||||
|
||||
// sessionFactory().getCache().evictQueryRegions();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheSpi() {
|
||||
//this needs to be the prefixed name :(
|
||||
//final String regionName = "a.b.c";
|
||||
final String regionName = cachePrefix + ".a.b.c";
|
||||
public void testLegacyCacheSpi() {
|
||||
// these need to be the prefixed name
|
||||
final String regionName = cachePrefix + '.' + localName;
|
||||
|
||||
final CacheImplementor cache = sessionFactory().getCache();
|
||||
|
||||
// just like stats, the cache for queries cannot be accessed second level cache regions map
|
||||
assert cache.getSecondLevelCacheRegionNames().length == 1;
|
||||
assert cache.getSecondLevelCacheRegionNames()[0].equals( regionName );
|
||||
assertEquals( 2, cache.getSecondLevelCacheRegionNames().length );
|
||||
|
||||
boolean foundRegion = false;
|
||||
for ( String name : cache.getSecondLevelCacheRegionNames() ) {
|
||||
if ( EqualsHelper.areEqual( name, regionName ) ) {
|
||||
foundRegion = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !foundRegion ) {
|
||||
fail( "Could not find region [" + regionName + "] in reported list of region names" );
|
||||
}
|
||||
assert cache.getEntityRegionAccess( regionName ) != null;
|
||||
assert cache.getNaturalIdCacheRegionAccessStrategy( regionName ) != null;
|
||||
assert cache.getCollectionRegionAccess(regionName ) != null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Entity( name = "Person" )
|
||||
@Table( name = "persons" )
|
||||
@Cacheable
|
||||
|
|
Loading…
Reference in New Issue