OlgaMaciaszek
OlgaMaciaszek

Reputation: 3912

Spring Data Repositiories - add specific parameters to every query

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?

Upvotes: 6

Views: 906

Answers (2)

ddarellis
ddarellis

Reputation: 3960

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)
}

Upvotes: 4

Zorglube
Zorglube

Reputation: 734

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;
    }
}

Upvotes: 1

Related Questions