Hi Marcus,
Thank you very much for taking the time to explain your use-case, which I
have linked from this issue:
https://github.com/jOOQ/jOOQ/issues/7642

Neither the Clause nor the VisitListener are going to be removed any time
soon. At this stage, I want to get feedback on all currently implemented
use-cases around the VisitListener, to get it right in a second go. For
example, jOOQ 4.0 (no release date planned yet) should work on immutable
QueryPart types, in case of which it might be easier to open them up to the
public API. In case of which clauses might not really be needed.

Unfortunately, the java.lang.Deprecated annotation doesn't allow to
indicate what the deprecation means, at this point, it just means that
Clause, as it is now, is not going to be implemented further (e.g. for new
DDL statements). But in your case, you're not in a hurry to replace your
implementation.

The caching use-case is a very interesting one. For example:

- Is there never going to be a MERGE statement on that table?
- What about plain SQL statements? Do you parse those using jOOQ's parser,
to trigger VisitListener behaviour?
- What about DDL on those tables?
- Are there no other processes writing to the tables?

Also, do you really need the Clause in your case? I mean, you could just
check out the VisitContext.queryParts() path and look for tables inside of
org.jooq.Insert, org.jooq.Update, org.jooq.Delete types. Consider this
logic:

DSL.using(new DefaultConfiguration().set(new DefaultVisitListener() {
    @Override
    public void visitStart(VisitContext context) {
        Stream.of(context.queryParts())
              .map(Object::getClass)
              .forEach(System.out::println);

        System.out.println();
    }

})).delete(table("b")).where("1 = 0").getSQL();


It prints:

class org.jooq.impl.DeleteQueryImpl

class org.jooq.impl.DeleteQueryImpl
class org.jooq.impl.KeywordImpl

class org.jooq.impl.DeleteQueryImpl
class org.jooq.impl.KeywordImpl

class org.jooq.impl.DeleteQueryImpl
class org.jooq.impl.SQLTable <-- look out for this table inside of the
org.jooq.Delete type

class org.jooq.impl.DeleteQueryImpl
class org.jooq.impl.SQLTable
class org.jooq.impl.SQLImpl

class org.jooq.impl.DeleteQueryImpl
class org.jooq.impl.KeywordImpl

class org.jooq.impl.DeleteQueryImpl
class org.jooq.impl.SQLCondition

class org.jooq.impl.DeleteQueryImpl
class org.jooq.impl.SQLCondition
class org.jooq.impl.SQLImpl


Does that work for you?

Am Fr., 29. Juni 2018 um 12:21 Uhr schrieb Marcus Gattinger <
[email protected]>:

> 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