As you already read in our previous article, our persistence data was based on database with support SQL as in many companies (specifically Oracle and Teradata). Unfortunately, this approach became gradually obsolete.
We also pointed out that Solr was our winner. Solr is written in Java and based on Lucene. Data is saved as a key and value (Map), it uses web interface for managing and it complies with the most important condition: redistribution.
Let’s point our look to Solr and introduce it more technically. To be able to create new storage in Solr, we must know configuration and scheme. The configuration is used for storage metadata (e.g. indexing, caching, quering …). The Scheme contains information about fields in storage (keys).
However, the usage of a new embedded database was not the end! “When you clean your house, don’t clean only the bedroom”.
What else did we do? We created special module (core). The module can work with different storage (e.g. in-memory…) and it is really simple to add new storage.
The usage of the storage is easy! When the developer uses core, he doesn’t have to know anything about the storage! He can just use the interface. Yes, we were inspired by Spring data.
So, how does it work? Developer creates document and repository and he defines system properties using annotations in document.
class Entity {
@Id
private final Integer id;
@ValidFrom
private final Long validFrom;
@ValidTo
private final Long validTo;
…
}
The example shows historicized entity: “@Id” defines primary key, whilst “@ValidFrom” and “@ValidTo” is used for historization.
Repository then works with document and has a common behavior. It is easy to use:
public interface EntityRepository
extends HistorizedRepository<Integer, Entity > {}
The repository is based on a proxy pattern. The developer only extends common class (HistorizedRepository or Repository) and the framework is processing individual operations.
entityRepository.findAny(queryBuilder.build());
The advantage of our solution is that interface entityRepository is not implemented! An invoker is called after calling operation (findAny) and the invoker itself executes the action! QueryBuilder then creates query that looks like select in SQL:
public class Query {
private final List<Where> wheres;
private final List<Sort> sortList;
private final Limit limit;
…
}
Yes, yes, we know, it is as child and it needs time for growing up, however, great start – don’t you think?