springboot引入neo4j
<dependency> <groupid>org.springframework.boot</groupid> <artifactid>spring-boot-starter-data-neo4j</artifactid> </dependency>
<spring.boot.version>2.2.11.relea</spring.boot.version>
大多数时候neo4j结合springboot都是按照实体类的映射,进行对象形式的创建节点,导致了节点属性的不可配性。结合这种问题,结合目前开发经验,可以使用neo4j 框架的ssion 进行原生cyphersql的执行。所以结合使用ssion进行动态可配等思路,建立一个neo4jutil..
neo4jutil作用
springboot结合neo4j,自定义封装cyphersql进行操作。实际就是使用neo4j的ssion.执行一些cyphersql操作,然后封装了一些方法供大家在既可以使用springboot的对象化操作方式的前提创建节点或者关系,也可以自定义继续封装一些特殊需求的方法,避免大家造轮子。
application.yml
spring: data: neo4j: uri: bolt://127.0.0.1:7688 urname: neo4j password: neo4j
config
package com.troy.keeper.modules.desk.config;import org.neo4j.ogm.ssion.ssionfactory;import org.springframework.beans.factory.annotation.value;import org.springframework.context.annotation.bean;import org.springframework.context.annotation.configuration;import org.springframework.data.neo4j.repository.config.enableneo4jrepositories;import org.springframework.data.neo4j.transaction.neo4jtransactionmanager;@configuration@enableneo4jrepositories("com.troy.keeper.desc.repository") // 声明neo4j repository存放地址public class neo4jconfig { @value("${spring.data.neo4j.uri}") private string uri; @value("${spring.data.neo4j.urname}") private string urname; @value("${spring.data.neo4j.password}") private string password; @bean public org.neo4j.ogm.config.configuration getconfiguration() { org.neo4j.ogm.config.configuration configuration = new org.neo4j.ogm.config.configuration.builder().uri(uri).connectionpoolsize(100).credentials(urname, password).withbapackages("com.troy.keeper.desc.repository").build(); return configuration; } @bean public ssionfactory ssionfactory() { return new ssionfactory(getconfiguration()); } @bean("neo4jtransaction") public neo4jtransactionmanager neo4jtransactionmanager(ssionfactory ssionfactory) { return new neo4jtransactionmanager(ssionfactory); }}
entity
neo4jbasicnode
//节点实体类package com.troy.keeper.modules.desk.entity.neo4j;import lombok.data;import java.io.rializable;import java.util.list;import java.util.map;/** * neo4j 节点实体类 * @author yangbm */@datapublic class neo4jbasicnode implements rializable { private static final long rialversionuid = 1l; /** * id */ private long id; /** * 标签 */ private list<string> labels; /** * 标签属性 */ private map<string, object> property;}
neo4jbaiscrelation
//关系实体类package com.troy.keeper.modules.desk.entity.neo4j;import lombok.data;import java.io.rializable;import java.util.map;/** * 关系 */@datapublic class neo4jbaiscrelation implements rializable { private static final long rialversionuid = 1l; /** * id */ private long id; /** * 标签 */ private string type; /** * 标签属性 */ private map<string, object> property;}
neo4jqueryrelation
//查询关系的时候返回的对象封装的实体类package com.troy.keeper.modules.desk.entity.neo4j;import lombok.data;import java.io.rializable;import java.util.map;/** * 关系 * @author yangbm */@datapublic class neo4jqueryrelation implements rializable { private static final long rialversionuid = 1l; /** * 开始节点id */ private long start; /** * 结束节点id */ private long end; /** * 关系类型 */ private string type; /** * id */ private long id; /** * 标签属性 */ private map<string, object> property;}
vo
neo4jbasicrelationreturnvo
package com.troy.keeper.modules.desk.vo.neo4j;import com.troy.keeper.modules.desk.entity.neo4j.neo4jbasicnode;import com.troy.keeper.modules.desk.entity.neo4j.neo4jqueryrelation;import lombok.data;import java.io.rializable;/** * 基础返回关系vo * 关系 * @author yangbm */@datapublic class neo4jbasicrelationreturnvo implements rializable { private static final long rialversionuid = 1l; private neo4jbasicnode start; private neo4jqueryrelation relationship; private neo4jbasicnode end;}
relationvo
package com.troy.keeper.modules.desk.vo.neo4j;import lombok.data;/** * 将关系的实体类,转换换成cyphersql需要字符串类型的vo * util里面会用到 * @author yangbm */@datapublic class relationvo { /** * 关系名称 */ private string relationlabelname; /** * 开始标签名称 */ private string startlabelname; /** * 开始节点条件 */ private string startnodeproperties; /** * 关系的属性 */ private string relationproperties; /** * 结束节点条件 */ private string endnodeproperties; /** * 结束标签名称 */ private string endlabelname; /** * 查询层级 */ private string level;}
util
neo4jutil
package com.troy.keeper.modules.desk.util;import com.fasterxml.jackson.core.jsongenerator;import com.fasterxml.jackson.databind.objectmapper;import com.troy.keeper.core.tool.utils.beanutil;import com.troy.keeper.core.tool.utils.func;import com.troy.keeper.modules.desk.dto.neo4j.neo4jsaverelationdto;import com.troy.keeper.modules.desk.dto.neo4j.relationdto;import com.troy.keeper.modules.desk.entity.neo4j.neo4jbaiscrelation;import com.troy.keeper.modules.desk.entity.neo4j.neo4jbasicnode;import com.troy.keeper.modules.desk.entity.neo4j.neo4jqueryrelation;import com.troy.keeper.modules.desk.vo.neo4j.neo4jbasicrelationreturnvo;import com.troy.keeper.modules.desk.vo.neo4j.relationvo;import lombok.sneakythrows;import org.apache.commons.collections.iteratorutils;import org.apache.commons.lang3.stringutils;import org.neo4j.driver.internal.internalpath;import org.neo4j.driver.types.node;import org.neo4j.driver.types.relationship;import org.neo4j.ogm.model.property;import org.neo4j.ogm.model.result;import org.neo4j.ogm.respon.model.nodemodel;import org.neo4j.ogm.ssion.ssion;import org.springframework.stereotype.component;import javax.annotation.resource;import java.util.*;/*** @author yangbm* neo4j工具类*/@componentpublic class neo4jutil {/*** init map序列号*/private static final objectmapper mapper = new objectmapper();static {mapper.configure(jsongenerator.feature.quote_field_names, fal);}@sneakythrowspublic static string propertiesmaptopropertiesstr(map<string,object> map) {map.entryt().removeif(entry -> func.impty(entry.getvalue()));return mapper.writevalueasstring(map);}@resourceprivate ssion ssion;public ssion getssion() {return this.ssion;}/*** 获取所有的标签名称** @return*/public list<string> getalllabelname() {string cyphersql = "match (n) return distinct labels(n) as name";result query = ssion.query(cyphersql, new hashmap<>());arraylist<string> labelnames = new arraylist<>();for (map<string, object> map : query.queryresults()) {string[] names = (string[]) map.get("name");for (string name : names) {labelnames.add(name);}}return labelnames;}/*** 获取所有的关系名称** @return*/public list<string> getallrelationname() {st环保手抄报 内容ring cyphersql = "match ()-[r]-() return distinct type(r) as name";result query = ssion.query(cyphersql, new hashmap<>());arraylist<string> relationnames = new arraylist<>();for (map<string, object> map : query.queryresults()) {relationnames.add(map.get("name").tostring());}return relationnames;}/*** 按条件查询节点** @param node* @return 返回节点集合*/public list<neo4jbasicnode> querynode(neo4jbasicnode node) {string cyphersql = "";if (func.isnotempty(node.getid())) {cyphersql = string.format("match (n) where id(n)=%s return n", node.getid());} el {string labels = "";if (func.isnotempty(node.getlabels())) {labels = ":`" + string.join("`:`", node.getlabels()) + "`";}string property = "";if (func.isnotempty(node.getproperty())) {property = neo4jutil.propertiesmaptopropertiesstr(node.getproperty());}cyphersql = string.format("match(n%s%s) return n", labels, property);}result query = ssion.query(cyphersql, new hashmap<>());arraylist<neo4jbasicnode> nodelist = new arraylist<>();iterable<map<string, object>> maps = query.queryresults();for (map<string, object> map : maps) {nodemodel querynode = (nodemodel) map.get("n");neo4jbasicnode startnodevo = new neo4jbasicnode();startnodevo.tid(querynode.getid());startnodevo.tlabels(arrays.aslist(querynode.getlabels()));list<property<string, object>> propertylist = querynode.getpropertylist();hashmap<string, object> promap = new hashmap<>();for (property<string, object> stringobjectproperty : propertylist) {if (promap.containskey(stringobjectproperty.getkey())) {throw new runtimeexception("数据重复");}promap.put(stringobjectproperty.getkey(), stringobjectproperty.getvalue());}startnodevo.tproperty(promap);nodelist.add(startnodevo);}ssion.clear();return nodelist;}/*** 创建节点** @param node 节点* @param nodup 是否去重。 true去重 fal不去重* @return*/public boolean createnode(neo4jbasicnode node, boolean nodup) {string labels = "";if (func.isnotempty(node.getlabels())) {labels = ":`" + string.join("`:`", node.getlabels()) + "`";}string property = "";if (func.isnotempty(node.getproperty())) {property = neo4jutil.propertiesmaptopropertiesstr(node.getproperty());}string cyphersql = string.format("%s(%s%s)", nodup ? "merge" : "create", labels, property);result query = ssion.query(cyphersql, new hashmap<>());ssion.clear();return query.querystatistics().getnodescreated770年() > 0;}/*** 创建节点(不去重)** @param node 节点* @param* @return*/public boolean createnode(neo4jbasicnode node) {return this.createnode(node, fal);}/*** 创建节点,(去重增强型)* 创建节点,如果节点存在,先把它删除,在重新创建* 这个方法的目的是因为 createnode方法所谓的去重,是指如果 ,已有节点a,需要创建的节点b,如果a的属性个数大于b的属性且属性对应的值一模一样,就会创建一个新的a。所以现在的方式是对b新增a中b缺少的属性* @param node* @return*/public boolean recreatenode(neo4jbasicnode node){list<string> savelabels = node.getlabels();map<string, object> saveproperty = node.getproperty();t<string> savepropertykeyt = saveproperty.keyt();//查询用属性查询节点是不是存在。//存在比较标签的lable1是不是一样。不一样就这个查询到的节点(少了就新增标签,多了就删除标签)neo4jbasicnode querynode= beanutil.copy(node,neo4jbasicnode.class);querynode.tlabels(null);list<neo4jbasicnode> querynodelist = this.querynode(querynode);if (querynodelist.impty()){return createnode(node,true);}for (neo4jbasicnode neo4jbasicnode : querynodelist) {//处理标签list<string> querylabels = neo4jbasicnode.getlabels();arraylist<string> addlabels = new arraylist<>();for (string savelabel : savelabels) {if (!querylabels.contains(savelabel)){//新增标签addlabels.add(savelabel);}}string addlabelstr=addlabels.impty()?"":("e:"+string.join(":",addlabels));//处理属性map<string, object> queryproperty = neo4jbasicnode.getproperty();t<string> querypropertykeyt = queryproperty.keyt();hashmap<string, object> addpropertymap = new hashmap<>();for (string savepropertykey: savepropertykeyt) {if (!querypropertykeyt.contains(savepropertykey)){addpropertymap.put(savepropertykey,saveproperty.get(savepropertykey));}}string addpropertystr=addpropertymap.impty()?"":(",e+="+ neo4jutil.propertiesmaptopropertiesstr(addpropertymap));if(stringutils.isallempty(addpropertystr,addpropertystr)){return true;}string addlabelcyphersql =string.format("merge (e) with e where id(e)=%s t %s %s return count(e) as count",neo4jbasicnode.getid(),addlabelstr,addpropertystr);result query = ssion.query(addlabelcyphersql, new hashmap<>());system.out.println("跟新了:"+neo4jbasicnode.getid());ssion.clear();}//创建不重复节点return true;};/*** 批量创建节点(存在的节点将会被重复创建)** @param nodelist 节点的list集合* @return 创建成功条数**/public long batchcreatenode(list<neo4jbasicnode> nodelist) {return this.batchcreatenode(nodelist, fal);}/*** 批量创建节点** @param nodelist 节点的list集合* @param nodup 是否去重。 true去重(存在的节点将不会被创建) fal不去重* @return 创建成功条数*/public long batchcreatenode(list<neo4jbasicnode> nodelist, boolean nodup) {arraylist<neo4jbasicnode> addnode = new arraylist<>();//验证for (neo4jbasicnode neo4jbasicnode : nodelist) {if ((!nodup) || this.querynode(neo4jbasicnode).size() == 0) {addnode.add(neo4jbasicnode);}}string cyphersql = "create";arraylist<string> content = new arraylist<>();for (neo4jbasicnode node : addnode) {string labels = "";if (func.isnotempty(node.getlabels())) {labels = ":`" + string.join("`:`", node.getlabels()) + "`";}string property = "";if (func.isnotempty(node.getproperty())) {property = neo4jutil.propertiesmaptopropertiesstr(node.getproperty());}content.add(string.format("(%s%s)", labels, property));}cyphersql += string.join(",", content);if (content.size() == 0) {return 0l;}result query = ssion.query(cyphersql, new hashmap<>());ssion.clear();return long.valueof(query.querystatistics().getnodescreated());}/*** 删除节点和相关关系** @param node 节点条件* @param delrelation true 删除节点相关的关系;fal 只删除不存在关系的,存在关系的节点将不会被删除关系* @return*/public integer delnode(neo4jbasicnode node, boolean delrelation) {string cyphersql = "";if (func.isnotempty(node.getid())) {cyphersql = string.format("match (n) where id(n)=%s ", node.getid());} el {string labels = "";if (func.isnotempty(node.getlabels())) {labels = ":`" + string.join("`:`", node.getlabels()) + "`";}string property = "";if (func.i星期四用英语怎么读snotempty(node.getproperty())) {property = neo4jutil.propertiesmaptopropertiesstr(node.getproperty());}cyphersql = string.format("match(n%s%s) ", labels, property);}if (delrelation) {cyphersql += "detach delete n";} el {//删除不存在关系的节点cyphersql += " where not exists((n)-[]-()) delete n";}result query = ssion.query(cyphersql, new hashmap<>());ssion.clear();return query.querystatistics().getnodesdeleted();}/*** 删除节点和相关关系* 只删除不存在关系的,存在关系的节点将不会被删除关系** @param node 节点条件 有关系的节点不会删除* @return*/public integer delnode(neo4jbasicnode node) {return this.delnode(node, fal);}public int querynodecreaterelation(neo4jbasicnode start, neo4jbasicnode end,ud neo4jbaiscrelation relation) {neo4jsaverelationdto dto = new neo4jsaverelationdto();dto.tstart(start);dto.tend(end);dto.trelationship(relation);return querynodecreaterelation(dto);}/*** 查询节点然后创建关系* 创建关系(查询开始节点和结束节点然后创造关系)* 注意:开始节点和结束节点以及创建的关系参数一定要存在!* 关系如果存在,不会重复创建* 因为需要返回创建条数 当前方法未做条件判断** @param saverelation 关系构造类* @return 返回创建关系的个数*/public int querynodecreaterelation(neo4jsaverelationdto saverelation) {//开始节点和结束节点验证string cyphersql = "";string startlable = "";if (func.isnotempty(saverelation.getstart().getlabels())) {startlable = ":`" + string.join("`:`", saverelation.getstart().getlabels()) + "`";}string startproperty = "";if (func.isnotempty(saverelation.getstart().getproperty())) {startproperty = neo4jutil.propertiesmaptopropertiesstr(saverelation.getstart().getproperty());}string endlable = "";if (func.isnotempty(saverelation.getend().getlabels())) {endlable = ":`" + string.join("`:`", saverelation.getend().getlabels()) + "`";}string endproperty = "";if (func.isnotempty(saverelation.getend().getproperty())) {endproperty = neo4jutil.propertiesmaptopropertiesstr(saverelation.getend().getproperty());}string startwhere = "";if (func.isnotempty(saverelation.getstart().getid())) {startwhere += " where id(start)=" + saverelation.getstart().getid();startlable = "";startproperty = "";}string endwhere = "";if (func.isnotempty(saverelation.getend().getid())) {endwhere += " where id(end)=" + saverelation.getend().getid();endlable = "";endproperty = "";}string relationtype = "";if (func.isnotempty(saverelation.getrelationship().gettype())) {relationtype = ":`" + saverelation.getrelationship().gettype() + "`";}if (func.impty(relationtype)) {throw new runtimeexception("关系名称不能为空!");}string relationproperty = "";if (func.isnotempty(saverelation.getrelationship().getproperty())) {relationproperty = neo4jutil.propertiesmaptopropertiesstr(saverelation.getrelationship().getproperty());}cyphersql = string.format("match (start%s%s) %s with start match (end%s%s) %s merge (start)-[rep%s%s]->(end)", startlable, startproperty, startwhere, endlable, endproperty, endwhere, relationtype, relationproperty);result query = ssion.query(cyphersql, new hashmap<>());ssion.clear();return query.querystatistics().getrelationshipscreated();}/*** 创建节点同时创建关系* 重复的不会被创建** @param saverelation* @return*/public boolean cretenodeandrelation(neo4jsaverelationdto saverelation) {string cyphersql = "";string startlable = "";if (func.isnotempty(saverelation.getstart().getlabels())) {startlable = ":`" + string.join("`:`", saverelation.getstart().getlabels()) + "`";}string startproperty = "";if (func.isnotempty(saverelation.getstart().getproperty())) {startproperty = neo4jutil.propertiesmaptopropertiesstr(saverelation.getstart().getproperty());}string endlable = "";if (func.isnotempty(saverelation.getend().getlabels())) {endlable = ":`" + string.join("`:`", saverelation.getend().getlabels()) + "`";}string endproperty = "";if (func.isnotempty(saverelation.getend().getproperty())) {endproperty = neo4jutil.propertiesmaptopropertiesstr(saverelation.getend().getproperty());}string relationtype = "";if (func.isnotempty(saverelation.getrelationship().gettype())) {relationtype = ":`" + saverelation.getrelationship().gettype() + "`";}if (func.impty(relationtype)) {throw new runtimeexception("关系名称不能为空!");}string relationproperty = "";if (func.isnotempty(saverelation.getrelationship().getproperty())) {relationproperty = neo4jutil.propertiesmaptopropertiesstr(saverelation.getrelationship().getproperty());}cyphersql = string.format("merge (start%s%s)-[rep%s%s]->(end%s%s)", startlable, startproperty, relationtype, relationproperty, endlable, endproperty);result query = ssion.query(cyphersql, new hashmap<>());ssion.clear();return query.querystatistics().getrelationshipscreated() > 0;}/*** 查询关系** @param relationdto* @return*/public list<neo4jbasicrelationreturnvo> queryrelation(relationdto relationdto) {relationvo relationvo = formatrelation(relationdto);//拼接sqlstring cyphersql = string.format("match p=(a%s%s)-[r%s%s]->(b%s%s)-[*女职工劳动保护特别规定0..%s]->() return p", relationvo.getstartlabelname(), relationvo.getstartnodeproperties(), relationvo.getrelationlabelname(), relationvo.getrelationproperties(), relationvo.getendlabelname(), relationvo.getendnodeproperties(), relationvo.getlevel());system.out.println(cyphersql);long starttime = system.currenttimemillis();result query = ssion.query(cyphersql, new hashmap<>());system.out.println(string.format("耗时%d秒", system.currenttimemillis() - starttime));iterable<map<string, object>> maps = query.queryresults();arraylist<neo4jbasicrelationreturnvo> returnlist = new arraylist<>();for (map<string, object> map : maps) {internalpath.lfcontainedgment[] ps = (internalpath.lfcontainedgment[]) map.get("p");for (internalpath.lfcontainedgment p : ps) {returnlist.add(changetoneo4jbasicrelationreturnvo(p));}}ssion.clear();return returnlist;}/*** 格式化** @param relationdto* @return*/public relationvo formatrelation(relationdto relationdto) {relationvo relationvo = new relationvo();//验证if (func.isnotempty(relationdto.getrelationlabelname())) {relationvo.trelationlabelname(":`" + relationdto.getrelationlabelname()+"`");} el {relationvo.trelationlabelname("");}if (func.isnotempty(relationdto.getstartlabelname())) {relationvo.tstartlabelname(":`" + relationdto.getstartlabelname()+"`");} el {relationvo.tstartlabelname("");}if (func.isnotempty(relationdto.getendlabelname())) {relationvo.tendlabelname(":`" + relationdto.getendlabelname()+"`");} el {relationvo.tendlabelname("");}if (func.isnotempty(relationdto.getstartnodeproperties())) {relationvo.tstartnodeproperties(neo4jutil.propertiesmaptopropertiesstr(relationdto.getstartnodeproperties()));} el {relationvo.tstartnodeproperties("");}if (func.isnotempty(relationdto.getrelationproperties())) {relationvo.trelationproperties(neo4jutil.propertiesmaptopropertiesstr(relationdto.getrelationproperties()));} el {relationvo.trelationproperties("");}if (func.isnotempty(relationdto.getendnodeproperties())) {relationvo.tendnodeproperties(neo4jutil.propertiesmaptopropertiesstr(relationdto.getendnodeproperties()));} el {relationvo.tendnodeproperties("");}if (func.isnotempty(relationdto.getlevel())) {relationvo.tlevel(relationdto.getlevel().tostring());} el {relationvo.tlevel("");}return relationvo;}/*** 转化neo4j默认查询的参数为自定返回类型** @param lfcontainedgment* @return neo4jbasicrelationreturn*/public neo4jbasicrelationreturnvo changetoneo4jbasicrelationreturnvo(internalpath.lfcontainedgment lfcontainedgment) {neo4jbasicrelationreturnvo neo4jbasicrelationreturnvo = new neo4jbasicrelationreturnvo();//startnode start = lfcontainedgment.start();neo4jbasicnode startnodevo = new neo4jbasicnode();startnodevo.tid(start.id());startnodevo.tlabels(iteratorutils.tolist(start.labels().iterator()));startnodevo.tproperty(start.asmap());neo4jbasicrelationreturnvo.tstart(startnodevo);//endnode end = lfcontainedgment.end();neo4jbasicnode endnodevo = new neo4jbasicnode();endnodevo.tid(end.id());endnodevo.tlabels(iteratorutils.tolist(end.labels().iterator()));endnodevo.tproperty(end.asmap());neo4jbasicrelationreturnvo.tend(endnodevo);//relationshipneo4jqueryrelation neo4jqueryrelation = new neo4jqueryrelation();relationship relationship = lfcontainedgment.relationship();neo4jqueryrelation.tstart(relationship.startnodeid());neo4jqueryrelation.tend(relationship.endnodeid());neo4jqueryrelation.tid(relationship.id());neo4jqueryrelation.ttype(relationship.type());neo4jqueryrelation.tproperty(relationship.asmap());neo4jbasicrelationreturnvo.trelationship(neo4jqueryrelation);return neo4jbasicrelationreturnvo;}}
到此这篇关于springboot结合neo4j自定义cyphersql的文章就介绍到这了,更多相关springboot自定义cyphersql内容请搜索www.887551.com以前的文章或继续浏览下面的相关文章希望大家以后多多支持www.887551.com!
本文发布于:2023-04-03 23:06:44,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/81ce0cd176f54f071a4b5bf6a5d023e0.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:SpringBoot结合Neo4j自定义cypherSql的方法.doc
本文 PDF 下载地址:SpringBoot结合Neo4j自定义cypherSql的方法.pdf
留言与评论(共有 0 条评论) |