mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
* Java language level updates concerning Maps. * Reverts when comments indicated no sync can happen.
225 lines
5.6 KiB
Java
225 lines
5.6 KiB
Java
package io.ebeaninternal.server.cache;
|
|
|
|
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.HashSet;
|
|
import java.util.LinkedHashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
/**
|
|
* List of changes to be applied to L2 cache.
|
|
*/
|
|
public class CacheChangeSet {
|
|
|
|
private final List<CacheChange> entries = new ArrayList<>();
|
|
|
|
private final Set<BeanDescriptor<?>> queryCaches = new HashSet<>();
|
|
|
|
private final Map<ManyKey, ManyChange> manyChangeMap = new HashMap<>();
|
|
|
|
/**
|
|
* Set of "base tables" modified used to invalidate entities based on views.
|
|
*/
|
|
private final Set<String> viewInvalidation = new HashSet<>();
|
|
|
|
private final boolean viewEntityInvalidation;
|
|
|
|
/**
|
|
* Construct specifying if we also need to process invalidation for entities based on views.
|
|
*/
|
|
public CacheChangeSet(boolean viewEntityInvalidation) {
|
|
this.viewEntityInvalidation = viewEntityInvalidation;
|
|
}
|
|
|
|
/**
|
|
* Apply the changes to the L2 cache except entity/view invalidation.
|
|
* <p>
|
|
* Return the set of table changes to process invalidation for entities based on views.
|
|
*/
|
|
public Set<String> apply() {
|
|
for (BeanDescriptor<?> entry : queryCaches) {
|
|
entry.clearQueryCache();
|
|
}
|
|
for (CacheChange entry : entries) {
|
|
entry.apply();
|
|
}
|
|
for (CacheChange entry : manyChangeMap.values()) {
|
|
entry.apply();
|
|
}
|
|
return viewInvalidation;
|
|
}
|
|
|
|
/**
|
|
* Add an entry to clear a query cache.
|
|
*/
|
|
public void addClearQuery(BeanDescriptor<?> descriptor) {
|
|
queryCaches.add(descriptor);
|
|
}
|
|
|
|
/**
|
|
* Add many property clear.
|
|
*/
|
|
public <T> void addManyClear(BeanDescriptor<T> desc, String manyProperty) {
|
|
many(desc, manyProperty).setClear();
|
|
}
|
|
|
|
/**
|
|
* Add many property remove.
|
|
*/
|
|
public <T> void addManyRemove(BeanDescriptor<T> desc, String manyProperty, Object parentId) {
|
|
many(desc, manyProperty).addRemove(parentId);
|
|
}
|
|
|
|
/**
|
|
* Add many property put.
|
|
*/
|
|
public <T> void addManyPut(BeanDescriptor<T> desc, String manyProperty, Object parentId, CachedManyIds entry) {
|
|
many(desc, manyProperty).addPut(parentId, entry);
|
|
}
|
|
|
|
/**
|
|
* On bean insert register table for view based entity invalidation.
|
|
*/
|
|
public void addBeanInsert(String baseTable) {
|
|
if (viewEntityInvalidation) {
|
|
viewInvalidation.add(baseTable);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove a bean from the cache.
|
|
*/
|
|
public <T> void addBeanRemove(BeanDescriptor<T> desc, Object id) {
|
|
entries.add(new CacheChangeBeanRemove(desc, id));
|
|
if (viewEntityInvalidation) {
|
|
viewInvalidation.add(desc.getBaseTable());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update a bean entry.
|
|
*/
|
|
public <T> void addBeanUpdate(BeanDescriptor<T> desc, Object id, Map<String, Object> changes, boolean updateNaturalKey, long version) {
|
|
entries.add(new CacheChangeBeanUpdate(desc, id, changes, updateNaturalKey, version));
|
|
if (viewEntityInvalidation) {
|
|
viewInvalidation.add(desc.getBaseTable());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update a natural key.
|
|
*/
|
|
public <T> void addNaturalKeyPut(BeanDescriptor<T> desc, Object id, Object val) {
|
|
entries.add(new CacheChangeNaturalKeyPut(desc, id, val));
|
|
}
|
|
|
|
/**
|
|
* Return the ManyChange for the given descriptor and property manyProperty.
|
|
*/
|
|
private ManyChange many(BeanDescriptor<?> desc, String manyProperty) {
|
|
ManyKey key = new ManyKey(desc, manyProperty);
|
|
ManyChange manyChange = manyChangeMap.computeIfAbsent(key, ManyChange::new);
|
|
return manyChange;
|
|
}
|
|
|
|
/**
|
|
* Changes for a specific many property.
|
|
*/
|
|
private static class ManyChange implements CacheChange {
|
|
|
|
final ManyKey key;
|
|
|
|
final List<Object> removes = new ArrayList<>();
|
|
|
|
final Map<Object, CachedManyIds> puts = new LinkedHashMap<>();
|
|
|
|
boolean clear;
|
|
|
|
ManyChange(ManyKey key) {
|
|
this.key = key;
|
|
}
|
|
|
|
/**
|
|
* Clear all entries.
|
|
*/
|
|
void setClear() {
|
|
this.clear = true;
|
|
removes.clear();
|
|
}
|
|
|
|
/**
|
|
* Remove entry for the given parentId.
|
|
*/
|
|
void addRemove(Object parentId) {
|
|
if (!clear) {
|
|
removes.add(parentId);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Put entry for the given parentId.
|
|
*/
|
|
void addPut(Object parentId, CachedManyIds entry) {
|
|
puts.put(parentId, entry);
|
|
}
|
|
|
|
@Override
|
|
public void apply() {
|
|
if (clear) {
|
|
key.cacheClear();
|
|
} else {
|
|
for (Map.Entry<Object, CachedManyIds> entry : puts.entrySet()) {
|
|
key.cachePut(entry.getKey(), entry.getValue());
|
|
}
|
|
for (Object parentId : removes) {
|
|
key.cacheRemove(parentId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Key for changes on a many property.
|
|
*/
|
|
private static class ManyKey {
|
|
|
|
private final BeanDescriptor<?> desc;
|
|
|
|
private final String manyProperty;
|
|
|
|
ManyKey(BeanDescriptor<?> desc, String manyProperty) {
|
|
this.desc = desc;
|
|
this.manyProperty = manyProperty;
|
|
}
|
|
|
|
@Override
|
|
public boolean equals(Object o) {
|
|
if (this == o) return true;
|
|
if (o == null || getClass() != o.getClass()) return false;
|
|
ManyKey manyKey = (ManyKey) o;
|
|
return desc.equals(manyKey.desc) && manyProperty.equals(manyKey.manyProperty);
|
|
}
|
|
|
|
@Override
|
|
public int hashCode() {
|
|
return 92821 * desc.hashCode() + manyProperty.hashCode();
|
|
}
|
|
|
|
void cacheClear() {
|
|
desc.cacheManyPropClear(manyProperty);
|
|
}
|
|
|
|
void cachePut(Object parentId, CachedManyIds entry) {
|
|
desc.cacheManyPropPut(manyProperty, parentId, entry);
|
|
}
|
|
|
|
void cacheRemove(Object parentId) {
|
|
desc.cacheManyPropRemove(manyProperty, parentId);
|
|
}
|
|
}
|
|
}
|