一尘不染

Spring Boot锁定代码以获取唯一的ID

spring-boot

我写了一个必须返回唯一字符串的控制器。要求是,即使经过数年并且即使代码将扩展到更多VM,此控制器的两次调用也绝不能返回相同的String。

我的问题是以下代码是否正确达到声明的目的,或者您是否有任何提示。

控制器:

@RestController
public class UtilityController {

    @Autowired
    UtilityServices utilityServices;

    @GetMapping("/uniqueIdentifier")
    @ResponseBody
    public String uniqueIdentifier() {
        return utilityServices.getUniqueIdentifier();
    }

服务:

@Service
public class UtilityServices {

    @Autowired
    private UniqueIdRepository uniqueIdRepository;

    @Transactional
    public String getUniqueIdentifier() {
       String uniqueId = RandomString.getSecureRandomString();
       while (uniqueIdRepository.existsById(uniqueId)) {
           uniqueId = RandomString.getSecureRandomString();
       }
       uniqueIdRepository.save(new UniqueId(uniqueId));
       return uniqueId;
    }
}

实体:

@Entity
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@EqualsAndHashCode
@ToString
public class UniqueId implements Serializable {

    @Id
    private String uniqueId;

}

仓库:

public interface UniqueIdRepository extends CrudRepository<UniqueId, String> {

}

就这样。我忽略了RandomString该类的代码,因为它在这种情况下不相关:我基于编写了一个代码SecureRandom,很可能每次返回一个不同的String时,但是我对此没有保证。假设我的RandomString.getSecureRandomString()方法迟早可以返回相同的String。

我不确定@Transactional注解是否保证该getUniqueIdentifier()方法永远不会抛出错误。


阅读 444

收藏
2020-05-30

共1个答案

一尘不染

根据您的情况,更好的主意是使用UUID

因此,任何人都可以创建一个UUID并几乎可以肯定地使用它来标识某些内容,即该标识符不会重复已经或将要创建的用于标识其他内容的标识符。因此,以后可以将由独立各方用UUID标记的信息合并到单个数据库中,或在同一信道上传输,且重复的可能性很小。

@Service
public class UtilityServices {
    @Autowired
    private UniqueIdRepository uniqueIdRepository;

    @Transactional
    public String getUniqueIdentifier() {
       String uniqueId = String.format("%s-%s",
            RandomStringUtils.randomAlphanumeric(4),
            UUID.randomUUID().toString().replace("-", "")
       );
       // you could left this check 
       while (uniqueIdRepository.existsById(uniqueId)) {
           uniqueId = UUID.randomUUID().toString().replace("-", "");
       }
       uniqueIdRepository.save(new UniqueId(uniqueId));
       return uniqueId;
    }
}

顺便说一句, 您可以使用@DataModel:

@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
public class UniqueId implements Serializable {
    private static final long serialVersionUID = 0L;
    @Id
    private String uniqueId;   
}

而且不要忘记serialVersionUID

2020-05-30