package org.hibernate.test.cache; import static org.hamcrest.CoreMatchers.equalTo; import static org.junit.Assert.assertThat; import static org.junit.Assert.fail; import java.util.Date; import java.util.List; import java.util.Map; import org.hamcrest.CoreMatchers; import org.hibernate.Session; import org.hibernate.Transaction; import org.hibernate.cache.ehcache.internal.strategy.ItemValueExtractor; import org.hibernate.cache.spi.access.SoftLock; import org.hibernate.cfg.Configuration; import org.hibernate.stat.QueryStatistics; import org.hibernate.stat.SecondLevelCacheStatistics; import org.hibernate.stat.Statistics; import org.hibernate.test.domain.Event; import org.hibernate.test.domain.EventManager; import org.hibernate.test.domain.Item; import org.hibernate.test.domain.Person; import org.hibernate.test.domain.PhoneNumber; import org.hibernate.test.domain.VersionedItem; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; /** * @author Chris Dennis * @author Brett Meyer */ public class HibernateCacheTest extends BaseCoreFunctionalTestCase { private static final String REGION_PREFIX = "hibernate.test."; @Override protected void configure(Configuration config) { System.setProperty( "derby.system.home", "target/derby" ); config.configure( "hibernate-config/hibernate.cfg.xml" ); } @Override protected void afterSessionFactoryBuilt() { sessionFactory().getStatistics().setStatisticsEnabled( true ); } @Test public void testQueryCacheInvalidation() throws Exception { Session s = sessionFactory().openSession(); Transaction t = s.beginTransaction(); Item i = new Item(); i.setName( "widget" ); i.setDescription( "A really top-quality, full-featured widget." ); s.persist( i ); t.commit(); s.close(); SecondLevelCacheStatistics slcs = sessionFactory() .getStatistics() .getSecondLevelCacheStatistics( REGION_PREFIX + Item.class.getName() ); assertThat( slcs.getPutCount(), equalTo( 1L ) ); assertThat( slcs.getElementCountInMemory(), equalTo( 1L ) ); assertThat( slcs.getEntries().size(), equalTo( 1 ) ); s = sessionFactory().openSession(); t = s.beginTransaction(); i = (Item) s.get( Item.class, i.getId() ); assertThat( slcs.getHitCount(), equalTo( 1L ) ); assertThat( slcs.getMissCount(), equalTo( 0L ) ); i.setDescription( "A bog standard item" ); t.commit(); s.close(); assertThat( slcs.getPutCount(), equalTo( 2L ) ); Object entry = slcs.getEntries().get( i.getId() ); Map map; if ( entry instanceof Map ) { map = (Map) entry; } else { map = ItemValueExtractor.getValue( entry ); } assertThat( (String) map.get( "description" ), equalTo( "A bog standard item" ) ); assertThat( (String) map.get( "name" ), equalTo( "widget" ) ); // cleanup s = sessionFactory().openSession(); t = s.beginTransaction(); s.delete( i ); t.commit(); s.close(); } @Test public void testEmptySecondLevelCacheEntry() throws Exception { sessionFactory().evictEntity( Item.class.getName() ); Statistics stats = sessionFactory().getStatistics(); stats.clear(); SecondLevelCacheStatistics statistics = stats.getSecondLevelCacheStatistics( REGION_PREFIX + Item.class.getName() ); Map cacheEntries = statistics.getEntries(); assertThat( cacheEntries.size(), equalTo( 0 ) ); } @Test public void testStaleWritesLeaveCacheConsistent() { Session s = sessionFactory().openSession(); Transaction txn = s.beginTransaction(); VersionedItem item = new VersionedItem(); item.setName( "steve" ); item.setDescription( "steve's item" ); s.save( item ); txn.commit(); s.close(); Long initialVersion = item.getVersion(); // manually revert the version property item.setVersion( item.getVersion() - 1 ); try { s = sessionFactory().openSession(); txn = s.beginTransaction(); s.update( item ); txn.commit(); s.close(); fail( "expected stale write to fail" ); } catch ( Throwable expected ) { // expected behavior here if ( txn != null ) { try { txn.rollback(); } catch ( Throwable ignore ) { } } } finally { if ( s != null && s.isOpen() ) { try { s.close(); } catch ( Throwable ignore ) { } } } // check the version value in the cache... SecondLevelCacheStatistics slcs = sessionFactory().getStatistics() .getSecondLevelCacheStatistics( REGION_PREFIX + VersionedItem.class.getName() ); assertThat( slcs, CoreMatchers.<Object>notNullValue() ); final Map entries = slcs.getEntries(); Object entry = entries.get( item.getId() ); Long cachedVersionValue; if ( entry instanceof SoftLock ) { //FIXME don't know what to test here //cachedVersionValue = new Long( ( (ReadWriteCache.Lock) entry).getUnlockTimestamp() ); } else { cachedVersionValue = (Long) ( (Map) entry ).get( "_version" ); assertThat( initialVersion, equalTo( cachedVersionValue ) ); } // cleanup s = sessionFactory().openSession(); txn = s.beginTransaction(); item = (VersionedItem) s.load( VersionedItem.class, item.getId() ); s.delete( item ); txn.commit(); s.close(); } @Test public void testGeneralUsage() { EventManager mgr = new EventManager( sessionFactory() ); Statistics stats = sessionFactory().getStatistics(); // create 3 persons Steve, Orion, Tim Person stevePerson = new Person(); stevePerson.setFirstname( "Steve" ); stevePerson.setLastname( "Harris" ); Long steveId = mgr.createAndStorePerson( stevePerson ); mgr.addEmailToPerson( steveId, "steve@tc.com" ); mgr.addEmailToPerson( steveId, "sharrif@tc.com" ); mgr.addTalismanToPerson( steveId, "rabbit foot" ); mgr.addTalismanToPerson( steveId, "john de conqueroo" ); PhoneNumber p1 = new PhoneNumber(); p1.setNumberType( "Office" ); p1.setPhone( 111111 ); mgr.addPhoneNumberToPerson( steveId, p1 ); PhoneNumber p2 = new PhoneNumber(); p2.setNumberType( "Home" ); p2.setPhone( 222222 ); mgr.addPhoneNumberToPerson( steveId, p2 ); Person orionPerson = new Person(); orionPerson.setFirstname( "Orion" ); orionPerson.setLastname( "Letizi" ); Long orionId = mgr.createAndStorePerson( orionPerson ); mgr.addEmailToPerson( orionId, "orion@tc.com" ); mgr.addTalismanToPerson( orionId, "voodoo doll" ); Long timId = mgr.createAndStorePerson( "Tim", "Teck" ); mgr.addEmailToPerson( timId, "teck@tc.com" ); mgr.addTalismanToPerson( timId, "magic decoder ring" ); Long engMeetingId = mgr.createAndStoreEvent( "Eng Meeting", stevePerson, new Date() ); mgr.addPersonToEvent( steveId, engMeetingId ); mgr.addPersonToEvent( orionId, engMeetingId ); mgr.addPersonToEvent( timId, engMeetingId ); Long docMeetingId = mgr.createAndStoreEvent( "Doc Meeting", orionPerson, new Date() ); mgr.addPersonToEvent( steveId, docMeetingId ); mgr.addPersonToEvent( orionId, docMeetingId ); for ( Event event : (List<Event>) mgr.listEvents() ) { mgr.listEmailsOfEvent( event.getId() ); } QueryStatistics queryStats = stats.getQueryStatistics( "from Event" ); assertThat( "Cache Miss Count", queryStats.getCacheMissCount(), equalTo( 1L ) ); assertThat( "Cache Hit Count", queryStats.getCacheHitCount(), equalTo( 0L ) ); assertThat( "Cache Put Count", queryStats.getCachePutCount(), equalTo( 1L ) ); } }