Как добавить собственный метод в Spring Data JPA

Я изучаю Spring Data JPA. Рассмотрим приведенный ниже пример, где я получу, что все функции crud и finder будут работать по умолчанию, и если я хочу настроить Finder, это также можно легко сделать в самом интерфейсе.

@Transactional(readOnly = true)
public interface AccountRepository extends JpaRepository<Account, Long> {

  @Query("<JPQ statement here>")
  List<Account> findByCustomer(Customer customer);
}

Я хотел бы знать, как я могу добавить полный настраиваемый метод с его реализацией для указанного выше AccountRepository? Поскольку это интерфейс, я не могу реализовать там метод.


person Sharad Yadav    schedule 09.08.2012    source источник


Ответы (14)


Вам необходимо создать отдельный интерфейс для ваших пользовательских методов:

public interface AccountRepository 
    extends JpaRepository<Account, Long>, AccountRepositoryCustom { ... }

public interface AccountRepositoryCustom {
    public void customMethod();
}

и укажите класс реализации для этого интерфейса:

public class AccountRepositoryImpl implements AccountRepositoryCustom {

    @Autowired
    @Lazy
    AccountRepository accountRepository;  /* Optional - if you need it */

    public void customMethod() { ... }
}

См. также:

person axtavt    schedule 09.08.2012
comment
Может ли эта настраиваемая реализация внедрить реальный репозиторий, чтобы использовать определенные там методы? В частности, я хотел бы сослаться на различные функции find *, определенные в интерфейсе репозитория в реализации поиска более высокого уровня. Поскольку у этих функций find * () нет реализации, я не могу объявить их в пользовательском интерфейсе или классе Impl. - person JBCP; 23.10.2014
comment
Я следил за этим ответом, к сожалению, теперь Spring Data пытается найти свойство customMethod в моем объекте Account, поскольку он пытается автоматически сгенерировать запрос для всех методов, определенных в AccountRepository. Есть способ остановить это? - person Nick Foote; 25.06.2015
comment
@NickFoote обратите внимание, что имя класса, который вы реализуете в своем репозитории, должно быть: AccountRepositoryImpl not: AccountRepositoryCustomImpl и т. Д. - это очень строгое соглашение об именах. - person Xeon; 13.07.2015
comment
@JBCP, вы когда-нибудь находили на это ответ? - person end-user; 14.08.2015
comment
@ конечный пользователь: да, ваш объект impl может внедрить репозиторий, без проблем - person JBCP; 14.08.2015
comment
@JBCP: есть ли у вас фрагмент кода, чтобы продемонстрировать, где и как? - person end-user; 14.08.2015
comment
@ end-user - я обновил ответ выше примером, он очень простой, хотя я не думаю, что это обязательно очевидно. - person JBCP; 14.08.2015
comment
Я вижу проблему в этой спецификации. Если вы автоматически подключаете AccountRepository в AccountRepositoryImpl, у вас будут его собственные методы внутри странного цикла. Я бы автоматически подключил другой интерфейс, расширяющий CRUD. - person Esteban S; 30.11.2015
comment
* Имя файла Impl важно. У меня был класс реализации с тем же именем, что и у интерфейса репозитория (в другом пакете), и Spring не запускался. - person Xdg; 20.04.2016
comment
@JBCP, спасибо, это именно та проблема, которую я должен был решить. Я хотел расширить репо, в которое я уже добавил собственные методы поиска, такие как findByFooAndBar(). Я не подумал просто вставить репозиторий (который уже расширяет это) в пользовательский impl, потому что кажется, что это создаст круговую ссылку или что-то в этом роде? но работает так ... - person wired00; 01.07.2016
comment
@ wired00 Я думаю, что он создает круговую ссылку, и я не вижу, как @JBCP заставил ее работать. Когда я пытаюсь сделать что-то подобное, я получаю исключение: Error creating bean with name 'accountRepositoryImpl': Bean with name 'accountRepositoryImpl' has been injected into other beans [accountRepository] in its raw version as part of a circular reference, but has eventually been wrapped. - person Robert Hunt; 01.07.2016
comment
На самом деле, похоже, что это работает, если моя реализация пользовательского репозитория не расширяет QueryDslRepositorySupport - person Robert Hunt; 01.07.2016
comment
@roberthunt на самом деле я использовал это без проблем - person wired00; 01.07.2016
comment
Да, см. Мой предыдущий комментарий о том, что он не работает, если вы расширяете QueryDslRepositorySupport. Вы также должны внедрить репозиторий через инъекцию поля или установщика, а не инъекцию конструктора, иначе он не сможет создать bean-компонент. Кажется, что это работает, но решение кажется немного «грязным», я не уверен, есть ли какие-либо планы по улучшению того, как это работает, со стороны команды Spring Data. - person Robert Hunt; 01.07.2016
comment
внедрение репозитория в пользовательский impl не работает в весенней загрузке 1.4.3. Вы получите ошибку циклической зависимости bean-компонента, и приложение не запустится. Вместо этого вы можете ввести entitymanager (благодаря @jelies) и entityinformation (благодаря @NealeU) - person mpprdev; 30.01.2017
comment
Я также поместил @Repository в свой собственный репозиторий Impl, но он не работает. нужна ли какая-то конфигурация для сканирования этого класса как репозитория? - person Mahdi; 31.01.2017
comment
Я помещал свой класс AccountRepositoryImpl в свой файл AccountRepositoryCustom и имел ту же проблему, что и @NickFoote. Мне нужно было убедиться, что 1) интерфейс был назван XRepositoryCustom в соответствии с соглашением об именах, 2) класс Impl также был назван правильно (без Custom) и 3) * RepositoryImpl находился в собственном файле. Потом все заработало. - person Geyser14; 25.04.2017
comment
так какое же решение? получить ту же проблему с sring 1.5 - person robert trudel; 26.06.2017
comment
Это рекомендуемый способ сделать это, если я хочу иметь собственный способ сохранения ресурсов? Например. имея отношение m-to-n и желая обеспечить, чтобы ресурс и его связь были созданы за один запуск (см. также мой вопрос). - person Stefan Falk; 06.12.2017
comment
почему AccountRepository расширяет AccountRepositoryCustom? - person Kalpesh Soni; 26.09.2018
comment
Не удалось создать экземпляр основного репозитория после добавления вспомогательного репозитория Custom, хотя после этого я аннотировал @repository и получил ту же ошибку - person ThinkTank; 14.03.2019
comment
Не удалось создать экземпляр основного репозитория после добавления вспомогательного репозитория Custom, хотя после этого я аннотировал @repository и получил ту же ошибку - person ThinkTank; 14.03.2019
comment
Решена циклическая зависимость с помощью аннотации Lazy с аннотацией Autowired в реализации настраиваемого метода. - person tsnorri; 01.04.2019
comment
Просто обратите внимание, что пользовательский интерфейс должен содержать @NoRepositoryBean, как это делает JPARepository, чтобы исключить возможность захвата интерфейсов репозитория и, как следствие, создания создаваемого экземпляра. - person David Peláez; 07.05.2020

