#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.