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
相关产品推荐
相关产品推荐

