/* * Copyright (c) 2017. Sunghyouk Bae <sunghyouk.bae@gmail.com> * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package org.hibernate.cache.redis.hibernate52; import lombok.extern.slf4j.Slf4j; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; import org.hibernate.cache.redis.hibernate52.models.HibernateItem; import org.hibernate.cache.redis.hibernate52.models.VersionedHibernateItem; import org.hibernate.cache.redis.hibernate52.strategy.AbstractReadWriteRedisAccessStrategy; import org.hibernate.cache.redis.hibernate52.util.HibernateCacheUtil; import org.hibernate.cache.spi.access.AccessType; import org.hibernate.cfg.Configuration; import org.hibernate.resource.transaction.backend.jta.internal.JtaTransactionCoordinatorBuilderImpl; import org.hibernate.stat.SecondLevelCacheStatistics; import org.hibernate.stat.Statistics; import org.hibernate.testing.junit4.BaseCoreFunctionalTestCase; import org.junit.Test; import java.util.Map; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.fail; import static org.hibernate.cfg.Environment.*; @Slf4j public abstract class AbstractHibernateCacheTest extends BaseCoreFunctionalTestCase { protected static final String ABSTRACT_READ_WRITE_REDIS_ACCESS_STRATEGY_CLASS_NAME = AbstractReadWriteRedisAccessStrategy.class.getName(); protected static final String HIBERNATE_ITEM_CLASS_NAME = ABSTRACT_READ_WRITE_REDIS_ACCESS_STRATEGY_CLASS_NAME + "$HibernateItem"; @Override protected Class<?>[] getAnnotatedClasses() { return new Class<?>[]{ HibernateItem.class, VersionedHibernateItem.class }; } @Override protected String getCacheConcurrencyStrategy() { return AccessType.READ_WRITE.getExternalName(); } @Override protected void configure(Configuration cfg) { super.configure(cfg); cfg.setProperty(CACHE_REGION_PREFIX, "hibernate"); cfg.setProperty(USE_SECOND_LEVEL_CACHE, "true"); cfg.setProperty(USE_QUERY_CACHE, "true"); cfg.setProperty(GENERATE_STATISTICS, "true"); cfg.setProperty(USE_STRUCTURED_CACHE, "true"); cfg.setProperty(TRANSACTION_COORDINATOR_STRATEGY, JtaTransactionCoordinatorBuilderImpl.class.getName()); configCache(cfg); } protected abstract void configCache(final Configuration cfg); protected abstract Map getMapFromCacheEntry(final Object entry); @Test public void queryCacheInvalidation() { Session s = openSession(); Transaction t = s.beginTransaction(); HibernateItem item = new HibernateItem(); item.setName("widget"); item.setDescription("A really top-quality, full-featured widget"); s.persist(item); t.commit(); s.clear(); String regionName = HibernateCacheUtil.getRegionName(sessionFactory(), HibernateItem.class); assertThat(regionName).isNotEmpty(); log.debug("HibernateItem regionName={}", regionName); SecondLevelCacheStatistics slcs = sessionFactory().getStatistics() .getSecondLevelCacheStatistics(regionName); // FIXME : HibernateItem Region Name 이 지정한 값이 아닌 class name 으로 나온다. Why??? //assertThat(slcs.getElementCountInMemory()).isGreaterThan(0); s = openSession(); t = s.beginTransaction(); HibernateItem loaded = (HibernateItem) s.get(HibernateItem.class, item.getId()); assertThat(loaded).isNotNull(); assertThat(loaded.getId()).isEqualTo(item.getId()); assertThat(loaded.getName()).isEqualTo(item.getName()); assertThat(loaded.getDescription()).isEqualTo(item.getDescription()); loaded.setDescription("A blog standard item"); t.commit(); s.close(); s = openSession(); t = s.beginTransaction(); s.delete(item); t.commit(); s.close(); } @Test public void emptySecondLevelCacheEntry() throws Exception { SessionFactory sf = sessionFactory(); sf.getCache().evictEntityRegion(HibernateItem.class.getName()); Statistics stats = sf.getStatistics(); String regionName = HibernateCacheUtil.getRegionName(sf, HibernateItem.class); log.debug("regionName={}", regionName); assertThat(regionName).isNotEmpty(); stats.clear(); SecondLevelCacheStatistics slcs = stats.getSecondLevelCacheStatistics(regionName); Map cacheEntries = slcs.getEntries(); assertThat(cacheEntries).isNotNull().isEmpty(); } @SuppressWarnings("all") @Test public void staleWritesLeaveCacheConsistent() { Session session = openSession(); Transaction tx = session.beginTransaction(); VersionedHibernateItem vitem = new VersionedHibernateItem(); vitem.setName("steve"); vitem.setDescription("steve's item"); session.save(vitem); tx.commit(); session.close(); Long initialVersion = vitem.getVersion(); // manually revert the version property vitem.setVersion(Long.valueOf(vitem.getVersion().longValue() - 1L)); try { session = openSession(); tx = session.beginTransaction(); session.update(vitem); tx.commit(); session.close(); fail("expected stale write to fail!!!"); } catch (Exception expected) { if (tx != null) { try { tx.rollback(); } catch (Exception ignored) { } } } finally { if (session != null && session.isOpen()) { try { session.close(); } catch (Exception ignored) { } } } // check the version value in the cache... String regionName = HibernateCacheUtil.getRegionName(sessionFactory(), VersionedHibernateItem.class); log.debug("VersionedHibernateItem's regionName={}", regionName); assertThat(regionName).isNotEmpty(); SecondLevelCacheStatistics slcs = sessionFactory().getStatistics() .getSecondLevelCacheStatistics(regionName); // Map cacheEntries = slcs.getEntries(); // Object entry = cacheEntries.get(vitem.getId()); // log.debug("entry=[{}]", entry); Long cachedVersionValue; // final String lockStr = AbstractReadWriteRedisAccessStrategy.class.getName() + "$Lock"; // boolean isLock = entry.getClass() // .getName() // .equals(lockStr); // // if (isLock) { // // // } else { // cachedVersionValue = (Long) getMapFromCacheEntry(entry).get("_version"); // assertThat(cachedVersionValue.longValue()).isEqualTo(initialVersion.longValue()); // } // clean up session = openSession(); tx = session.beginTransaction(); VersionedHibernateItem loaded = (VersionedHibernateItem) session.load(VersionedHibernateItem.class, vitem.getId()); assertThat(loaded).isNotNull(); session.delete(loaded); tx.commit(); session.close(); } }