I see what you mean. We unit test our DAO layer against the real postgres 
db. But at the service layer, I'm working on re-designing our test classes 
to use "memory DAOs". I started with the approach to write memory DAO 
versions of every DAO class, essentially instead of JOOQ queries to do 
hashtable stream filter/map, etc. It's extremely fast: test classes that 
took 10 seconds to execute now take less than 100 ms. But it's a lot of 
effort, and forces us to make sure our real DAO classes are properly unit 
tested in all cases.

Hopefully, H2 will give us similar speed and configuration simplicity, 
without all the development effort!

FYI, for the hashtable implementation I started, I use a class that 
maintains all the hashtables to support join emulation:

//
// The purpose of this class is to enable memory dal classes to emulate the 
following sql
// features by providing a central service of all repositories by type:
//   1) sql joins
//   2) long-based primary key sequence generation
//
@Singleton
public class MemoryRepositoryService implements IMemoryRepositoryService {

   private final  Map<Class<? extends UpdatableRecord<?>>,
                  Map<?, ? extends UpdatableRecord<?>>> _repositories;
   private final Map<Class<? extends UpdatableRecord<?>>, Class<?>> _idTypes;

   private AtomicLong _sequenceGenerator;

   public MemoryRepositoryService() {
      _repositories = new HashMap<>();
      _idTypes = new HashMap<>();
      _sequenceGenerator = new AtomicLong();
   }

   @Override
   public <R extends UpdatableRecord<R>, T> Map<T, R> repository(Class<R> 
valueClass,
                                                                Class<T> 
keyClass)
   {
      if (_repositories.containsKey(valueClass)) {
         validateKeyClass(keyClass);
         return (Map<T, R>) _repositories.get(valueClass);
      } else {
         return syncRepository(valueClass, keyClass);
      }
   }

   private synchronized <R extends UpdatableRecord<R>, T>
                        Map<T, R> syncRepository(Class<R> valueClass, Class<T> 
keyClass)
   {
      Map<T, R> repository;

      // double checked lock
      if (_repositories.containsKey(valueClass)) {
         validateKeyClass(keyClass);
         repository = (Map<T, R>) _repositories.get(valueClass);
      } else {
         repository = new ConcurrentHashMap<>();
         _idTypes.put(valueClass, keyClass);
         _repositories.put(valueClass, repository);
      }

      return repository;
   }

   private <T> void validateKeyClass(Class<T> keyClass) {
      if (!_idTypes.get(keyClass).equals(keyClass)) {
         throw new IllegalArgumentException(
               "Key type does not match existing registered type");
      }
   }

   @Override
   public synchronized void clear() {
      _repositories.values().forEach(Map::clear);
   }

   @Override
   public long nextLong() {
      return _sequenceGenerator.incrementAndGet();
   }
}


 

On Friday, July 1, 2016 at 9:33:07 AM UTC-4, Lukas Eder wrote:
>
> First, you'll add a bunch of values in 1-2 hashmaps. Then you refactor. 
> Then you figure out that very often, these hashmaps are rather similar. 
> Then you notice that minimal transactionality is nice. And perhaps locking. 
> And suddenly, you have implemented a full scale RDBMS built on hashmaps 
> that can be queried using a DSL that looks like SQL... Why go through all 
> that hassle? :)
>
> The nice thing about H2 is that in principle, you could just keep a copy 
> of your .db file somewhere and restore that at the end of a test that 
> includes writing...
>
> Cheers,
> Lukas
>
> 2016-07-01 15:09 GMT+02:00 Jacob G <[email protected] <javascript:>>:
>
>> Thanks. I'll take a look at it, particularly to evaluate in-process mode, 
>> performance, and complexity of configuration, schema setup and teardown 
>> between each unit test method. The nice thing about hash tables is there is 
>> no schema setup or teardown.
>>
>> On Friday, July 1, 2016 at 8:04:37 AM UTC-4, Lukas Eder wrote:
>>>
>>> Yes, that exists, and it has a name! H2 in-memory database. :) (or 
>>> HSQLDB or Derby)
>>>
>>> Hope this helps.
>>> Lukas
>>>
>>> 2016-07-01 13:46 GMT+02:00 Jacob G <[email protected]>:
>>>
>>>> For unit testing, I'd like to be able to use in-memory hash tables for 
>>>> data rather than a database. Rather than re-implement memory-based DAO 
>>>> classes for every JOOQ-based DAO class, I'd rather have JOOQ execute 
>>>> itself 
>>>> on hash tables. Conceptually, it seems very doable since Jooq's powerful 
>>>> metadata model lends itself to being rendered and executed in alternative 
>>>> ways to sql.
>>>>
>>>> Has anyone thought about this, or even worked on or implemented such a 
>>>> solution?
>>>>
>>>> If I were to go about it, what approach would you suggest, and are 
>>>> there existing hooks I can use to redirect Jooq to a different hash table 
>>>> implementation. I see that there is a hook for connections once sql is 
>>>> rendered, but I'd like to hook in before that, while the query is still an 
>>>> object. Is that what AbstractDelegatingQuery is for? Any other concerns?
>>>>
>>>> -- 
>>>> 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] <javascript:>.
>> 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