1

I'm developing an API with Spring boot where I encounter this issue. I want to generate 6 digits number every time there's a new register to insert into column referral_code, where it has to be UNIQUE. Here is my entity

@Entity
public class StoreEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "store_name", columnDefinition = "varchar(255) default '' not null")
    private String storeName;

    @Column(name = "referral_code", columnDefinition = "varchar(255) default '' not null")
    private String referralCode;

    @Column(name = "created_at", columnDefinition = "timestamp default current_timestamp not null")
    private Timestamp createdAt = new Timestamp(System.currentTimeMillis());
}

in my register service, I have created a generate a random number with this method (reference)

protected String createRandomReferralCode(){
        Random r = new Random();
        int numbers = 100000 + (int)(r.nextFloat() * 899900);
        return String.valueOf(numbers);
    }

so when the new store register, I'm getting the number from the above function and set it to referralCode. Here's the register function

public StoreEntity register(StoreDto storeDto) {
        StoreEntity storeEntity = new StoreEntity();

        //----call to generate random 6 digit code-----
        String generateReferralCode = createRandomReferralCode();

        storeEntity.setStoreName(storeDto.getStoreName());
        storeEntity.setReferralCode(generateReferralCode);

        return storeDao.save(storeEntity);
}

now, my problem is how can we ensure that the number getting from the above function createRandomReferralCode() always generates a unique one?

ATTEMPTS: in my repository, I've created a function findReferralCode, to check if the referral code already exists in the table row; however, doing so seems to slow down the application's performance.

@Repository
public interface StoreDao extends JpaRepository<StoreEntity, Long> {
    StoreEntity findReferralCode(String referralCode);
}
munirot
  • 97
  • 5
  • 16
  • 6
    Have you considered that 6 digits will be a very limited pool of codes? Also, what's the point of randomizing if your range is 000000 to 999999 if you simply could have a identity counter running from 000000 to 999999? Sounds like security by obscurity to me. – Filburt Oct 08 '20 at 08:00
  • 2
    Does the number need to be random? Otherwise you could simply increment a register. – Déjà vu Oct 08 '20 at 08:03
  • @e2-e4 if we don't randomize it and simply increasing it then anyone can guess and use the code right? that's the whole idea of generating a unique number. – munirot Oct 08 '20 at 08:10
  • @Filburt I forgot to mention that every time the code has been used, we will generate a new one to replace that used one. – munirot Oct 08 '20 at 08:17
  • 3
    6 digits is not much. Applying a hash to an incrementing number (with a 'salt' stuck to it, for instance), sha-256... Sure that's a large key but there won't be collisions, and nobody will guess the original number for decades – Déjà vu Oct 08 '20 at 08:34
  • 2
    So as @Filburt says, it is security by obscurity. Personally I would use a random uuid – jr593 Oct 08 '20 at 08:46
  • 3
    The only way to be completely sure there won't be collisions is by checking on the database; you could add an index for the column in order to speed it up. That being said, 6 numeric digits will run out pretty quickly, and even if it doesn't, there will be a point where there will be so many combinations present in the database, that there will be a very high chance that some will be found out by random guessing. – Haroldo_OK Oct 08 '20 at 09:57

0 Answers0