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

SpringBoot中如何根据用户邮箱将OTP存入对应数据库记录行

问题根因

Spring Data JPA的save()方法默认逻辑为:传入的实体对象如果无主键值、或主键值对应记录在数据库中不存在,会直接执行INSERT语句新增记录;只有传入的实体携带数据库中已存在的主键值时,才会执行UPDATE更新对应行。
你当前的代码直接new了一个全新的空SessionHandling对象,仅设置了OTP字段就调用save,这个新对象没有关联任何已有用户的主键ID,也没有绑定传入的邮箱参数,所以每次调用都会插入一条仅OTP字段有值、其余字段全为NULL的新记录,完全不会匹配已有邮箱对应的用户行。

修复方案
  • 先在你的Repository接口中添加按邮箱查询已有用户记录的方法,方法名要和实体类的字段名匹配:
// 实体类中邮箱字段名为emailid,所以查询方法写为findByEmailid
Optional<SessionHandling> findByEmailid(String email);
  • 修改sendOtp方法的持久化逻辑,不要新建空对象,先查询对应邮箱的已有用户记录,再更新该记录的OTP字段:
public String sendOtp(@RequestParam("email") String email) {
        
    String otp = RandomString.make(8);
    
    String subject = "OTP from session-handling-proj By Harshit";
    String toEmail = email;
    String body = "OTP :  " + otp;
    
    // 根据传入邮箱查询已存在的用户记录,查不到直接抛出参数异常
    SessionHandling sessionHandling = repo.findByEmailid(email)
            .orElseThrow(() -> new IllegalArgumentException("传入邮箱不存在对应用户"));
    // 仅更新已有记录的OTP字段
    sessionHandling.setOneTimePassword(otp);
    // 此时对象携带数据库已存在的主键ID,save会执行UPDATE而非INSERT
    repo.save(sessionHandling);
    
    this.emailService.sendMail(toEmail, subject, body);
    return "success";
}
优化建议
  • 存储OTP时可以同步给time字段赋值当前时间戳,后续做OTP有效性校验时,可以直接判断当前时间与生成时间的差值是否超出你设置的有效期。
  • 增加邮箱格式校验、接口频率限制,避免被恶意调用刷邮件发送接口。

内容的提问来源于stack exchange,提问作者Harshit Toxia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 18:43:01