#2387 - Hit the L2 bean cache via property IN expression (when property is the id property)

This commit is contained in:
Rob Bygrave
2021-09-23 00:23:23 +12:00
parent c9c61d9f97
commit 477e7eeeda
8 changed files with 101 additions and 24 deletions
@@ -1,6 +1,6 @@
package io.ebeaninternal.api;
import io.ebeaninternal.server.expression.IdInExpression;
import io.ebeaninternal.server.expression.IdInCommon;
import java.util.ArrayList;
import java.util.Collection;
@@ -13,10 +13,10 @@ import java.util.Set;
*/
public final class CacheIdLookupMany<T> implements CacheIdLookup<T> {
private final IdInExpression idInExpression;
private final IdInCommon idInExpression;
private int remaining;
public CacheIdLookupMany(IdInExpression idInExpression) {
public CacheIdLookupMany(IdInCommon idInExpression) {
this.idInExpression = idInExpression;
}
@@ -34,15 +34,12 @@ public final class CacheIdLookupMany<T> implements CacheIdLookup<T> {
*/
@Override
public List<T> removeHits(BeanCacheResult<T> cacheResult) {
Set<Object> hitIds = new HashSet<>();
List<T> beans = new ArrayList<>(hitIds.size());
for (BeanCacheResult.Entry<T> hit : cacheResult.hits()) {
hitIds.add(hit.getKey());
beans.add(hit.getBean());
}
this.remaining = idInExpression.removeIds(hitIds);
return beans;
}
@@ -0,0 +1,20 @@
package io.ebeaninternal.server.expression;
import java.util.Collection;
import java.util.Set;
/**
* Id IN expression common for cache handling.
*/
public interface IdInCommon {
/**
* Return the ids this expression is looking to fetch.
*/
Collection<?> idValues();
/**
* Remove Ids that where obtained from l2 cache. Don't fetch these from DB.
*/
int removeIds(Set<Object> hitIds);
}
@@ -20,7 +20,7 @@ import java.util.Set;
/**
* In a collection of Id values.
*/
public final class IdInExpression extends NonPrepareExpression {
public final class IdInExpression extends NonPrepareExpression implements IdInCommon {
private final List<Object> idCollection;
private boolean multiValueIdSupported;
@@ -29,16 +29,12 @@ public final class IdInExpression extends NonPrepareExpression {
this.idCollection = new ArrayList<>(idCollection);
}
/**
* Return the ids this expression is looking to fetch.
*/
@Override
public Collection<Object> idValues() {
return idCollection;
}
/**
* Remove Ids that where obtained from l2 cache. Don't fetch these from DB.
*/
@Override
public int removeIds(Set<Object> hitIds) {
idCollection.removeAll(hitIds);
return idCollection.size();
@@ -10,13 +10,9 @@ import io.ebeaninternal.server.el.ElPropertyValue;
import io.ebeaninternal.server.persist.MultiValueWrapper;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.*;
final class InExpression extends AbstractExpression {
public final class InExpression extends AbstractExpression implements IdInCommon {
private final boolean not;
@@ -49,6 +45,24 @@ final class InExpression extends AbstractExpression {
this.empty = false;
}
public String property() {
return propName;
}
@Override
public Collection<?> idValues() {
if (bindValues == null) {
bindValues = new ArrayList<>(sourceValues);
}
return bindValues;
}
@Override
public int removeIds(Set<Object> hitIds) {
bindValues.removeAll(hitIds);
return bindValues.size();
}
private List<Object> values() {
if (empty || sourceValues == null) {
return Collections.emptyList();
@@ -56,7 +56,6 @@ public final class CQueryPlanStats {
* Return a Snapshot of the query execution statistics potentially resetting the internal counters.
*/
Snapshot getSnapshot(boolean reset) {
TimedMetricStats collect = timedMetric.collect(reset);
Snapshot snapshot = new Snapshot(collected, queryPlan, collect);
collected = true;
@@ -14,9 +14,7 @@ import io.ebeaninternal.server.autotune.ProfilingListener;
import io.ebeaninternal.server.core.SpiOrmQueryRequest;
import io.ebeaninternal.server.deploy.*;
import io.ebeaninternal.server.el.ElPropertyDeploy;
import io.ebeaninternal.server.expression.DefaultExpressionList;
import io.ebeaninternal.server.expression.IdInExpression;
import io.ebeaninternal.server.expression.SimpleExpression;
import io.ebeaninternal.server.expression.*;
import io.ebeaninternal.server.query.NativeSqlQueryPlanKey;
import io.ebeaninternal.server.rawsql.SpiRawSql;
import io.ebeaninternal.server.transaction.ExternalJdbcTransaction;
@@ -631,6 +629,11 @@ public final class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<
SpiExpression singleExpression = underlyingList.get(0);
if (singleExpression instanceof IdInExpression) {
return new CacheIdLookupMany<>((IdInExpression) singleExpression);
} else if (singleExpression instanceof InExpression) {
InExpression in = (InExpression)singleExpression;
if (in.property().equals(beanDescriptor.idName())) {
return new CacheIdLookupMany<>(in);
}
}
}
return null;