我的group类有一个令牌属性,我的Java代码用它来验证是否应该允许操作,具体取决于谁试图调用它。我有用于生成字母数字键并在组构造函数中分配令牌的代码。例如
public Group(){
super();
this.token = Crypt.generate(30); // length of key
}
这工作正常,我的数据库现在很小,但是,我认为生成的密钥有可能已经存在。在这种情况下,当我尝试将数据插入数据库时,我将收到org.springframework.dao.DataIntegrityViolationException。我讨论了在try / catch中包装每个insert语句然后再次尝试,但我还需要检查本可以成功保存的记录,因为我现在通常在批处理中插入Group表。
List<Group> groups = new ArrayList<>();
groups.add(new Group("grp1");
groups.add(new Group("grp2");
groups.add(new Group("grp3");
try {
groupRepository.save(groups);
} catch (DataIntegrityViolationException e){
List<Group> secondAttemptGroups = new ArrayList<>();
for(Group g : groups){
Group insertedGroup = groupRepository.findByName(g.getName());
if(insertedGroup == null){
secondAttempGroups.add(new Group(g.getName());
}
}
if(!(secondAttempGroups.isEmpty()){
try {
group.repository.save(secondAttempGroups);
} catch(DataIntegrityViolationException e2){
// ...
}
}
}
必须有更好的方法来防止这种情况发生。
答案 0 :(得分:0)
在仔细考虑了这个问题后,我认为我可以使用Spring JPA验证令牌,而无需将整个数据库放入我的代码中。这就是我想出来的。
public static List<Group> validateTokens(List<Group> groups, int iterations){
LOGGER.info("Validating Tokens: Iteration #" + iterations);
boolean dirtyToken = false;
// Validate that the groups provided don't contain duplicate tokens.
Set<String> tokenSet = new HashSet<>();
for(Group g1 : groups){
tokenSet.add(g1.getToken());
}
if(tokenSet.size() != groups.size()){
dirtyToken = true;
for(Group g2 : groups){
g2.setToken(Crypt.generate(TOKEN_LENGTH));
}
}
// Validate that the groups provided don't contain tokens that are already present in the database.
for(Group g3 : groups){
Group databaseGroup = groupRepository.findByToken(g3.getToken());
if(databaseGroup != null){
dirtyToken = true;
g3.setToken(Crypt.generate(TOKEN_LENGTH));
}
}
if(dirtyToken && iterations-- > 0){
return validateTokens(groups, iterations);
}
else if(dirtyToken && iterations < 1){
LOGGER.warn("Tokens could not be validated and Unique Constraint Violtation will be thrown. " +
"Perhaps it's time to increase the token length from " + TOKEN_LENGTH + ".");
return groups;
}
else {
return groups;
}
上面的递归方法有效。 @Robert我没有考虑数据库生成的值,但在开发过程中我将仅使用h2作为我的数据库。这种方法是否仍然可行,也许更容易?