您的位置:首页 > 汽车 > 新车 > 2022年8月国内重大新闻_微信营销方式有哪些_百度联盟app_品牌策划运营公司

2022年8月国内重大新闻_微信营销方式有哪些_百度联盟app_品牌策划运营公司

2025/4/1 6:36:10 来源:https://blog.csdn.net/qq_40570699/article/details/144131840  浏览:    关键词:2022年8月国内重大新闻_微信营销方式有哪些_百度联盟app_品牌策划运营公司
2022年8月国内重大新闻_微信营销方式有哪些_百度联盟app_品牌策划运营公司

系列文章目录

之前的系列文章:
一、概述篇:https://blog.csdn.net/qq_40570699/article/details/143024984
二、入门篇:https://blog.csdn.net/qq_40570699/article/details/143905723
三、进阶篇:

  • 1.批量导入数据

文章目录

  • 系列文章目录
  • 需求场景
  • 一、解决思路
  • 二、代码
    • 1.将属性更新的逻辑封装为一个通用的工具类,可以处理任意类型的对象。
    • 2.在服务端使用上述工具方法封装节点更新逻辑,无需手动处理反射或循环。
    • 3.进一步抽象为通用接口
    • 4.服务扩展
    • 5.代码调用
  • 三、总结


需求场景

代码版本及依赖在该系列入门篇已阐明

1.我需要使用Java向Neo4j新增一批数据。若数据已存在则更新非空属性的值,若不存在则新增节点数据。
2.我的节点实体很多,我想要个能够高复用的抽象代码。


一、解决思路

基于我们对ES的更新思路一致,Neo4j提供的saveAll也需要我们先查询后更新。所以我们先将我们插入的数据分类为已存在数据不存在数据对应的修改新增

二、代码

1.将属性更新的逻辑封装为一个通用的工具类,可以处理任意类型的对象。

代码如下(示例):

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Objects;public class ObjectUtils {/*** 更新目标对象的非空属性* * @param source 源对象,包含最新属性值* @param target 目标对象,将被更新*/public static <T> void updateNonNullProperties(T source, T target) {if (source == null || target == null) {throw new IllegalArgumentException("Source and target objects must not be null");}Field[] fields = source.getClass().getDeclaredFields();for (Field field : fields) {try {field.setAccessible(true);Object value = field.get(source);if (value != null) {field.set(target, value);}} catch (IllegalAccessException e) {throw new RuntimeException("Error updating properties", e);}}}/*** 将一批实体更新到数据库(适用于批量更新场景)** @param sources 待更新的源对象集合* @param existingEntities 已存在的实体集合* @param getIdentifierFunction 用于提取唯一标识符的方法引用* @param saveFunction 保存方法引用* @param <T> 实体类型* @param <ID> 唯一标识符类型*/public static <T, ID> void saveOrUpdateEntities(Collection<T> sources,Collection<T> existingEntities,java.util.function.Function<T, ID> getIdentifierFunction,java.util.function.Consumer<Collection<T>> saveFunction) {// 构建已存在实体的 Map<Identifier, Entity>var existingEntityMap = existingEntities.stream().collect(java.util.stream.Collectors.toMap(getIdentifierFunction, e -> e));// 遍历源数据,更新或新增sources.forEach(source -> {ID identifier = getIdentifierFunction.apply(source);T existingEntity = existingEntityMap.get(identifier);if (existingEntity != null) {updateNonNullProperties(source, existingEntity);} else {existingEntities.add(source); // 新增}});// 保存所有数据saveFunction.accept(existingEntities);}
}

2.在服务端使用上述工具方法封装节点更新逻辑,无需手动处理反射或循环。

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;@Service
public class YourNodeService {private final YourNodeRepository yourNodeRepository;public YourNodeService(YourNodeRepository yourNodeRepository) {this.yourNodeRepository = yourNodeRepository;}/*** 插入或更新节点* * @param nodes 节点列表*/@Transactionalpublic void saveOrUpdateNodes(List<YourNode> nodes) {// 提取所有 name 属性List<String> names = nodes.stream().map(YourNode::getName).toList();// 查询数据库中的已存在节点List<YourNode> existingNodes = yourNodeRepository.findByNameIn(names);// 使用通用工具方法处理更新逻辑ObjectUtils.saveOrUpdateEntities(nodes,existingNodes,YourNode::getName,yourNodeRepository::saveAll);}
}

3.进一步抽象为通用接口

import java.util.List;public interface GenericService<T, ID> {void saveOrUpdate(List<T> entities, java.util.function.Function<T, ID> identifierFunction);
}
import org.springframework.data.repository.CrudRepository;
import org.springframework.transaction.annotation.Transactional;import java.util.List;
import java.util.stream.Collectors;public class GenericServiceImpl<T, ID> implements GenericService<T, ID> {private final CrudRepository<T, ID> repository;public GenericServiceImpl(CrudRepository<T, ID> repository) {this.repository = repository;}@Override@Transactionalpublic void saveOrUpdate(List<T> entities, java.util.function.Function<T, ID> identifierFunction) {// 提取所有标识符List<ID> identifiers = entities.stream().map(identifierFunction).collect(Collectors.toList());// 查询已存在的实体List<T> existingEntities = (List<T>) repository.findAllById(identifiers);// 调用通用工具更新或插入数据ObjectUtils.saveOrUpdateEntities(entities,existingEntities,identifierFunction,repository::saveAll);}
}

4.服务扩展

import org.springframework.stereotype.Service;@Service
public class YourNodeService extends GenericServiceImpl<YourNode, String> {public YourNodeService(YourNodeRepository yourNodeRepository) {super(yourNodeRepository);}
}

5.代码调用

//name为你实体中标准@Id的唯一属性
yourNodeService.saveOrUpdate(nodes, YourNode::getName);

三、总结

  • 复用性强:
    通过通用工具类或服务接口实现,支持不同实体类型的批量更新或插入逻辑。
  • 代码简洁:
    省去每次手写循环处理逻辑,业务层代码更简明。
  • 可扩展性:
    轻松扩展到其他实体类型,只需注入对应的 Repository 和标识符方法。
  • 性能优化:
    避免重复查询数据库,支持批量查询和保存,减少数据库交互次数。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com