Hi Marcus,

Thanks a lot for your feedback. I'm glad to hear that
VisitContext.queryParts() works for you. One less reason not to eventually
abandon org.jooq.Clause :)

Great to hear that there seems little risk of your solution breaking. Btw,
are you using PostgreSQL or Oracle, perhaps? There are some messaging
capabilities in those databases that could be used to help invalidate
caches as well. I've made good experience with Oracle AQ for that purpose,
in the past. PostgreSQL has NOTIFY. Of course, such a message system might
turn out to be a bit too chatty.

Another option could be to use a log miner, such as Debezium or Golden
Gate, etc.

Thanks,
Lukas

Am Do., 5. Juli 2018 um 16:29 Uhr schrieb Marcus Gattinger <[email protected]
>:

> 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.
>

-- 
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.

Reply via email to