AurélienThank you for your time. I would be very happy to have a Jooq cache layer working :)What would you do to provide a way to easily cache a query ?I would prefer to use the first solution. However, if you specified the fetch() method as final in the AbstractResultQuery class, I think you had a reason. So it would be wrong to just override the AbstractResultQuery class to remove the final keyword.- the second solution is to provide methods like fetchCached(Select query): List<User>. This way I have to hack though the query with Java reflection to get the from table names.- adding selectFromCached(Table) and selectCached(Fields) methods. It would returned a slightly modified SelectImpl. However, the delegate class (currently SelectQueryImpl), will be replaced. This way I can get the table names with the getFrom() method and I can override the fetch() method from AbstractResultQuery to be able to either execute the query or return the cached result. Wait, the fetch() method is final, it cannot be overridden :'(. I have to directly override the AbstractResultQuery class to remove the final modifier :/.I have found two ways to cache a query result in the dao :- identify the table names used in the query (to be able to clear the cache for the query when any of the tables used in the query are being updated).- concatenate all the query parameters to create the cache entry : DSLContext.extractBindValues(query),- identify the query : DSLContext.renderNamedParams(query),Now comes the problematic part. I want to provide a way to cache any queries with possibly Joins. To cache a query like that, I need to :- the possibility to cache a query result,- a useCache() method overridable (default implementation returns false),Now the real layer : CachedDAOImpl class. This class should inherit the original DAOImpl class. It should add :- UserPojo and UserTable rename. It enables to easily distinct each generated classes. I don't like having many public classes with the same name in a project.- One time generation of the User and UserDao classes. It enables to extend the generated AbstractUserDao and UserPojo classes.To summarize, I want to change two things from the original Jooq codegen :BaseName.java (remain the same)Tables.java (remain the same)Keys.java (remain the same)UserTable.java (only the class name change, I want to distinct the "real" User object from the generated ones)UserRecord.java (remain the same)recordsUserPojo.java (only the class name change, I want to distinct the "real" User object from the generated ones)pojosIUser.java (remain the same)interfacesAbstractUserDao.java (public abstract class AbstractUserDao<T extends UserPojo> extends CachedDAOImpl<UserRecord, T, Long>)Let's start with the code generation. I want for a table named "user" to generate this hierarchy :I want to create a cache layer on top of Jooq. For now, I only have thought on how I want the cache layer to behave and how it should connect to Jooq. I would like to have your opinion on the layer "architecture". Moreover I would like to have an advice on how I could extract the table names used in a Jooq query : I have found 2 solutions, but none of them are satisfactory.Hi Lukas,
beansUser.java (extends UserPojo, generated only if the file does not exist)
daosUserDao.java (extends AbstractUserDao<User>, generated only if the file does not exist)generated
tabledaos
- the clearCache() method.If the useCache() method returns true, all "simple" accesses should be cached, ie fetchById and fetchOneByUniqueField. The cache properties (maxSize, expire etc) should be parametrized in the application, but it could be good to be able to override the default cache properties in the Dao. Anyway, when an object is cached with fetchById, the cache is clean for the id "k", if the row with the id "k" is updated or removed (works only if the delete, or update methods are called from the Dao). That part is easy.
PS: About caching, I am well aware that too much caching kills the cache system. An application cache system should be set up only if the application really needs it. However, caching DB query results is often a very simple way to increase the application execution speed.
- UserPojo and UserTable rename. It enables to easily distinct each generated classes. I don't like having many public classes with the same name in a project.- One time generation of the User and UserDao classes. It enables to extend the generated AbstractUserDao and UserPojo classes.To summarize, I want to change two things from the original Jooq codegen :BaseName.java (remain the same)Tables.java (remain the same)Keys.java (remain the same)UserTable.java (only the class name change, I want to distinct the "real" User object from the generated ones)UserRecord.java (remain the same)recordsUserPojo.java (only the class name change, I want to distinct the "real" User object from the generated ones)pojosIUser.java (remain the same)interfacesAbstractUserDao.java (public abstract class AbstractUserDao<T extends UserPojo> extends CachedDAOImpl<UserRecord, T, Long>)Let's start with the code generation. I want for a table named "user" to generate this hierarchy :I want to create a cache layer on top of Jooq. For now, I only have thought on how I want the cache layer to behave and how it should connect to Jooq. I would like to have your opinion on the layer "architecture". Moreover I would like to have an advice on how I could extract the table names used in a Jooq query : I have found 2 solutions, but none of them are satisfactory.Hi Lukas,
beansUser.java (extends UserPojo, generated only if the file does not exist)
daosUserDao.java (extends AbstractUserDao<User>, generated only if the file does not exist)generated
tabledaos
- the possibility to cache a query result,Now the real layer : CachedDAOImpl class. This class should inherit the original DAOImpl class. It should add :- a useCache() method overridable (default implementation returns false),
- the clearCache() method.If the useCache() method returns true, all "simple" accesses should be cached, ie fetchById and fetchOneByUniqueField. The cache properties (maxSize, expire etc) should be parametrized in the application, but it could be good to be able to override the default cache properties in the Dao. Anyway, when an object is cached with fetchById, the cache is clean for the id "k", if the row with the id "k" is updated or removed (works only if the delete, or update methods are called from the Dao). That part is easy.
- concatenate all the query parameters to create the cache entry : DSLContext.extractBindValues(query),- identify the query : DSLContext.renderNamedParams(query),Now comes the problematic part. I want to provide a way to cache any queries with possibly Joins. To cache a query like that, I need to :
- identify the table names used in the query (to be able to clear the cache for the query when any of the tables used in the query are being updated).
I have found two ways to cache a query result in the dao :- adding selectFromCached(Table) and selectCached(Fields) methods. It would returned a slightly modified SelectImpl. However, the delegate class (currently SelectQueryImpl), will be replaced. This way I can get the table names with the getFrom() method and I can override the fetch() method from AbstractResultQuery to be able to either execute the query or return the cached result. Wait, the fetch() method is final, it cannot be overridden :'(. I have to directly override the AbstractResultQuery class to remove the final modifier :/.
I would prefer to use the first solution. However, if you specified the fetch() method as final in the AbstractResultQuery class, I think you had a reason.- the second solution is to provide methods like fetchCached(Select query): List<User>. This way I have to hack though the query with Java reflection to get the from table names.
So it would be wrong to just override the AbstractResultQuery class to remove the final keyword.
What would you do to provide a way to easily cache a query ?
AurélienThank you for your time. I would be very happy to have a Jooq cache layer working :)
PS: About caching, I am well aware that too much caching kills the cache system. An application cache system should be set up only if the application really needs it. However, caching DB query results is often a very simple way to increase the application execution speed.
--
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 jooq-user+...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
Hey Lukas,
Thank you for your quick answer !
I'll take your advice and try to write a cache close to jdbc, your solution with jOOQ MockConnection seems promising.
I will also wait for the new SQL rendering and variable binding SPI to enable the cache to be correctly cleared.
As soon as I have something working, I will share it here !
--
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 jooq-user+...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to a topic in the Google Groups "jOOQ User Group" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/jooq-user/xSjrvnmcDHw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to jooq-user+...@googlegroups.com.
Hi Lukas,The issue is on my side, and i need some advice on how to resolve it. I am currently using Jooq with Dropwizard.So the jooq configuration is created at app launch and then injected into my services, so the configuration is global across the app.Now introducing the caching layer i have to include MockDataProviderOriginal jooq connectionDSLContext create = DSL.using(configuration)
Jooq with cachingconfiguration.set(new DefaultVisitListenerProvider(new CacheVisitListener()));
configuration.set((VisitListenerProvider) () -> new CacheVisitListener());
configuration.set(new MockConnection(new ResultCache(configuration.connectionProvider().acquire())));
return DSL.using(configuration);Now since the configuration is global, i think because of the MockConnection object whenever i insert an UpdatableRecord the primary key id is null. As a result my test cases are failing.
How do i overcome this issue? is there a way for me to create a new connection from the original one and is that a good idea?
--
DSL.using(Connection, SQLDialect)
DSL.using(new DefaultConfiguration().set(connection).set(dialect));
--
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 jooq-user+...@googlegroups.com.