我在JPA 2.1 Hibernate EHCache 上。
這是我的命名查詢(查詢代碼不相關):
List<MyEntity> list = getEntityManager()
.createNamedQuery("my-query-id", MyEntity.class))
.setHint(QueryHints.CACHEABLE, true)
.setHint(QueryHints.CACHE_REGION, "my-query-region")
.setParameter("my-query-param", "my-param-value")
.setMaxResults(1)
.getResultList();
if (list.isEmpty()) {
log.warn("No data found.");
return null;
}
return list;
我希望實作的目標是僅在結果非空時才快取查詢結果。
我敢肯定,因為我通過跟蹤級別的休眠日志記錄檢查了它,無論如何都會快取該空結果集。
任何建議將不勝感激。
問候!
uj5u.com熱心網友回復:
我通過撰寫一個EHCache 裝飾器找到了一個解決方案,如下所示:
EHCache XML 配置片段
<cache name="my-queries-region"
maxEntriesLocalHeap="50000"
eternal="false"
timeToLiveSeconds="14400">
<persistence strategy="none"/>
<!-- https://www.ehcache.org/ehcache.xml -->
<cacheDecoratorFactory
class="com.example.JpaCacheDecoratorNotEmptyQueryFactory" />
</cache>
裝飾工廠實作
package com.example;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.constructs.CacheDecoratorFactory;
import java.util.Properties;
public class JpaCacheDecoratorNotEmptyQueryFactory extends CacheDecoratorFactory {
@Override
public Ehcache createDecoratedEhcache(Ehcache cache, Properties properties) {
return new JpaCacheDecoratorNotEmptyQueryDecorator(cache);
}
@Override
public Ehcache createDefaultDecoratedEhcache(Ehcache cache, Properties properties) {
return new JpaCacheDecoratorNotEmptyQueryDecorator(cache);
}
}
裝飾器實作
package com.example;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.sf.ehcache.CacheException;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import net.sf.ehcache.constructs.EhcacheDecoratorAdapter;
import org.hibernate.cache.internal.QueryResultsCacheImpl;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.List;
@Slf4j
public class JpaCacheDecoratorNotEmptyQueryDecorator extends EhcacheDecoratorAdapter {
private final Field resultsField;
@SneakyThrows
@SuppressWarnings("rawtypes")
protected boolean canCache(Element element) {
boolean cacheable = true;
Object value = element.getObjectValue();
if (value instanceof QueryResultsCacheImpl.CacheItem) {
List results = (List)resultsField.get(value);
cacheable = !results.isEmpty();
}
if (!cacheable) {
if (log.isDebugEnabled()) {
log.debug("Query not cacheable due to empty result set.");
}
}
return cacheable;
}
protected boolean canCache(Collection<Element> elements) {
for (Element element: elements) {
if (!canCache(element)) {
return false;
}
}
return true;
}
@SneakyThrows
public JpaCacheDecoratorNotEmptyQueryDecorator(Ehcache underlyingCache) {
super(underlyingCache);
resultsField = QueryResultsCacheImpl
.CacheItem
.class
.getDeclaredField("results");
resultsField.setAccessible(true);
}
@Override
public void put(Element element, boolean doNotNotifyCacheReplicators)
throws IllegalArgumentException,
IllegalStateException,
CacheException
{
if (canCache(element)) {
super.put(element, doNotNotifyCacheReplicators);
}
}
@Override
public void put(Element element)
throws IllegalArgumentException,
IllegalStateException,
CacheException
{
if (canCache(element)) {
super.put(element);
}
}
@Override
public void putAll(Collection<Element> elements)
throws IllegalArgumentException,
IllegalStateException,
CacheException
{
if (canCache(elements)) {
super.putAll(elements);
}
}
@Override
public void putQuiet(Element element)
throws IllegalArgumentException,
IllegalStateException,
CacheException
{
if (canCache(element)) {
super.putQuiet(element);
}
}
@Override
public void putWithWriter(Element element)
throws IllegalArgumentException,
IllegalStateException,
CacheException
{
if (canCache(element)) {
super.putWithWriter(element);
}
}
@Override
public Element putIfAbsent(Element element)
throws NullPointerException
{
if (canCache(element)) {
return super.putIfAbsent(element);
} else {
return null;
}
}
@Override
public Element putIfAbsent(Element element, boolean doNotNotifyCacheReplicators)
throws NullPointerException
{
if (canCache(element)) {
return super.putIfAbsent(element, doNotNotifyCacheReplicators);
} else {
return null;
}
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/329693.html
上一篇:HQL-COALESCE或CASEonLEFTJOIN
下一篇:事務提交后休眠不保存物體
