I have several entities and use Spring Data JPA repositories with specifications query my database. Therefore I created a generic class SpecBuilder to build my queries based on a query description (MyQueryDescriptor).
public class Specs { public static <T extends MyEntityIFace> Specification<T> myfind(final MyQueryDescriptor qDesc) { return new Specification<T>() { @Override public Predicate toPredicate(Root<T> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) { try { return SpecBuilder.mySpec(root, criteriaQuery, criteriaBuilder, qDesc); } catch (Exception e) { ...handle error... } } }; } } My repositories:
public interface Entity1DAO extends Repository<Entity1,Long>, JpaSpecificationExecutor { } and
public interface Entity2DAO extends Repository<Entity2,Long>, JpaSpecificationExecutor { } Now there are 3 things I am not quite sure about:
1)
Is this use of a generic SpecBuilder a clean design?
2)
Is there a way to avoid writing those repository interfaces for each entity? Let's say a generic repository?
3)
The MyQueryDescriptor class has a method to return an instance of an Entity, which will be queried.
What would be a clean way to obtain the according repository based on the entity class, avoiding a switch case? I was thinking about putting an annotation with the specific repository class to each entity but it feels a bit smelly.
Should I create a factory and inject a map like
Entity1.class => Entity1DAO Entity2.class => Entity2DAO ?
findAll(),save(T), etc but why not let the details be left to inference? You can let the system generate nice things likefindThisByThatAndTheOther(T that, T2 theOther);?findThisByThatAndTheOther(T that, T2 theOther)but mySpecBuilderclass should be able to create all criteria queries I'd need. Therefore creating empty repositories for many entities feels like a lot of overhead.