/*
* 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.spring;
import lombok.extern.slf4j.Slf4j;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cache.redis.hibernate4.util.HibernateCacheUtil;
import org.hibernate.cache.redis.jpa.models.Account;
import org.hibernate.cache.redis.jpa.models.Item;
import org.hibernate.cache.redis.jpa.models.Person;
import org.hibernate.stat.SecondLevelCacheStatistics;
import org.hibernate.stat.Statistics;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
@Slf4j
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {HibernateRedisConfiguration.class})
public class SpringHibernateTest {
@Autowired
SessionFactory sf;
@Before
public void setup() {
assertThat(sf).isNotNull();
sf.getStatistics().setStatisticsEnabled(true);
sf.getStatistics().clear();
}
public SecondLevelCacheStatistics getSecondLevelCacheStatistics(Class clazz) {
String regionName = HibernateCacheUtil.getRegionName(sf, clazz);
log.debug("class={}, region={}", clazz.getSimpleName(), regionName);
return sf.getStatistics().getSecondLevelCacheStatistics(regionName);
}
@Test
public void emptySecondLevelCacheEntry() throws Exception {
sf.getCache().evictEntityRegion(Item.class);
Statistics stats = sf.getStatistics();
stats.clear();
String regionName = HibernateCacheUtil.getRegionName(sf, Item.class);
assertThat(regionName).isNotEmpty();
log.debug("Item region name={}", regionName);
SecondLevelCacheStatistics slcs = getSecondLevelCacheStatistics(Item.class);
log.debug("Region name={}, Element in memory={}, hit count={}",
regionName, slcs.getElementCountInMemory(), slcs.getHitCount());
assertThat(regionName).contains("common");
assertThat(slcs.getElementCountInMemory()).isEqualTo(0);
assertThat(slcs.getHitCount()).isEqualTo(0);
}
@Test
public void queryCacheInvalidation() throws Exception {
sf.getCache().evictEntityRegion(Item.class);
Session s = sf.openSession();
Transaction tx = s.beginTransaction();
Item item = Item.of("Widget", "A realy top-quality, full-featured widget.");
s.persist(item);
tx.commit();
s.close();
SecondLevelCacheStatistics slcs = getSecondLevelCacheStatistics(Item.class);
log.info(slcs.toString());
s = sf.openSession();
Item loaded = (Item) s.get(Item.class, item.getId());
assertThat(loaded).isNotNull();
s.close();
log.info(slcs.toString());
assertThat(slcs.getPutCount()).isEqualTo(1);
assertThat(slcs.getElementCountInMemory()).isEqualTo(1);
}
@Test
public void simpleEntityCaching() throws Exception {
sf.getCache().evictEntityRegion(Item.class);
SecondLevelCacheStatistics slcs = getSecondLevelCacheStatistics(Item.class);
Session session;
log.debug("Item Save - #1");
Item item = new Item();
item.setName("redis");
item.setDescription("redis cache item");
session = sf.openSession();
session.save(item);
session.flush();
session.close();
log.debug("Item Read - #1");
session = sf.openSession();
Item loaded = (Item) session.get(Item.class, item.getId());
assertThat(loaded).isNotNull();
session.close();
log.info(slcs.toString());
log.debug("put count={}, element in memory={}", slcs.getPutCount(), slcs.getElementCountInMemory());
assertThat(slcs.getPutCount()).isEqualTo(1);
assertThat(slcs.getElementCountInMemory()).isEqualTo(1);
log.debug("Item Update - #1");
session = sf.openSession();
// session.merge(loaded);
loaded.setDescription("Update description...");
session.saveOrUpdate(loaded);
session.flush();
session.close();
log.debug("Item Read - #2");
session = sf.openSession();
loaded = (Item) session.get(Item.class, loaded.getId());
assertThat(loaded).isNotNull();
assertThat(loaded.getId()).isEqualTo(item.getId());
assertThat(loaded.getDescription()).isNotEqualTo(item.getDescription());
session.close();
log.debug("Item Read - #3");
session = sf.openSession();
loaded = (Item) session.get(Item.class, loaded.getId());
assertThat(loaded).isNotNull();
assertThat(loaded.getId()).isEqualTo(item.getId());
assertThat(loaded.getDescription()).isNotEqualTo(item.getDescription());
session.close();
log.debug("Item Read - #4");
session = sf.openSession();
loaded = (Item) session.get(Item.class, loaded.getId());
assertThat(loaded).isNotNull();
assertThat(loaded.getId()).isEqualTo(item.getId());
assertThat(loaded.getDescription()).isNotEqualTo(item.getDescription());
session.close();
log.info(slcs.toString());
log.debug("put count={}, element in memory={}", slcs.getPutCount(), slcs.getElementCountInMemory());
assertThat(slcs.getPutCount()).isEqualTo(2); // update
assertThat(slcs.getElementCountInMemory()).isEqualTo(1);
}
@Test
public void hqlLoad() throws Exception {
sf.getCache().evictEntityRegion(Item.class);
SecondLevelCacheStatistics slcs = getSecondLevelCacheStatistics(Item.class);
Session session;
log.debug("Item Save - #1");
Item item = Item.of("redis", "redis cache item");
session = sf.openSession();
session.save(item);
session.flush();
session.close();
log.debug("Item Read - #1");
session = sf.openSession();
Query query = session.createQuery("select e from Item e where e.id=:id").setParameter("id", item.getId()).setCacheable(true);
Item loaded = (Item) query.uniqueResult();
assertThat(loaded).isNotNull();
session.close();
log.debug("Item Read - #2");
session = sf.openSession();
query = session.createQuery("select e from Item e where e.id=:id").setParameter("id", item.getId()).setCacheable(true);
loaded = (Item) query.uniqueResult();
assertThat(loaded).isNotNull();
session.close();
log.debug("Item Read - #3");
session = sf.openSession();
loaded = (Item) session.get(Item.class, item.getId());
assertThat(loaded).isNotNull();
session.close();
log.debug("Item Read - #4");
session = sf.openSession();
query = session.createQuery("select e from Item e where e.id=:id").setParameter("id", item.getId()).setCacheable(true);
loaded = (Item) query.uniqueResult();
assertThat(loaded).isNotNull();
session.close();
}
@Test
public void nonrestrictCaching() throws Exception {
sf.getCache().evictEntityRegion(Account.class);
sf.getCache().evictEntityRegion(Person.class);
SecondLevelCacheStatistics slcs = getSecondLevelCacheStatistics(Account.class);
SecondLevelCacheStatistics slcs2 = getSecondLevelCacheStatistics(Person.class);
Session session = sf.openSession();
Person person = new Person();
person.setAge(40);
person.setFirstname("Bae");
person.setLastname("Sunghyouk");
session.save(person);
Account account = new Account();
account.setPerson(person);
session.save(account);
session.flush();
session.close();
session = sf.openSession();
Account acc = (Account) session.get(Account.class, account.getId());
assertThat(acc).isNotNull();
assertThat(acc.getPerson()).isNotNull();
session.close();
log.info("Account:[{}]", slcs.toString());
assertThat(slcs.getPutCount()).isEqualTo(1);
assertThat(slcs.getElementCountInMemory()).isEqualTo(1);
log.info("Person:[{}]", slcs2.toString());
assertThat(slcs2.getPutCount()).isEqualTo(1);
assertThat(slcs2.getElementCountInMemory()).isEqualTo(1);
session = sf.openSession();
acc = (Account) session.get(Account.class, account.getId());
assertThat(acc).isNotNull();
assertThat(acc.getPerson()).isNotNull();
session.close();
log.info("Account:[{}]", slcs.toString());
assertThat(slcs.getPutCount()).isEqualTo(1);
assertThat(slcs.getElementCountInMemory()).isEqualTo(1);
log.info("Person:[{}]", slcs2.toString());
assertThat(slcs2.getPutCount()).isEqualTo(1);
assertThat(slcs2.getElementCountInMemory()).isEqualTo(1);
}
@Test
public void massiveCaching() throws Exception {
sf.getCache().evictEntityRegion(Item.class);
Session session = sf.openSession();
Transaction tx = session.beginTransaction();
int count = 100;
for (int i = 0; i < count; i++) {
Item item = new Item();
item.setName("redis - " + i);
item.setDescription("redis cache item - " + i);
session.save(item);
}
tx.commit();
session.close();
session = sf.openSession();
tx = session.beginTransaction();
List<Item> items = (List<Item>) session.createCriteria(Item.class).list();
assertThat(items.size()).isEqualTo(count);
items = (List<Item>) session.createCriteria(Item.class).list();
for (Item item : items) {
session.update(item);
}
tx.commit();
session.close();
SecondLevelCacheStatistics slcs = getSecondLevelCacheStatistics(Item.class);
log.info(slcs.toString());
assertThat(slcs.getPutCount()).isEqualTo(count);
assertThat(slcs.getElementCountInMemory()).isEqualTo(count);
session = sf.openSession();
tx = session.beginTransaction();
items = (List<Item>) session.createCriteria(Item.class).list();
for (Item item : items) {
item.getName();
}
tx.commit();
session.close();
session = sf.openSession();
tx = session.beginTransaction();
items = (List<Item>) session.createCriteria(Item.class).list();
for (Item item : items) {
session.delete(item);
}
tx.commit();
session.flush();
session.close();
}
}