Reputation: 13636
I use java spring and mongodb repository for my project.
Here is repository defeniton:
@Repository
public interface InfoRepository extends MongoRepository<Info, String> {
List<InfoDto> findAll();
}
Here is Info Defenition:
@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;
}
Here is InfoDto class defenition:
@Data
public class InfoDto {
private String name;
private String companyName;
private Address address;
}
When I start to run the project IU get this error:
'findAll()' in '...repository.InfoRepository' clashes with 'findAll()'
in 'org.springframework.data.mongodb.repository.MongoRepository'; attempting to use incompatible return type
To prevent the clashe I change the name of the repository function from this:
List<InfoDto> findAll();
to this:
List<InfoDto> findAllMakeProjection();
But after I make changes above and run the function, I get this error:
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!
Any idea why I get the error and how to fix it?
Upvotes: 0
Views: 703
Reputation: 1382
List<T> findAll()
is a method provided in MongoRepository Interface, so it's not possible to change its return type in sub-interfaces. At most, you can change the return type to List implementations like ArrayList<T>
or LinkedList<T>
.
If you change the method name to List<InfoDto> findAllMakeProjection()
, Spring Data MongoDB will try to build the query using the property name, but there is no property named so it will throw an error.
But it is allowed to add anything before By
word in the method name, e.g. findAllBy
, findEverythingBy
, findDataBy
. Anything after By
will work as filters(where condition) and if we don't add anything after By
, it will work like findAll
(no filters)
So, change the method name accordingly and you will be able to run your query.
Upvotes: 2
Reputation: 1099
What happens in here is findAll()
is a default built in repository method name reserved for Spring Data JPA. so if you introduce your own findAll()
inside your custom Repository(no matter it is JPARespository
or MongoRepository
) it will clash with the findAll()
provided by JPA.
changing the method name to List<InfoDto> findAllMakeProjection();
will make JPA to build the query using JPQL so it will try to extract entity properties from the method name unless you defined the query with @Query
annotation.
So if you want to do so it should be something like findAllBySomeCondition
or findBySomeCondition
ex : findByNameAndCompanyName(), findByEmail(), findAllByCompanyName()
Best way is to remove the List<InfoDto> findAll();
inside InfoRepository
. Still, you can call
@Autowired
private InfoRepository infoRepository;
.......
infoRepository.findAll();
So this will return a List<Info>
.
And simply you cannot reurn a List of DTO objects directly through MongoRepository
like you did. It will originally return a List of model objects(List<Info>
). in order to return a list of DTOs,
@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();
}
you might need to bit tricky and do additional things with mapping address from entity to DTO.
Upvotes: 1