В дополнение к ответу от axtavt, не забывайте, что вы можете добавить Entity Manager в свою собственную реализацию, если он вам нужен для создания вашего запросы:

public class AccountRepositoryImpl implements AccountRepositoryCustom {

    @PersistenceContext
    private EntityManager em;

    public void customMethod() { 
        ...
        em.createQuery(yourCriteria);
        ...
    }
}
person jelies    schedule 11.03.2013
comment
Однако спасибо, я хочу знать, как использовать Pageable и Page в пользовательской реализации. Какие-нибудь входы? - person Wand Maker; 10.07.2013

Принятый ответ работает, но имеет три проблемы:

  • Он использует недокументированную функцию Spring Data при именовании пользовательской реализации как AccountRepositoryImpl. документация четко указано, что он должен называться AccountRepositoryCustomImpl, имя пользовательского интерфейса плюс Impl
  • Вы не можете использовать внедрение конструктора, только @Autowired, что считается плохой практикой.
  • У вас есть циклическая зависимость внутри настраиваемой реализации (поэтому вы не можете использовать внедрение конструктора).

Я нашел способ сделать его идеальным, хотя и не без использования еще одной недокументированной функции Spring Data:

public interface AccountRepository extends AccountRepositoryBasic,
                                           AccountRepositoryCustom 
{ 
}

public interface AccountRepositoryBasic extends JpaRepository<Account, Long>
{
    // standard Spring Data methods, like findByLogin
}

