I am currently working on a project where I have created the following custom Repository:
public interface ServiceRepository<T extends ServiceEntity> extends JpaRepository<T, UUID>, ServiceRepositoryCustom { } public interface ServiceRepositoryCustom { List<ServiceEntity> findAllContainingName(String query); } @Repository("Repo") public class ServiceRepositoryCustomImpl implements ServiceRepositoryCustom { private final EntityManager em; public ServiceRepositoryCustomImpl(EntityManager em) { System.out.println("I got constructed"); this.em = em; } @Override public List<ServiceEntity> findAllContainingName(String name) { System.out.println("I got called with: " + name); CriteriaBuilder cb = em.getCriteriaBuilder(); CriteriaQuery<ServiceEntity> cq = cb.createQuery(ServiceEntity.class); Root<ServiceEntity> serviceEntity = cq.from(ServiceEntity.class); List<Predicate> predicates = new ArrayList<>(); if(name != null) { // predicates.add(cb.equal(serviceEntity.get("name"), name)); predicates.add(cb.like(serviceEntity.get("name"), name + "%")); } cq.where(predicates.toArray(predicates.toArray(new Predicate[0]))); return em.createQuery(cq).getResultList(); } }
The print statement “I got called with: ” never gets called. So for whatever reason Spring Boot is not running the method through my custom implementation.
Any suggestions? Any help is much appreciated
Edit: Here is the code that injects and uses the Repository in question
@Repository public interface PineappleServiceRepository extends ServiceRepository<PineappleServiceEntity> { } @Component("Registry") @DependsOn({"Context", "Repo"}) public class Registry { private final List<ServiceRepository<? extends ServiceEntity>> serviceRepositories = new ArrayList<>(); public Registry(PineappleServiceRepository pineappleServiceRepository) { this.serviceRepositories.add(pineappleServiceRepository); } }
Edit 2: The code prints “I got constructed”
Edit 3:
Class where findAllContainingName
is called
@RestController @RequestMapping("/test") @DependsOn("Registry") public class ServiceController { private final Registry registry; public ServiceController(@NotNull Registry registry) { this.registry = registry; } @GetMapping("") List<ServiceEntity> all(@RequestParam("q") String query) { return getAllServices(query); } private @NotNull List<ServiceEntity> getAllServices(String query) { List<ServiceEntity> response = new ArrayList<>(); for(ServiceRepository<? extends ServiceEntity> repo: this.registry.getServiceRepositories()){ response.addAll(repo.findAllContainingName(query)); } return response; } }
Edit 4:
Here the entities:
@Entity @Table(name = "services") public abstract class ServiceEntity { protected @Id UUID id = UUID.randomUUID(); protected String name; // Constructor + Getters and Setters } @Entity public class PineappleServiceEntity extends ServiceEntity { // Additional Properties, matching Constructors, Getters and Setters }
Advertisement
Answer
So I was able to reproduce your problem and fix it. Issue with your code is that your PineappleServiceRepository
is not extending ServiceRepositoryCustom
directly. It seems your repository needs to implement it directly if you are accessing custom repository methods from that repository. I got that idea from this post.
So to fix your issue, either remove PineappleServiceRepository
(as you don’t have any properties in PineappleEntity) and use ServiceRepository
to call that custom method or make PineappleServiceRepository
extend ServiceRepositoryCustom
.
I have pushed changes to GitHub with fix. You can take a look. If you want to keep PineappleServiceRepository
and access custom method using this repository, let me know, I can update code.