批量多字段唯一性校验
思路:
- 查询列表本身是否含有重复数据
- 新增修改分开考虑,新增只考虑数据库中是否有相同数据,修改不仅要考虑数据库中是否有相同数据,还要排除自身。
- 由于是批量校验,排除自身只需考虑所有修改操作均为修改自身非校验字段。
import lombok.AllArgsConstructor;
import lombok.Data;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
import java.util.stream.Collectors;
public class Main {
private static final String SUCCESS_MSG = "成功";
private static final String ERROR_MSG = "校验失败";
private static List<Human> humanDb = new ArrayList<>();
static {
humanDb.add(new Human(1L,"赵云", "子龙", "男"));
humanDb.add(new Human(2L,"关羽", "云长", "男"));
humanDb.add(new Human(3L,"曹操", "孟德", "男"));
}
public static void main(String[] args) {
List<Human> humans = new ArrayList<>();
humans.add(new Human(1L,"赵云", "子龙", "男", "长坂坡"));
humans.add(new Human(null,"诸葛亮", "孔明", "男"));
humans.add(new Human(null,"周瑜", "公瑾", "男"));
Main main = new Main();
main.unique(humans);
System.out.println(SUCCESS_MSG);
humans.add(new Human(null,"赵云", "子龙", "男"));
try {
main.unique(humans);
} catch (Exception e) {
System.out.println("catch 1");
System.out.println(e.getMessage());
}
humans.remove(humans.size() - 1);
humans.add(new Human(2L,"曹操", "孟德", "男"));
try {
main.unique(humans);
} catch (Exception e) {
System.out.println("catch 2");
System.out.println(e.getMessage());
}
}
public void unique(List<Human> humans) {
if (CollectionUtils.isEmpty(humans)) {
throw new RuntimeException(ERROR_MSG);
}
// 查询列表本身是否含有重复数据
Map<String, List<Human>> humanMap = humans.stream().collect(Collectors.groupingBy(this::getGroupKey));
humanMap.forEach((k, v) -> {
if (CollectionUtils.isNotEmpty(v) && v.size() > 1) {
throw new RuntimeException(ERROR_MSG);
}
});
List<Long> modifyIds = humans.stream().map(Human::getId)
.filter(Objects::nonNull).collect(Collectors.toList());
// 获取数据库所有重复数据
List<Long> dbIds = this.selectRepeatId(humans);
// 如果是新增重复,modifyIds 必不包含于 dbIds
// 如果是修改重复,分以下两种情况
// 1.修改操作均为修改自身非校验字段,modifyIds 必包含于 dbIds
// 2.修改操作不均为修改自身非校验字段,modifyIds 必不包含于 dbIds
if (!modifyIds.containsAll(dbIds)) {
throw new RuntimeException(ERROR_MSG);
}
}
private List<Long> selectRepeatId(List<Human> humans) {
List<String> keys = humans.stream().map(this::getGroupKey).collect(Collectors.toList());
return humanDb.stream()
.filter(v -> keys.contains(this.getGroupKey(v)))
.map(Human::getId).collect(Collectors.toList());
}
private String getGroupKey(Human human) {
return StringUtils.join(human.getName(), human.getWord(), human.getSex());
}
@AllArgsConstructor
@Data
static class Human {
private Long id;
private String name;
private String word;
private String sex;
private String other;
public Human(Long id, String name, String word, String sex) {
this.id = id;
this.name = name;
this.word = word;
this.sex = sex;
}
}
}