仁者爱人,有礼者敬人。爱人者,人恒爱之;敬人者,人恒敬之。——孟子
前两天写了关联表更新封装
今天写个另一种类型的
public static <T, K extends Comparable<? super K> & Serializable, A, L extends Comparable<? super L> & Serializable> BaseDbBO<A> saveAttach(AttachBO<T, K, A> bo) { val mainList = bo.getMainList(); val mainKeys = Steam.of(mainList).map(bo.getMainKey()).toList(); val attachKeyExecutable = LambdaHelper.resolve(bo.getAttachKey()); val attachKeySetter = getSetter(attachKeyExecutable); val compareGetterSetterMap = Steam.of(bo.getAttachCompares()) .toMap(Function.identity(), MpUtil::getSetter); val attachListFromClient = Steam.of(mainList).flat(m -> Steam.of(bo.getAttachGetter().apply(m)) .peek(a -> attachKeySetter.accept(a, bo.getMainKey().apply(m)))) .toList(); val attachGetterExecutable = LambdaHelper.resolve(bo.getAttachGetter()); val field = ReflectHelper.getField(attachGetterExecutable.getClazz(), BeanHelper.getPropertyName(attachGetterExecutable.getName())); Class<A> genericType = (Class<A>) ReflectHelper.getGenericTypes(field.getGenericType())[0]; val attachListFromDb = Many.of(bo.getAttachKey()).in(mainKeys) .value(v -> { val vo = ((SerSupp<A>) genericType::newInstance).get(); BeanUtils.copyProperties(v, vo); return vo; }) .query(); val attachTableInfo = TableInfoHelper.getTableInfo(attachKeyExecutable.getClazz()); val attachPrimaryKey = MpUtil.<A, L>getGetter((Class<A>) attachKeyExecutable.getClazz(), attachTableInfo.getKeyProperty()); val attachKeyListFromDb = Steam.of(attachListFromDb).map(attachPrimaryKey).toList(); if (attachKeyListFromDb.isEmpty()) { bo.setWillInsertList(attachListFromClient); bo.setDataList(attachListFromClient); return bo; } if (attachListFromClient.isEmpty()) { bo.setWillDeleteList(attachListFromDb); return bo; } val mainIdAttachesMapFromDb = Steam.of(attachListFromDb).group(bo.getAttachKey()); val mainIdAttachesMapFromClient = Steam.of(attachListFromClient).group(bo.getAttachKey()); mainKeys.forEach(mainKey -> { val attachesFromDb = mainIdAttachesMapFromDb.getOrDefault(mainKey, emptyList()); val attachesFromClient = mainIdAttachesMapFromClient.getOrDefault(mainKey, emptyList()); if (attachesFromDb.isEmpty() && attachesFromClient.isEmpty()) { return; } if (attachesFromDb.isEmpty()) { bo.getWillInsertList().addAll(attachesFromClient); return; } if (attachesFromClient.isEmpty()) { bo.getWillDeleteList().addAll(attachesFromDb); return; } val idAttachMapFromDb = Steam.of(attachesFromDb).toMap(attachPrimaryKey); // insert Steam.of(attachesFromClient) .filter(attach -> { val id = attachPrimaryKey.apply(attach); return Objects.isNull(id) || !idAttachMapFromDb.containsKey(id); }) .forEach(bo.getWillInsertList()::add); val idAttachMapFromClient = Steam.of(attachesFromClient) .filter(attach -> { val id = attachPrimaryKey.apply(attach); return Objects.nonNull(id); }).toMap(attachPrimaryKey); // remove val attachKeysFromDb = idAttachMapFromDb.keySet(); Steam.of(attachKeysFromDb) .filter(id -> !idAttachMapFromClient.containsKey(id)) .map(idAttachMapFromDb::get) .forEach(bo.getWillDeleteList()::add); // modify attachKeysFromDb.retainAll(idAttachMapFromClient.keySet()); attachKeysFromDb.forEach(attachKey -> { val attachFromDb = idAttachMapFromDb.get(attachKey); val attachFromClient = idAttachMapFromClient.get(attachKey); if (Objects.nonNull(attachFromDb) && Objects.nonNull(attachFromClient)) { Steam.of(bo.getAttachCompares()).forEach(ac -> { val value = ac.apply(attachFromClient); if (!Objects.equals(value, ac.apply(attachFromDb))) { val executable = LambdaHelper.resolve((Serializable) ac); val setter = compareGetterSetterMap.get(ac); val fieldType = ReflectHelper.getField(executable.getClazz(), BeanHelper.getPropertyName(executable.getName())).getType(); setter.accept(attachFromDb, value); if (isComparable(fieldType) && (!bo.getWillUpdateList().contains(attachFromDb))) { bo.getWillUpdateList().add(attachFromDb); } } }); } }); }); bo.setAfterExecuted(b -> { attachListFromDb.removeIf(bo.getWillDeleteList()::contains); attachListFromDb.addAll(bo.getWillInsertList()); val idAttachMap = Steam.of(attachListFromDb).toMap(attachPrimaryKey); attachListFromClient.forEach(data -> { val primaryKey = attachPrimaryKey.apply(data); idAttachMap.put(primaryKey, data); }); bo.setDataList(new ArrayList<>(idAttachMap.values())); }); return bo; }
使用起来也差不多
val cards = MpUtil.saveAttach(new AttachBO<ProductDetailVO, Long, ProductDetailCardVO>() {{ setMainList(vos); setMainKey(ProductDetailVO::getId); setAttachKey(ProductDetailCardVO::getDetailId); setAttachGetter(ProductDetailVO::getCardList); setAttachCompares(Lists.of( ProductDetailCardVO::getType, ProductDetailCardVO::getCanAdd, ProductDetailCardVO::getViewMode, ProductDetailCardVO::getDataList )); }}).execute();