You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot/SpringSecurity登录用户无法更新信息,无报错但数据库未变更

Spring用户更新信息无法持久化(无报错)

问题根源

你的Controller里存在致命逻辑错误:前端提交的表单数据已经绑定到user参数,但你直接用数据库查询的原始用户覆盖了这个参数,导致Service接收的是未修改的原始用户,自然不会有任何更新写入数据库。

看这段错误代码:

// 前端提交的user已包含修改后的firstName/lastName,但此处直接被原始用户覆盖
user = repo.findByEmail(principal.getName());

修复方案

保留前端提交的user对象中的修改字段,仅通过数据库查询获取原始用户的完整数据,再将修改字段同步到原始用户后执行保存。同时注意处理密码字段:如果前端留空,不要覆盖原始密码。

修正后的代码

Controller类

@PostMapping("/myAccount/update")
public String updateAccount(User userForm, RedirectAttributes redirectAttributes, Principal principal){
    System.out.println("Updating user details...");
    // 从数据库获取原始用户数据
    User userInDB = repo.findByEmail(principal.getName());
    // 将前端修改的字段同步到原始用户
    userInDB.setFirstName(userForm.getFirstName());
    userInDB.setLastName(userForm.getLastName());
    // 密码字段处理:仅当前端输入新密码时才更新
    if (userForm.getPassword() != null && !userForm.getPassword().isEmpty()) {
        // 注意:生产环境必须加密密码,禁止明文存储
        userInDB.setPassword(userForm.getPassword());
    }
    User updatedUser = service.updateAccount(userInDB);

    if (updatedUser == null) {
        System.out.println("Error updating user details.");
    } else {
        redirectAttributes.addFlashAttribute("message", "Details Updated!");
        return "redirect:/myAccount";
    }

    return "redirect:/myAccount";
}

优化后的Service类(简化逻辑)

在@Transactional注解下,修改从数据库获取的持久化状态对象后,事务提交时Hibernate会自动同步到数据库,手动调用repo.save()并非必须(但调用也不影响):

@Transactional
public User updateAccount(User userToUpdate){
    System.out.println("Fetching user with id: " + userToUpdate.getId());

    Optional<User> optionalUser = repo.findById(userToUpdate.getId());
    if(!optionalUser.isPresent()){
        System.out.println("User not found.");
        return null;
    }

    User userInDB = optionalUser.get();
    System.out.println("User fetched: " + userInDB);

    // 同步修改字段
    userInDB.setFirstName(userToUpdate.getFirstName());
    userInDB.setLastName(userToUpdate.getLastName());
    // 密码字段补充处理
    if (userToUpdate.getPassword() != null && !userToUpdate.getPassword().isEmpty()) {
        userInDB.setPassword(userToUpdate.getPassword());
    }
    System.out.println("Updated user ready to persist: " + userInDB);

    // 事务提交时自动同步数据库,save方法可省略
    User savedUser = repo.save(userInDB);
    System.out.println("User saved: " + savedUser);

    return savedUser;
}

补充说明

  1. 控制台输出看似正常是因为打印的是同一个对象的内存地址,但对象字段值实际为原始数据,并未被前端修改。
  2. 生产环境务必使用加密工具(如BCryptPasswordEncoder)处理密码,禁止明文存储。
  3. 可使用ModelMapper等工具类简化字段拷贝操作,避免手动编写大量set方法。

内容的提问来源于stack exchange,提问作者James Coding

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 16:55:22