Hi Lukas,
thank you for your answer. I think your approach using
VisitContext.queryParts() should also work for us.
Now to your questions:
- Currently we do not use any MERGE statement within our application. So
I can not say, whether my solution will correctly identify the target table.
- We never execute plain SQL statements - at least for data
manipulation. All statements are composed through the jOOQ-API.
- We also not use any DDL statements. So that is not a use case we have
to care for.
- Well, other processes might exist (at least the cache invalidator is
part of a web application). But to be honest, there might be always some
scenarios that will lead other application parts to work with stale data.
For now the cache invalidator does a good job for us :)
Regards,
Marcus
Am Freitag, 29. Juni 2018 12:21:20 UTC+2 schrieb Marcus Gattinger:
>
> Hi Lukas,
>
> I have seen, that the enumeration org.jooq.Clause has been marked for
> deprecation. I use this enumeration as part of an automatic cache
> invalidation that I've been written.
>
> The cache I've build caches entity instances based of their class and id
> (primary key). Think of a map like this:
> Map<Class<IEntity>, Cache<Integer, IEntity>>
>
> So the cache groups entities of the same class and the id is used to get
> the cached entity instance.
>
> The cache invalidator is registered as VisitListenerProvider on the
> jOOQ-Configuration and uses the following implementation:
>
> import com.google.common.collect.ImmutableMap;
> import com.google.common.collect.ImmutableSet;
> import de.onesense.domain.entity.IEntity;
> import org.jooq.Clause;
> import org.jooq.Table;
> import org.jooq.VisitContext;
> import org.jooq.impl.DefaultVisitListener;
> import org.springframework.stereotype.Component;
>
> import java.util.Arrays;
> import java.util.List;
> import java.util.Map;
> import java.util.Set;
>
> /**
> * A component to invalidate cached entity instances on demand based on
> executed insert, update or delete queries.
> *
> * The cache invalidator is a visit listener that implements Query rendering
> and variable binding lifecycle management in order to allow to implement query
> * transformation or custom query processing.
> */
> @Component
> public class EntityCacheInvalidator extends DefaultVisitListener {
> // The set of query clauses that require a cache invalidation.
> private final static Set<Clause> INVALIDATION_CLAUSES =
> ImmutableSet.of(Clause.DELETE_DELETE, Clause.INSERT_INSERT_INTO,
> Clause.UPDATE_UPDATE);
>
> // The mapping between database tables and domain entity classes.
> private final static Map<String, List<Class<? extends IEntity>>>
> TABLE_MAPPING = ImmutableMap.<String, List<Class<? extends IEntity>>>builder()
> //.put(CLIENT.getName(), ImmutableList.of(Client.class))
> //...
> .build();
>
> // The attached entity cache to trigger invalidation requests.
> private EntityCache entityCache;
>
> /**
> * Creates a new instance of the cache invalidator and attaches it to the
> given entity cache.
> *
> * @param entityCache The entity cache to attach to.
> */
> public EntityCacheInvalidator(final EntityCache entityCache) {
> this.entityCache = entityCache;
> }
>
> @Override
> public void visitEnd(final VisitContext context) {
> if (entityCache == null) {
> return;
> }
>
> // Entity cache must be (partly) invalidated for any query that
> modifies data.
> // The check for empty data is done to prevent multiple cache
> invalidation.
> boolean invalidateCache =
> Arrays.stream(context.clauses()).anyMatch(INVALIDATION_CLAUSES::contains) &&
> context.data().isEmpty();
> if (invalidateCache) {
> // Check whether the current query part refers to a table.
> String tableName = context.queryPart() instanceof Table ?
> ((Table) context.queryPart()).getName() : null;
> if (tableName != null) {
> List<Class<? extends IEntity>> entityClasses =
> TABLE_MAPPING.get(tableName);
> if (entityClasses != null) {
> entityClasses.forEach(entityClass ->
> entityCache.invalidate((Class<IEntity>) entityClass));
> }
> }
> }
> }
> }
>
>
> As you can see, each SQL insert, update or delete statement will be
> analyzed to retrieve all affected tables. Due to the mapping of table to
> entity class we can invalidate the cache in a very targeted manner.
> What options do I have to make this cache invalidation still work even if
> the enumeration org.jooq.Clause is removed in the next major release of
> jOOQ?
>
> Thank you for your help.
>
> Kind regards,
> Marcus
>
--
You received this message because you are subscribed to the Google Groups "jOOQ
User Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.