6

I have a few repositories that extend org.springframework.data.mongodb.repository.MongoRepository. I have added some methods for searching entities by different parameters, however, in any search, I only want to search for entities that have the active field set to true (have opted for marking as active=false in place of deleting). For example, two sample repositories would look like this:

interface XxRepository extends MongoRepository<Xx, String> {

    Optional<Xx> findOneByNameIgnoreCaseAndActiveTrue(String name)

    Page<Xx> findByActiveTrue(Pageable pageable)

    Xx findOneByIdAndActiveTrue(String id)

}

interface YyRepository extends MongoRepository<Yy, String> {

    Optional<Yy> findOneByEmailAndActiveTrue(String email)
}

Is there any way that would allow me not to add byActiveTrue\ andActiveTrue to each and every method and set it up somewhere in one place for all the queries?

2 Answers 2

4

Please try this. No need to provide implementation. Change 'active' and 'email' to your db column name.

interface YyRepository extends MongoRepository<Yy, String> {
    @Query(value = "{ 'active' : { '$eq': true }, 'email' : ?0 }")
    Optional<Yy> findOneByEmailAndActiveTrue(@Param("email") String email)
}
Sign up to request clarification or add additional context in comments.

2 Comments

I already have such naming and the methods in my repo work. I'm just looking for a way to avoid repetitions in the method names.
You can have whatever method you want. In this way the active true is passed from the query params not the method name.
1

You can write an template query into the MongoRepository using Criteria. Example

class abstract MongoRepository<W, X> {

    protected Class<W> typeOfEntity;
    private Class<X> typeOfId;

    public MongoRepository() {
        typeOfEntity = (Class<W>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        typeOfId = (Class<X>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    public W get(X id) throws Exception {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery<W> q = cb.createQuery(typeOfEntity);
        Root<W> r = q.from(typeOfEntity);

        String idName = CommonEntity.findIdFieldName(typeOfEntity);
        Predicate andClose = cb.and(cb.equal(r.get("active"), true));

        q.where(cb.equal(r.get(idName), id), andClose);

        return em.createQuery(q).getSingleResult();
    }
}

After that, you stay confident into the object running way ans stereotyping to run the good type of request.

The findIdFieldNameis an method using the @Id to get the id field name.

public abstract class CommonEntity implements Serializable {

    public static String findIdFieldName(Class cls) {
        for (Field field : cls.getDeclaredFields()) {
            String name = field.getName();
            Annotation[] annotations = field.getDeclaredAnnotations();
            for (int i = 0; i < annotations.length; i++) {
                if (annotations[i].annotationType().equals(Id.class)) {
                    return name;
                }
            }
        }
        return null;
    }
}

3 Comments

Yes, but I like the succinct and readable style of the custom queries in Spring data repositories, so I'm wondering if there is a way to continue using that declarative way of query-building, however without repeating that specific parameter every single time.Not sure if there is any way of implementing it like that, though.
You can use the inheritance way of coding I purposed you and just field the W get(X id) by : Query q = em.createQuery("Select * From table Where id = :idValue And active = true"); q.setParameters("idValue", id); return em.getSingleResult();
After that in each repository object inheriting of MongoRepository<W, X> you @Override get method by @Override W get (X id) { super.get(id); }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.