package com.mydreamjob.auth; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Modifying; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import java.time.LocalDateTime; import java.util.List; import java.util.Optional; @Repository public interface SmsVerificationCodeRepository extends JpaRepository { @Modifying(clearAutomatically = true, flushAutomatically = true) @Query("UPDATE SmsVerificationCode c SET c.used = true " + "WHERE c.id = :id AND c.used = false AND c.expiredAt > :now " + "AND c.attempts < c.maxAttempts") int consumeIfValid(@Param("id") Long id, @Param("now") LocalDateTime now); @Modifying(clearAutomatically = true, flushAutomatically = true) @Query("UPDATE SmsVerificationCode c SET c.attempts = c.attempts + 1 " + "WHERE c.id = :id AND c.used = false AND c.expiredAt > :now " + "AND c.attempts < c.maxAttempts") int incrementFailedAttemptsIfValid(@Param("id") Long id, @Param("now") LocalDateTime now); List findByPhoneAndCreatedAtAfter(String phone, LocalDateTime after); /** * 按手机号+用途查询,按创建时间降序返回(最新在前) */ List findByPhoneAndPurposeOrderByCreatedAtDesc(String phone, String purpose); /** * 查询手机号+用途下最新的未使用验证码 */ @Query("SELECT c FROM SmsVerificationCode c WHERE c.phone = :phone AND c.purpose = :purpose AND c.used = false ORDER BY c.createdAt DESC") java.util.stream.Stream streamLatestUnusedByPhoneAndPurpose(@Param("phone") String phone, @Param("purpose") String purpose); /** * 按手机号+用途查询已使用的验证码(用于测试中取旧验证码) */ List findByPhoneAndPurposeAndUsedTrueOrderByCreatedAtDesc(String phone, String purpose); }