Почему я получаю ошибку «Свойство не найдено» в репозитории?

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

Вопрос:

Я использую java spring и репозиторий mongodb для своего проекта.

Вот хранилище defeniton:

 @Repository
public interface InfoRepository extends MongoRepository<Info, String> {
    List<InfoDto> findAll();
}
 

Вот информация о защите:

 @Document("info")
@Data
public class Info{
    @Id
    private String id = null;
    private String name;
    private String companyName;
    private String email;
    private Address address;
    private String website;
}
 

Вот информация о защите класса:

 @Data
public class InfoDto {
    private String name;
    private String companyName;
    private Address address;
}
 

Когда я начинаю запускать проект, я получаю эту ошибку:

 'findAll()' in '...repository.InfoRepository' clashes with 'findAll()' 
in 'org.springframework.data.mongodb.repository.MongoRepository'; attempting to use incompatible return type
 

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

 List<InfoDto> findAll();
 

к этому:

 List<InfoDto> findAllMakeProjection();
 

Но после того, как я внесу изменения выше и запущу функцию, я получу эту ошибку:

 org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'infoServiceImpl' defined in file 
[...InfoServiceImpl.class]: 
Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: 
Error creating bean with name 'infoRepository' defined in ".../repository.InfoRepository" defined in @EnableMongoRepositories 
declared on MongoRepositoriesRegistrar.EnableMongoRepositoriesConfiguration: 
Invocation of init method failed; nested exception is org.springframework.data.mapping.PropertyReferenceException: 
No property findAllMakeProjection found for type Info!
 

Есть идеи, почему я получаю ошибку и как ее исправить?

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

1. Как насчет того, чтобы перейти List<InfoDto> findAll(); на List<Info> findAll();

2. @DilermandoLima Мне нужно настроить возвращаемый объект

3. измените имя метода на findAllBy

4. @Harshit, спасибо тебе за пост! Это работает, не могли бы вы, пожалуйста, дать какое-то объяснение, я приму его в качестве ответа.

Ответ №1:

List<T> findAll() это метод, предоставляемый в интерфейсе MongoRepository, поэтому невозможно изменить его тип возвращаемого значения в подинтерфейсах. Самое большее, вы можете изменить тип возвращаемого значения, чтобы перечислить реализации типа ArrayList<T> или LinkedList<T> .

Если вы измените имя метода на List<InfoDto> findAllMakeProjection() , Spring Data MongoDB попытается выполнить запрос с использованием имени свойства, но имя свойства отсутствует, поэтому оно выдаст ошибку.

Но разрешается добавлять что-либо перед By словом в имени метода, например findAllBy , findEverythingBy , findDataBy . Все , что будет после By , будет работать как фильтры(где условие), и если мы ничего не добавим после By , это будет работать как findAll (без фильтров)

Итак, измените имя метода соответствующим образом, и вы сможете выполнить свой запрос.

Ответ №2:

Здесь происходит findAll() то, что имя встроенного метода репозитория по умолчанию зарезервировано для Spring Data JPA. поэтому, если вы введете свой собственный findAll() в свой пользовательский репозиторий(независимо от того, есть ли он JPARespository или MongoRepository нет), он будет конфликтовать с findAll() предоставленным JPA.

изменение имени метода на List<InfoDto> findAllMakeProjection(); заставит JPA создавать запрос с использованием JPQL, поэтому он попытается извлечь свойства сущности из имени метода, если вы не определили запрос с @Query аннотацией.

Так что, если вы хотите это сделать, это должно быть что-то вроде findAllBySomeCondition или findBySomeCondition

экс : findByNameAndCompanyName(), findByEmail(), findAllByCompanyName()

Лучший способ-удалить List<InfoDto> findAll(); внутреннюю InfoRepository часть . Тем не менее, вы можете позвонить

 @Autowired
private InfoRepository infoRepository;

.......


infoRepository.findAll();
 

Так что это вернет a List<Info> .

И просто вы не можете повторно просмотреть список объектов DTO напрямую, MongoRepository как вы это сделали. Первоначально он вернет список объектов модели( List<Info> ). для того, чтобы вернуть список DTO,

 @Repository
public interface InfoRepository extends MongoRepository<Info, String> {
    @Query(value="select new com.foo.bar.InfoDto(i.name,i.companyName, i.address) from Info i")
    List<InfoDto> findAllInfos();
}
 

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