Spring Boot查询用户接口userName返回null问题求助
问题分析与解决方案
问题描述
集成Spring Security并实现用户创建、数据库接入后,调用查询所有用户的GET接口时出现以下异常:
- 仅
userName字段返回null,id和password字段值正常返回 UserRepository.findAll()方法返回的结果中userName同样为null,但数据库中该字段已存储有效数据
相关代码如下:
User实体类
@Entity @Table(name = "users") @Data @AllArgsConstructor @NoArgsConstructor public class User implements UserDetails{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Column(name = "userName") private String userName; @Column(name = "password") private String password; }
UserRepository
public interface UserRepository extends JpaRepository<User, Integer> { User findByUserName(String userName); }
UserManager
@Service @AllArgsConstructor public class UserManager { private UserRepository userRepository; private PasswordEncoderConfig passwordEncoderConfig; private ModelMapperService modelMapperService; public Result createUser(CreateUserRequest createUserRequest){ User checkUser = userRepository.findByUserName(createUserRequest.getUserName()); if(checkUser != null){ return new ErrorResult("User available"); } createUserRequest.setPassword(passwordEncoderConfig.bCryptPasswordEncoder().encode(createUserRequest.getPassword())); User user = this.modelMapperService.forRequest().map(createUserRequest, User.class); userRepository.save(user); return new SuccessResult("Add User"); } public DataResult<List<GetAllUsersResponse>> getAllUser(){ List<User> users = userRepository.findAll(); System.out.println(users); List<GetAllUsersResponse> responses = users.stream() .map(user->this.modelMapperService.forResponse() .map(user, GetAllUsersResponse.class)).collect(Collectors.toList()); return new SuccessDataResult<List<GetAllUsersResponse>>(responses, "Data"); } }
UserController
@RestController @RequestMapping("/user") @AllArgsConstructor public class UserController { private UserManager userManager; @PostMapping("/add") public Result createUser(@RequestBody CreateUserRequest createUserRequest) { return userManager.createUser(createUserRequest); } @GetMapping("/getall") public DataResult<List<GetAllUsersResponse>> getAllUser() { return userManager.getAllUser(); } }
GetAllUsersResponse
@Data @NoArgsConstructor @AllArgsConstructor public class GetAllUsersResponse { private int id; private String userName; private String password; }
ModelMapperManager
@AllArgsConstructor public class ModelMapperManager implements ModelMapperService{ private ModelMapper modelMapper; @Override public ModelMapper forResponse() { this.modelMapper.getConfiguration() .setAmbiguityIgnored(true) .setMatchingStrategy(MatchingStrategies.LOOSE); return this.modelMapper; } @Override public ModelMapper forRequest() { this.modelMapper.getConfiguration() .setAmbiguityIgnored(true) .setMatchingStrategy(MatchingStrategies.STANDARD); return this.modelMapper; } }
原因分析
核心问题在于User实体类实现了UserDetails接口,但未重写接口要求的getUsername()方法:
- UserDetails接口定义了
String getUsername();方法,用于获取用户名 - 实体类字段名为
userName,Lombok的@Data注解生成的getter方法是getUserName(),而非getUsername() - JPA/Spring Security在映射数据时,会优先识别UserDetails接口的
getUsername()方法,但该方法未被正确实现,导致无法读取userName字段的值
额外排查点:数据库字段名与@Column(name = "userName")的配置是否完全匹配(包括大小写),部分数据库对字段名大小写敏感,若数据库实际字段为username/USER_NAME等,会导致映射失败。
解决方案
1. 重写UserDetails的getUsername()方法
修改User实体类,明确重写getUsername()方法并返回userName字段,同时实现UserDetails接口的其他必要方法:
@Entity @Table(name = "users") @Data @AllArgsConstructor @NoArgsConstructor public class User implements UserDetails{ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private int id; @Column(name = "userName") private String userName; @Column(name = "password") private String password; // 重写UserDetails的getUsername方法 @Override public String getUsername() { return this.userName; } @Override public boolean isAccountNonExpired() { return true; } @Override public boolean isAccountNonLocked() { return true; } @Override public boolean isCredentialsNonExpired() { return true; } @Override public boolean isEnabled() { return true; } @Override public Collection<? extends GrantedAuthority> getAuthorities() { // 根据实际需求配置权限,此处默认返回空集合 return new ArrayList<>(); } }
2. 校验数据库字段与实体类映射一致性
- 确认数据库中用户表的字段名与
@Column注解的name属性完全一致,若数据库字段为下划线命名(如user_name),可修改注解为@Column(name = "user_name") - 若使用MySQL,可检查
lower_case_table_names配置,确保字段名大小写处理符合预期
验证方案
修改代码后重启服务,重新调用/user/getall接口,确认userName字段能正常返回数据库中的值;同时查看UserRepository.findAll()的打印结果,确认userName不再为null。
内容的提问来源于stack exchange,提问作者trangela
相关产品推荐
相关产品推荐

