Oi @jaabax!
Achei que o exemplo dado pelo colega @lvbarbosa tinha respondido seu questionamento, mas talvez não tenha ficado claro.
Se você precisa gerar muitas queries não há problema fazer com que o repositório receba um objeto criado no serviço que represente essa query.
Esse padrão é descrito no eea como QueryObject, já no DDD existe uma abordagem parecida, porém mais focada na regra de negócio em vez de ser um mero descritor do SQL, onde o padrão é chamado Specification mas que também é passado para o Repository com as “especificações” das entidades buscadas (um dos usos desse padrão).
No JPA existe uma implementação do QueryObject na Criteria API que pode ser usado na camada de serviço para criar suas queries complexas. Como o JPA é uma especificação então não importa qual a implementação você vai usar se Hibernate ou EclipseLink (se bem que se você for mudar de um para outro provavelmente vai ter problemas com LazyLoading etc… mas que não vem ao caso para o que foi questionado).
Não estou dizendo para escrever SQL no serviço senão não faria sentido existir o repositório, mas não há problema algum em colocar a construção dessa query no serviço desde que usando um objeto que abstraia o SQL para que o serviço não seja dependente de banco e seja fácil de testar (em aplicações reais às vezes é preciso até colocar lógica no banco, coisa que é horrível do ponto de vista da manutenção).
Para ficar bem claro e fácil a resolução desse tipo de problema no futuro eu recomendo a leitura do [eea] (https://martinfowler.com/books/eaa.html) (apesar de longo basta ler as primeiras 100 páginas conforme dito pelo próprio autor, o resto é para consulta quando precisar implementar).
O DDD também é essencial porém a leitura é bem pesada. Tem que ler no mínimo umas 3 vezes pra entender essa bagaça (ou não entender nunca como no meu caso rsrs).
E também, pra tirar férias de vez da família, OOA&D mas esse é de boa leitura rsrs.
Se acha que isso é overengineering eu concordo que pode ser sim, depende do caso. Isso deveria ser usado apenas se realmente necessário. O que a maioria das aplicações grandes e enterprise o são. Não existe solução simples para problemas complexos.