Spring Data MongoDB пытается генерировать запросы для пользовательских методов репозитория

#java #mongodb #spring-data #spring-data-document

#java #mongodb #spring-data #spring-data-document

Вопрос:

На основе документации документа Spring Data я предоставил пользовательскую реализацию метода репозитория. Имя пользовательского метода ссылается на свойство, которого не существует в объекте домена:

 @Document
public class User {
    String username;
}

public interface UserRepositoryCustom {
    public User findByNonExistentProperty(String arg);
}

public class UserRepositoryCustomImpl implements UserRepositoryCustom {
    @Override
    public User findByNonExistentProperty(String arg) {
        return /*perform query*/;
    }
}

public interface UserRepository
        extends CrudRepository<?, ?>, UserRepositoryCustom {

    public User findByUsername(String username);
}
  

Однако, возможно, из-за выбранного мной имени метода ( findByNonExistentPropertyName ), Spring Data пытается проанализировать имя метода и создать запрос на его основе. Когда он не может найти nonExistentProperty в User , генерируется исключение.

Возможные решения:

  1. Я допустил ошибку в том, как я предоставляю реализацию пользовательского метода?
  2. Есть ли способ указать Spring не пытаться генерировать запрос на основе имени этого метода?
  3. Должен ли я просто избегать использования каких-либо префиксов, которые распознает Spring Data?
  4. Ничего из вышеперечисленного.

Спасибо!

Комментарии:

1. Я не уверен, является ли это реальной проблемой или нет, но разве UserRepositoryCustomImpl не должен реализовывать UserRepositoryCustom?

2. Да, вы правы, и это так, я просто пропустил это при написании вопроса. Спасибо!

Ответ №1:

Ваш класс реализации должен быть назван UserRepositoryImpl (если вы придерживаетесь конфигурации по умолчанию), поскольку мы пытаемся найти его на основе найденного имени интерфейса репозитория Spring Data. Причина, по которой мы начинаем с этого, заключается в том, что мы не можем достоверно знать, какой из интерфейсов, которые вы расширяете, является тем, который имеет пользовательскую реализацию. Учитывая сценарий, подобный этому

 public interface UserRepository extends CrudRepository<User, BigInteger>,
  QueryDslPredicateExecutor<User>, UserRepositoryCustom { … }
  

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

Итак, что мы обычно предлагаем, так это придумать соглашение об именовании, скажем, Custom суффикса для интерфейса, содержащего методы, которые будут реализованы вручную. Затем вы можете настроить инфраструктуру репозитория для выбора классов реализации, используя CustomImpl в качестве суффикса repository-impl-postfix атрибут repositories элемента:

 <mongo:repositories base-package="com.acme" 
                    repository-impl-postfix="CustomImpl" />
  

В справочной документации есть дополнительная информация об этом, но, похоже, вы хотя бы кратко проверили это. 🙂

Комментарии:

1. Большое вам спасибо! Я полностью пропустил, что название реализации в примере не содержало Custom . Поскольку я внедрял UserRepositoryCustom , я интуитивно ожидал, что Spring Data будет искать класс с именем UserRepositoryCustomImpl , но я могу оценить, насколько сложно это может быть реализовать, не требуя от пользователя предоставления дополнительных метаданных. Спасибо вам и всей команде Spring Data за создание такого фантастического проекта!

2. Добро пожаловать. Мы знаем, что это было бы немного более интуитивно понятным, чем вы изначально думали об этом, поэтому я благодарен, что вы задали этот вопрос, поскольку мы создаем некоторые фрагменты информации таким образом :).