public interface AccountRepositoryCustom 
{
    public void customMethod();
}

public class AccountRepositoryCustomImpl implements AccountRepositoryCustom 
{
    private final AccountRepositoryBasic accountRepositoryBasic;

    // constructor-based injection
    public AccountRepositoryCustomImpl(
        AccountRepositoryBasic accountRepositoryBasic)
    {
        this.accountRepositoryBasic = accountRepositoryBasic;
    }

    public void customMethod() 
    {
        // we can call all basic Spring Data methods using
        // accountRepositoryBasic
    }
}
person Danila Piatov    schedule 30.07.2018
comment
Это сработало. Я хочу подчеркнуть важность того, что имя параметра в конструкторе должно соответствовать соглашению в этом ответе (должно быть accountRepositoryBasic). В противном случае Spring жаловался на то, что есть 2 варианта bean-компонентов для инъекции в мой конструктор *Impl. - person goat; 14.09.2018
comment
так в чем польза AccountRepository - person Kalpesh Soni; 26.09.2018
comment
@KalpeshSoni методы из AccountRepositoryBasic и AccountRepositoryCustom будут доступны через введенный AccountRepository - person geg; 07.02.2019
comment
Не могли бы вы указать способ создания контекста? Я не могу собрать все вместе. Спасибо. - person franta kocourek; 30.03.2020

Это ограничено в использовании, но для простых пользовательских методов вы можете использовать методы интерфейса по умолчанию, например:

import demo.database.Customer;
import org.springframework.data.repository.CrudRepository;

public interface CustomerService extends CrudRepository<Customer, Long> {


    default void addSomeCustomers() {
        Customer[] customers = {
            new Customer("Józef", "Nowak", "[email protected]", 679856885, "Rzeszów", "Podkarpackie", "35-061", "Zamknięta 12"),
            new Customer("Adrian", "Mularczyk", "[email protected]", 867569344, "Krosno", "Podkarpackie", "32-442", "Hynka 3/16"),
            new Customer("Kazimierz", "Dejna", "[email protected]", 996435876, "Jarosław", "Podkarpackie", "25-122", "Korotyńskiego 11"),
            new Customer("Celina", "Dykiel", "[email protected]", 947845734, "Żywiec", "Śląskie", "54-333", "Polna 29")
        };

        for (Customer customer : customers) {
            save(customer);
        }
    }
}

РЕДАКТИРОВАТЬ:

В учебнике этой весны написано:

Spring Data JPA также позволяет вам определять другие методы запроса, просто объявляя их сигнатуру метода.

Таким образом, можно даже просто объявить такой метод, как:

Customer findByHobby(Hobby personHobby);

и если объект Hobby является свойством клиента, то Spring автоматически определит для вас метод.

person Tomasz Mularczyk    schedule 20.05.2016

Есть немного измененное решение, которое не требует дополнительных интерфейсов.

