为什么我在存储库中收到错误 "No property found"?

Why I get error "No property found" on repository?

我为我的项目使用 java spring 和 mongodb 存储库。

这里是存储库定义:

@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;
}

这是 InfoDto class 定义:

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

当我开始 运行 项目时,IU 得到这个错误:

'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!

知道我为什么会收到错误消息以及如何解决它吗?

这里发生的是 findAll() 是为 Spring Data JPA 保留的默认内置存储库方法名称。因此,如果您在自定义存储库中引入自己的 findAll()(无论是 JPARespository 还是 MongoRepository),它将与 JPA 提供的 findAll() 发生冲突。

将方法名称更改为 List<InfoDto> findAllMakeProjection(); 将使 JPA 使用 JPQL 构建查询,因此它将尝试从方法名称中提取实体属性,除非您使用 @Query 注释定义查询。

因此,如果您想这样做,它应该类似于 findAllBySomeConditionfindBySomeCondition

例如:findByNameAndCompanyName(), findByEmail(), findAllByCompanyName()

最好的方法是删除 InfoRepository 里面的 List<InfoDto> findAll();。不过,您可以致电

@Autowired
private InfoRepository infoRepository;

.......


infoRepository.findAll();

所以这将 return 一个 List<Info>

而且您不能像以前那样直接通过 MongoRepository 返回 DTO 对象列表。它最初是 return 模型对象列表 (List<Info>)。为了 return 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 的映射地址做一些额外的事情。

List<T> findAll() 是 MongoRepository 接口中提供的方法,因此无法在子接口中更改其 return 类型。最多,您可以将 return 类型更改为 List 实现,例如 ArrayList<T>LinkedList<T>.

如果将方法名称更改为 List<InfoDto> findAllMakeProjection(),Spring Data MongoDB 将尝试使用 属性 名称构建查询,但没有 属性 命名,所以它会抛出一个错误。

但是可以在方法名的By字之前加任何东西,例如findAllByfindEverythingByfindDataByBy 之后的任何内容都将用作过滤器(where 条件),如果我们在 By 之后不添加任何内容,它将像 findAll(无过滤器)

一样工作

因此,相应地更改方法名称,您将能够 运行 您的查询。