Spring Boot中MongoRepository初始化失败及自定义Repository依赖缺失问题
问题:Spring Data MongoDB Repository 查询生成失败及自定义Repository Bean找不到
我搜了大量相关问答,但每个场景都不一样,折腾一小时没找到解决方案,求指引。
初始错误信息
报错核心是org.springframework.beans.factory.UnsatisfiedDependencyException:创建appUserService Bean时,构造参数0依赖的appUserRepository初始化失败。嵌套异常显示Spring Data无法为AppUserRepository的enableAppUser方法生成查询,提示AppUser类中没有enableAppUser属性。完整错误栈:
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'appUserService' defined in file [D:\portfolio\TripAdvisorApp\target\classes\demo\tripadvisorapp\security\appuser\AppUserService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'appUserRepository' defined in demo.tripadvisorapp.security.appuser.AppUserRepository defined in @EnableMongoRepositories declared on MongoRepositoriesRegistrar.EnableMongoRepositoriesConfiguration: Invocation of init method failed; nested exception is org.springframework.data.repository.query.QueryCreationException: Could not create query for public abstract int demo.tripadvisorapp.security.appuser.AppUserRepository.enableAppUser(java.lang.String); Reason: No property 'enableAppUser' found for type 'AppUser'; nested exception is org.springframework.data.mapping.PropertyReferenceException: No property 'enableAppUser' found for type 'AppUser' ...(省略后续栈信息)
相关代码
AppUserService
@Service @AllArgsConstructor public class AppUserService implements UserDetailsService { private final static String USER_NOT_FOUND_MESSAGE = "User with email %s not found"; private final AppUserRepository appUserRepository; private final BCryptPasswordEncoder bCryptPasswordEncoder; private final ConfirmationTokenService confirmationTokenService; @Override public UserDetails loadUserByUsername(String email) throws UsernameNotFoundException { return appUserRepository.findByEmail(email).orElseThrow(() -> new UsernameNotFoundException(String.format(USER_NOT_FOUND_MESSAGE, email))); } public String signUpUser(AppUser appUser) { boolean userExists = appUserRepository.findByEmail(appUser.getEmail()) .isPresent(); if (userExists) { throw new IllegalStateException("Email already taken"); } String encodedPassword = bCryptPasswordEncoder.encode(appUser.getPassword()); appUser.setPassword(encodedPassword); appUserRepository.save(appUser); String token = UUID.randomUUID().toString(); ConfirmationToken confirmationToken = new ConfirmationToken( token, LocalDateTime.now(), LocalDateTime.now().plusMinutes(15), appUser ); confirmationTokenService.saveConfirmationToken(confirmationToken); return token; } public int enableAppUser(String email) { return appUserRepository.enableAppUser(email); } }
AppUserRepository
@Transactional(readOnly = true) @Repository public interface AppUserRepository extends MongoRepository<AppUser, Long> { Optional<AppUser> findByEmail(String email); @Transactional int enableAppUser(String email); }
AppUser
@Getter @Setter @EqualsAndHashCode @NoArgsConstructor @Document("app_user") public class AppUser implements UserDetails { @Id private String id; private String firstName; private String lastName; private String email; private String password; private AppUserRole appUserRole; private Boolean locked = false; private Boolean enabled = false; public AppUser(String firstName, String lastName, String email, String password, AppUserRole appUserRole) { this.firstName = firstName; this.lastName = lastName; this.email = email; this.password = password; this.appUserRole = appUserRole; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { SimpleGrantedAuthority authority = new SimpleGrantedAuthority(appUserRole.name()); return Collections.singletonList(authority); } @Override public String getPassword() { return password; } @Override public String getUsername() { return email; } public String getFirstName() { return firstName; } public String getLastName() { return lastName; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return !locked; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return enabled; } }
尝试解决及新问题
- 尝试添加
@ComponentScan注解:
@ComponentScan(basePackages = {"demo.tripadvisorapp.security.token"}) @ComponentScan(basePackages = {"demo.tripadvisorapp.security.appuser"})
但问题未解决。
- 按照建议创建自定义Repository后,出现新错误:
Parameter 1 of constructor in demo.tripadvisorapp.security.appuser.impl.AppUserServiceImpl required a bean of type 'demo.tripadvisorapp.security.token.CustomizedUserRepository' that could not be found. Action: Consider defining a bean of type 'demo.tripadvisorapp.security.token.CustomizedUserRepository' in your configuration
解决方案指引
针对第一个错误(查询生成失败)
Spring Data MongoDB的方法命名规则基于实体属性,enableAppUser不符合规则——实体里只有enabled属性。可以用两种方式修正:
- 方法命名规范修正:
改成符合更新操作的命名,让Spring自动生成查询:
调用时传入@Transactional int updateEnabledByEmail(boolean enabled, String email);true和目标邮箱即可。 - 手动指定查询语句:
用@Query注解直接写MongoDB更新语句:@Transactional @Query(value = "{'email': ?0}", update = "{$set: {'enabled': true}}") int enableAppUser(String email);
针对第二个错误(自定义Repository Bean找不到)
- 检查
@EnableMongoRepositories的basePackages是否包含自定义Repository所在的demo.tripadvisorapp.security.token包,确保Spring能扫描到该接口。 - 若自定义Repository是「接口+实现类」模式:
- 实现类默认命名规则为「接口名+Impl」,比如
CustomizedUserRepositoryImpl,否则需要在接口上用@RepositoryDefinition指定实现类。 - 实现类要加
@Repository或@Component注解,让Spring将其纳入Bean管理。
- 实现类默认命名规则为「接口名+Impl」,比如
- 检查
AppUserServiceImpl的构造参数注入是否正确,确保依赖的CustomizedUserRepository是Spring管理的合法Bean。
内容的提问来源于stack exchange,提问作者Stefan Jankovic
相关产品推荐
相关产品推荐