Как указано в задокументированной функциональности суффикс Impl позволяет получить такое чистое решение:

  • Определите в вашем обычном @Repository интерфейсе, скажем MyEntityRepository пользовательские методы (в дополнение к вашим методам Spring Data)
  • Create a class MyEntityRepositoryImpl (the Impl suffix is the magic) anywhere (doesn't even need to be in the same package) that implements the custom methods only and annotate such class with @Component** (@Repository will not work).
    • This class can even inject MyEntityRepository via @Autowired for use in the custom methods.

Пример:

Класс сущности (для полноты):

package myapp.domain.myentity;
@Entity
public class MyEntity {
    @Id     private Long id;
    @Column private String comment;
}

Интерфейс репозитория:

package myapp.domain.myentity;

@Repository
public interface MyEntityRepository extends JpaRepository<MyEntity, Long> {

    // EXAMPLE SPRING DATA METHOD
    List<MyEntity> findByCommentEndsWith(String x);

    List<MyEntity> doSomeHql(Long id);   // custom method, code at *Impl class below

    List<MyEntity> useTheRepo(Long id);  // custom method, code at *Impl class below

}

Компонент реализации пользовательских методов:

package myapp.infrastructure.myentity;

@Component // Must be @Component !!
public class MyEntityRepositoryImpl { // must have the exact repo name + Impl !!

    @PersistenceContext
    private EntityManager entityManager;

    @Autowired
    private MyEntityRepository myEntityRepository;

    @SuppressWarnings("unused")
    public List<MyEntity> doSomeHql(Long id) {
        String hql = "SELECT eFROM MyEntity e WHERE e.id = :id";
        TypedQuery<MyEntity> query = entityManager.createQuery(hql, MyEntity.class);
        query.setParameter("id", id);
        return query.getResultList();
    }

    @SuppressWarnings("unused")
    public List<MyEntity> useTheRepo(Long id) {
        List<MyEntity> es = doSomeHql(id);
        es.addAll(myEntityRepository.findByCommentEndsWith("DO"));
        es.add(myEntityRepository.findById(2L).get());
        return es;
    }

}

Использование:

// You just autowire the the MyEntityRepository as usual
// (the Impl class is just impl detail, the clients don't even know about it)
@Service
public class SomeService {
    @Autowired
    private MyEntityRepository myEntityRepository;

    public void someMethod(String x, long y) {
        // call any method as usual
        myEntityRepository.findByCommentEndsWith(x);
        myEntityRepository.doSomeHql(y);
    }
}

И это все, нет необходимости в каких-либо интерфейсах, кроме репозитория Spring Data, который у вас уже есть.


Единственные возможные недостатки, которые я выявил:

  • Пользовательские методы в классе Impl помечены компилятором как неиспользуемые, поэтому предлагается @SuppressWarnings("unused").
  • У вас есть ограничение в один Impl класс. (В то время как в обычной реализации интерфейсов фрагментов в документации предлагается, что их может быть много.)
  • Если вы поместите класс Impl в другой пакет и ваш тест использует только @DataJpaTest, вы должны добавить @ComponentScan("package.of.the.impl.clazz") в свой тест, чтобы Spring загрузил его.
person acdcjunior    schedule 06.04.2019
comment
как правильно Autowire MyEntityRepositoryImpl? - person Konstantin Zyubin; 07.04.2020
comment
@KonstantinZyubin У вас автомайнируйте MyEntityRepository, а не *Impl. - person acdcjunior; 08.04.2020
comment
Невероятно подробный, подробный и полезный ответ. Определенно должно быть больше голосов! - person arnaldop; 05.02.2021
comment
Очень полезный ответ - person Samuel Moshie; 24.06.2021

Я использую следующий код, чтобы получить доступ к сгенерированным методам поиска из моей пользовательской реализации. Получение реализации через фабрику компонентов предотвращает проблемы создания циклических компонентов.

public class MyRepositoryImpl implements MyRepositoryExtensions, BeanFactoryAware {

    private BrandRepository myRepository;

    public MyBean findOne(int first, int second) {
        return myRepository.findOne(new Id(first, second));
    }

    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        myRepository = beanFactory.getBean(MyRepository.class);
    }
}
person Peter Rietzler    schedule 24.04.2015

Если вы хотите иметь возможность выполнять более сложные операции, вам может потребоваться доступ к внутренним компонентам Spring Data, и в этом случае работает следующее (как мое временное решение для DATAJPA-422):

public class AccountRepositoryImpl implements AccountRepositoryCustom {

    @PersistenceContext
    private EntityManager entityManager;

    private JpaEntityInformation<Account, ?> entityInformation;

    @PostConstruct
    public void postConstruct() {
        this.entityInformation = JpaEntityInformationSupport.getMetadata(Account.class, entityManager);
    }

    @Override
    @Transactional
    public Account saveWithReferenceToOrganisation(Account entity, long referralId) {
        entity.setOrganisation(entityManager.getReference(Organisation.class, organisationId));
        return save(entity);
    }

    private Account save(Account entity) {
        // save in same way as SimpleJpaRepository
        if (entityInformation.isNew(entity)) {
            entityManager.persist(entity);
            return entity;
        } else {
            return entityManager.merge(entity);
        }
    }

}
person NealeU    schedule 31.10.2013

Принимая во внимание фрагмент кода, обратите внимание, что вы можете передавать только Native объекты методу findBy ###, допустим, вы хотите загрузить список учетных записей, принадлежащих определенным клиентам, одно из решений - сделать это,

