批量多字段唯一性校验
思路:
- 查询列表本身是否含有重复数据
- 新增修改分开考虑,新增只考虑数据库中是否有相同数据,修改不仅要考虑数据库中是否有相同数据,还要排除自身。
- 由于是批量校验,排除自身只需考虑所有修改操作均为修改自身非校验字段。
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 必不包含于 dbIdsif (!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@Datastatic 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;}}
}