Extend findAll with custom filters

Asked

Viewed 2,187 times

2

I am trying to extend findAll from my JPA repository to make custom filters.

I did some research and found some ideas of use with Predicates and the like but did not identify something that worked in a practical way.

I wonder if someone has ever been through something like this or have some idea of how to do it without I need to create various forms of research within my Repository.

  • You need all your repositories to display the behavior of findAll changed? A group of repositories only? If so, you need one factory bean customized for repositories. If it’s just one (or a small group), property expressions does not solve your problem? In addition, your problem is in the use of predicates or in the manufacture of Beans?

  • need for some positorios only, a bit large by the way for custom searches. Do you have any examples of Factory bean ? just so I know if we’re speaking the same language. @Brunocésar desde agradeço

  • This answer is an example of a custom repository and a Factory bean that creates repositories with it as an implementation. I didn’t exactly understand your need, how "personalized" and complex, why jpa data has so many ways to define queries. If you include what you need as a result, it might be simpler to help.

  • @Brunocésar very good brother, puts as an answer so I can mark as solved

  • @Brunocésar What I need would be something like using filters for various fields using findall as the basis understood

  • Otto, I don’t understand this last comment. You need something other than the answer that was linked (and included below) or is this just it?

  • @I will do the tests to see if you answer and I will be warning in sequence ... since already battered

Show 2 more comments

2 answers

1


One of the ways to modify the default behavior of a Spring Data JPA method is to create another repository base implementation. In the documentation is shown as adds custom behavior to the repository.

The steps to be followed are more or less these:

  1. create a custom interface for your repositories, and can extend the JpaRepository even, something like that:
@NoRepositoryBean
public interface CustomGenericRepository<E extends CustomAbstractEntity, PK extends Serializable> extends
        JpaRepository<E, PK>, JpaSpecificationExecutor<E> { }

We will extend as well JpaSpecificationExecutor, why our custom repository will use Specifications and she supports this.

  1. the second step is to implement this interface that we have just defined. Below is an example that changes the behavior of findAll, using a Specification which will consider in the query only the records not deleted logically, something like this:
public class CustomGenericRepositoryImpl<E extends CustomAbstractEntity, PK extends Serializable> extends
        SimpleJpaRepository<E, PK> implements CustomGenericRepository<E, PK> {

    private final EntityManager entityManager;

    public CustomGenericRepositoryImpl(final Class<T> domainClass, final EntityManager entityManager) {
        super(domainClass, entityManager);
        this.entityManager = entityManager;
    }

    @Override
    public List<E> findAll() {
        return super.findAll(this.isRemoved());
    }

    private Specification<E> isRemoved() {
        return new Specification<E>() {

            @Override
            public Predicate toPredicate(final Root<E> root, final CriteriaQuery<?> query, final CriteriaBuilder cb) {
                return cb.isFalse(root.<Boolean> get("deleted"));
            }

        };

    }

}
  1. as we have a different implementation that we will use in our repositories, we need to create a way to instruct container spring as it will create the instances for the repositories. Then, we will create a Factory bean also customized and that also extends from one that is JPA, the JpaRepositoryFactoryBean:
public class CustomGenericRepositoryFactoryBean<T extends JpaRepository<S, ID>, S, ID extends Serializable> extends
        JpaRepositoryFactoryBean<T, S, ID> {

    @Override
    protected RepositoryFactorySupport createRepositoryFactory(final EntityManager entityManager) {
        return new RepositoryFactory(entityManager);
    }

    private static class RepositoryFactory<T, I extends Serializable> extends JpaRepositoryFactory {

        public RepositoryFactory(final EntityManager entityManager) {
            super(entityManager);
        }

        protected Object getTargetRepository(final RepositoryMetadata metadata) {
            return new CustomGenericRepositoryImpl<T, I>((Class<T>) metadata.getDomainClass(), em);
        }

        @Override
        protected Class<?> getRepositoryBaseClass(final RepositoryMetadata metadata) {
            return CustomGenericRepositoryImpl.class;
        }

    }

}
  1. Finally, we need to talk to the spring date what is the factory-class to create our repositories. Using XML you can use it like this:
<jpa:repositories base-package="com.brunocesar.custom.repository,com.brunocesar.custom.repository.support"
    factory-class="com.brunocesar.custom.repository.support.factory.CustomGenericRepositoryFactoryBean"
    transaction-manager-ref="transactionManagerCustom" entity-manager-factory-ref="entityManagerFactoryCustom" />

Using Java, considering a class only for configuration of repositories, just configure the attribute factoryClass of @EnableJpaRepositories, something like that:

@EnableJpaRepositories(factoryClass = "com.brunocesar.custom.repository.support.factory.CustomGenericRepositoryFactoryBean")
public class JPARepositoryConfig {

    // o resto da configuração continua a mesma =)

}

To use, simply extend your repository’s custom interface, CustomGenericRepository, something like that:

@Repository
public interface PessoaRepository extends CustomGenericRepository<Pessoa, Long> {

}

0

Implements Jparepository that Voce can customize your queries according to the attributes of your example object below :

public interface Empregado extends JpaRepository<Empregado , Integer> {
   //Atributo Endereco dentro de Empregado ele já implementa pra vc tudo!
   List<Empregado> findByEndereco(Endereco endereco );
}

Browser other questions tagged

You are not signed in. Login or sign up in order to post.