@Query("Select a from Account a where a."#nameoffield"=?1")
List<Account> findByCustomer(String "#nameoffield");

Сделайте так, чтобы имя запрашиваемой таблицы было таким же, как у класса Entity. Для дальнейших реализаций просмотрите это

person Samba    schedule 17.05.2015
comment
Это опечатка в запросе, это должно быть nameoffie l d, у меня нет надлежащего права ее исправлять. - person BrunoJCM; 29.08.2017

Здесь следует рассмотреть еще один вопрос. Некоторые люди ожидают, что добавление пользовательского метода в ваш репозиторий автоматически откроет их как службы REST по ссылке «/ search». К сожалению, это не так. В настоящее время Spring не поддерживает это.

Это особенность `` по дизайну '', Spring data rest явно проверяет, является ли метод настраиваемым методом, и не раскрывает его как ссылку поиска REST:

private boolean isQueryMethodCandidate(Method method) {    
  return isQueryAnnotationPresentOn(method) || !isCustomMethod(method) && !isBaseClassMethod(method);
}

Это цитата Оливера Гирке:

Это сделано намеренно. Пользовательские методы репозитория не являются методами запросов, поскольку они могут эффективно реализовать любое поведение. Таким образом, в настоящее время мы не можем решить, какой HTTP-метод будет использовать. POST был бы самым безопасным вариантом, но он не соответствует общим методам запросов (которые получают GET).

Дополнительные сведения см. В этой проблеме: https://jira.spring.io/browse/DATAREST-206 < / а>

person Lukasz Magiera    schedule 21.07.2015
comment
К сожалению, я потратил столько времени, пытаясь выяснить, что я сделал не так, и, наконец, я понимаю, что такой функции нет. Зачем им вообще реализовывать эту функциональность? Чтобы было меньше фасоли? Чтобы все методы дао были в одном месте? Я мог бы добиться этого другими способами. Кто-нибудь знает, какова цель добавления поведения к функции отдельных репозиториев? - person Skeeve; 08.02.2016
comment
Вы можете предоставить доступ к любым методам репозитория через REST, просто добавив к методу аннотацию @RestResource(path = "myQueryMethod"). Приведенная выше цитата просто заявляет, что Spring не знает, как вы хотите, чтобы он отображался (например, GET vs POST и т. Д.), Поэтому вы должны указать это через аннотацию. - person GreenGiant; 08.06.2018

Добавление настраиваемого поведения во все репозитории:

Чтобы добавить настраиваемое поведение во все репозитории, вы сначала добавляете промежуточный интерфейс для объявления общего поведения.

public interface MyRepository <T, ID extends Serializable> extends JpaRepository<T, ID>
{
    
    void sharedCustomMethod( ID id );
}

Теперь ваши индивидуальные интерфейсы репозитория будут расширять этот промежуточный интерфейс вместо интерфейса репозитория, чтобы включить заявленную функциональность.

Затем создайте реализацию промежуточного интерфейса, который расширяет базовый класс репозитория, зависящий от технологии сохранения. Затем этот класс будет действовать как настраиваемый базовый класс для прокси-серверов репозитория.

public class MyRepositoryImpl <T, ID extends Serializable> extends SimpleJpaRepository<T, ID> implements MyRepository<T, ID>
{
    
    private EntityManager entityManager;
    
       // There are two constructors to choose from, either can be used.
    public MyRepositoryImpl(Class<T> domainClass, EntityManager entityManager)
    {
        super( domainClass, entityManager );
        
        // This is the recommended method for accessing inherited class dependencies.
        this.entityManager = entityManager;
    }
    
    
    public void sharedCustomMethod( ID id )
    {
        // implementation goes here
    }
}

Spring Data Repositories Part I. Справка

введите описание изображения здесь

person Ali Yeganeh    schedule 19.06.2020

Я расширяю SimpleJpaRepository:

public class ExtendedRepositoryImpl<T extends EntityBean> extends SimpleJpaRepository<T, Long>
    implements ExtendedRepository<T> {

    private final JpaEntityInformation<T, ?> entityInformation;

    private final EntityManager em;

    public ExtendedRepositoryImpl(final JpaEntityInformation<T, ?> entityInformation,
                                                      final EntityManager entityManager) {
       super(entityInformation, entityManager);
       this.entityInformation = entityInformation;
       this.em = entityManager;
    }
}

и добавляет этот класс в @EnableJpaRepositoryries repositoryBaseClass.

person Devilluminati    schedule 12.11.2018

Я использую SimpleJpaRepository в качестве базового класса реализации репозитория и добавляю собственный метод в интерфейс, например:

public interface UserRepository  {
    User FindOrInsert(int userId);
}

@Repository
public class UserRepositoryImpl extends SimpleJpaRepository implements UserRepository {

    private RedisClient redisClient;

    public UserRepositoryImpl(RedisClient redisClient, EntityManager em) {
        super(User.class, em);
        this.redisClient = redisClient;
    }


@Override
public User FindOrInsert(int userId) {

    User u = redisClient.getOrSet("test key.. User.class, () -> {
        Optional<User> ou = this.findById(Integer.valueOf(userId));
        return ou.get();
    });
    …………
    return u;
}
person LoremIpsum    schedule 08.09.2020

Мне понравилось решение Данилы, и я начал его использовать, но никому в команде не нравилось создавать по 4 класса для каждого репозитория. Решение Данилы - единственное, что позволяет вам использовать методы Spring Data в классе Impl. Однако я нашел способ сделать это с помощью всего одного класса:

public interface UserRepository extends MongoAccess, PagingAndSortingRepository<User> {

    List<User> getByUsername(String username);


    default List<User> getByUsernameCustom(String username) {
        // Can call Spring Data methods!
        findAll();

        // Can write your own!
        MongoOperations operations = getMongoOperations();
        return operations.find(new Query(Criteria.where("username").is(username)), User.class);
    }
}

Вам просто нужен способ получить доступ к вашему компоненту db (в этом примере MongoOperations). MongoAccess предоставляет этот доступ ко всем вашим репозиториям, напрямую получая bean-компонент:

public interface MongoAccess {
    default MongoOperations getMongoOperations() {
        return BeanAccessor.getSingleton(MongoOperations.class);
    }
}

Где BeanAccessor:

@Component
public class BeanAccessor implements ApplicationContextAware {

    private static ApplicationContext applicationContext;

    public static <T> T getSingleton(Class<T> clazz){
        return applicationContext.getBean(clazz);
    }

    public static <T> T getSingleton(String beanName, Class<T> clazz){
        return applicationContext.getBean(beanName, clazz);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        BeanAccessor.applicationContext = applicationContext;
    }

}

К сожалению, вы не можете использовать @Autowire в интерфейсе. Вы можете автоматически подключить bean-компонент к MongoAccessImpl и предоставить в интерфейсе метод для доступа к нему, но Spring Data взорвется. Я не думаю, что он ожидает увидеть Impl, даже косвенно связанный с PagingAndSortingRepository.

person virtual-g    schedule 09.12.2020

Я столкнулся с этим, используя mongo и spring. Итак, давайте предположим, что мы используем MongoRepository для предоставления базовых операций crud, и предположим, что нам нужно реализовать некоторую операцию запроса пользовательских критериев с помощью mongoTemplate. Чтобы создать единый интерфейс для внедрения репозитория для crud и custom, нам нужно указать:

Пользовательский интерфейс:

public interface UserCustomRepository {
 List<User> findAllUsersBySomeCriteria(UserCriteriaRequest criteriaRequest);
}

Интерфейс UserRepository должен сначала расширять UserCustomRepository, а затем MongoRepository

@Repository
public interface UserRepository extends UserCustomRepository, MongoRepository<User, ObjectId> {
}

Имя UserRepositoryImpl должно совпадать с именем интерфейса crud с суффиксом * Impl.

@Component
@NoArgsConstructor
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class UserRepositoryImpl implements UserCustomRepository {

 private MongoTemplate mongoTemplate;

 @Override
 public List<User> findAllUsersBySomeCriteria(UserCriteriaRequest criteriaRequest){
  //some impl
 }
}

Давайте представим какой-нибудь сервис - здесь мы внедряем только интерфейс UserRepository и используем методы из репозитория crud и пользовательского класса impl.

@Service
@NoArgsConstructor
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class UserService {

 private UserRepository userReposityry;

 public List<User> getUserByCriteria(UserCriteriaRequest request) {
   userRepository.findById(request.getUserId); // Crud repository method
   userRepository.findAllUsersBySomeCriteria(request); // custom method.
 }
}
person mryba    schedule 07.05.2021