├── README.md ├── pom.xml └── src └── main ├── java └── com │ └── appleyk │ ├── Application.java │ ├── controller │ └── CoderController.java │ ├── node │ ├── BaseEntity.java │ └── Coder.java │ ├── repository │ └── CoderRepository.java │ └── result │ ├── ResponseMessage.java │ ├── ResponseResult.java │ └── ResultData.java └── resources ├── application.properties └── logback-boot.xml /README.md: -------------------------------------------------------------------------------- 1 | # spring-boot-neo4j 2 | spring-boot集成neo4j图形数据库,并实现简单的节点创建和查询 3 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | com.appleyk 5 | Spring-Boot-Neo4j 6 | 0.0.1-SNAPSHOT 7 | Spring-Boot 集成 Neo4j图形数据库 8 | 9 | 10 | 11 | 12 | org.springframework.boot 13 | spring-boot-starter-parent 14 | 1.5.9.RELEASE 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | org.springframework.boot 25 | spring-boot-starter-web 26 | 27 | 28 | 29 | org.springframework.boot 30 | spring-boot-starter-data-neo4j 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/main/java/com/appleyk/Application.java: -------------------------------------------------------------------------------- 1 | package com.appleyk; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.boot.builder.SpringApplicationBuilder; 6 | import org.springframework.boot.web.support.SpringBootServletInitializer; 7 | 8 | /** 9 | * 10 | * 下面是一个典型的结构: 11 | * 12 | * com +- example +- myproject +- Application.java -- 13 | * 注意这个位置,习惯性的放在项目的一开始,也就是根包的第一层 | + - domain | +- Customer.java | +- 14 | * CustomerRepository.java | + - service | +- CustomerService.java | + - web +- 15 | * CustomerController.java 16 | * 17 | * 18 | * 文件将声明 main 方法, 还有基本的 @Configuration 19 | * 20 | * @author yukun24@126.com 21 | * @date 2018年4月20日13:05:36 22 | */ 23 | @SpringBootApplication// same as @Configuration @EnableAutoConfiguration @ComponentScan 24 | public class Application extends SpringBootServletInitializer{ 25 | 26 | /** 27 | * SpringApplication类提供了一种从main()方法启动Spring应用的便捷方式。 在很多情况下, 你只需委托给 28 | * SpringApplication.run这个静态方法: 29 | * 30 | * @param args 31 | */ 32 | 33 | public static void main(String[] args) { 34 | 35 | SpringApplication.run(Application.class, args); 36 | 37 | } 38 | 39 | @Override 40 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { 41 | return application.sources(Application.class); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/com/appleyk/controller/CoderController.java: -------------------------------------------------------------------------------- 1 | package com.appleyk.controller; 2 | 3 | import org.springframework.beans.factory.annotation.Autowired; 4 | import org.springframework.transaction.annotation.Transactional; 5 | import org.springframework.web.bind.annotation.PostMapping; 6 | import org.springframework.web.bind.annotation.RequestBody; 7 | import org.springframework.web.bind.annotation.RequestMapping; 8 | import org.springframework.web.bind.annotation.RequestParam; 9 | import org.springframework.web.bind.annotation.RestController; 10 | 11 | import com.appleyk.node.Coder; 12 | import com.appleyk.repository.CoderRepository; 13 | import com.appleyk.result.ResponseResult; 14 | 15 | @RestController 16 | @RequestMapping("/rest/v1.0.1/database/coder") //restful风格的api接口 17 | public class CoderController { 18 | 19 | 20 | @Autowired 21 | CoderRepository coderRepositiory; 22 | 23 | @RequestMapping("/get") 24 | public Coder GetCoderByName(@RequestParam(value="name") String name){ 25 | Coder coder = coderRepositiory.findByName(name); 26 | return coder; 27 | } 28 | 29 | @PostMapping("/save") 30 | @Transactional 31 | public ResponseResult Create(@RequestBody Coder coder) throws Exception{ 32 | 33 | Coder result = coderRepositiory.save(coder); 34 | if(result!=null){ 35 | return new ResponseResult(200,result.getName()+"节点创建成功"); 36 | } 37 | return new ResponseResult(500,coder.getName()+"节点创建失败!"); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/appleyk/node/BaseEntity.java: -------------------------------------------------------------------------------- 1 | package com.appleyk.node; 2 | 3 | import org.neo4j.ogm.annotation.GraphId; 4 | 5 | import com.fasterxml.jackson.annotation.JsonIdentityInfo; 6 | import com.fasterxml.jackson.annotation.ObjectIdGenerators; 7 | 8 | /** 9 | * 抽取共同的属性字段 10 | * @author yukun24@126.com 11 | * @blob http://blog.csdn.net/appleyk 12 | * @date 2018年4月20日13:13:17 13 | */ 14 | @JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class, property="id") 15 | public abstract class BaseEntity { 16 | 17 | /** 18 | * Neo4j会分配的ID(节点唯一标识 当前类中有效) 19 | */ 20 | @GraphId 21 | private Long id; 22 | 23 | private String name; 24 | 25 | public Long getId() { 26 | return id; 27 | } 28 | 29 | public void setId(Long id) { 30 | this.id = id; 31 | } 32 | 33 | public String getName() { 34 | return name; 35 | } 36 | 37 | public void setName(String name) { 38 | this.name = name; 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/com/appleyk/node/Coder.java: -------------------------------------------------------------------------------- 1 | package com.appleyk.node; 2 | 3 | import org.neo4j.ogm.annotation.NodeEntity; 4 | 5 | /** 6 | * Neo4j的节点实体类:Coder 7 | * 8 | * @author yukun24@126.com 9 | * @blob http://blog.csdn.net/appleyk 10 | * @date 2018年4月20日13:09:22 11 | */ 12 | 13 | @NodeEntity 14 | public class Coder extends BaseEntity { 15 | 16 | private String sex; 17 | private String hobby; 18 | 19 | public Coder() { 20 | 21 | } 22 | 23 | public String getSex() { 24 | return sex; 25 | } 26 | 27 | public void setSex(String sex) { 28 | this.sex = sex; 29 | } 30 | 31 | public String getHobby() { 32 | return hobby; 33 | } 34 | 35 | public void setHobby(String hobby) { 36 | this.hobby = hobby; 37 | } 38 | 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/com/appleyk/repository/CoderRepository.java: -------------------------------------------------------------------------------- 1 | package com.appleyk.repository; 2 | 3 | 4 | import org.springframework.data.neo4j.repository.GraphRepository; 5 | import org.springframework.data.repository.query.Param; 6 | import org.springframework.stereotype.Repository; 7 | 8 | import com.appleyk.node.Coder; 9 | 10 | 11 | /** 12 | * Coder 节点增删改 13 | * @author yukun24@126.com 14 | * @blob http://blog.csdn.net/appleyk 15 | * @date 2018年4月20日13:13:36 16 | */ 17 | 18 | @Repository 19 | public interface CoderRepository extends GraphRepository{ 20 | 21 | /* 22 | CoderRepositiory 继承 GraphRepository类,实现增删查改 23 | 实现自己的接口:通过名字查询Coder(可以是单个Coder,也可以是一个List集合), 24 | spring-data-neo4j 支持方法命名约定查询 findBy{Coder的属性名}, 25 | findBy后面的属性名一定要Coder类里存在,否则会报错 26 | */ 27 | 28 | Coder findByName(@Param("name") String name); 29 | 30 | 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/com/appleyk/result/ResponseMessage.java: -------------------------------------------------------------------------------- 1 | package com.appleyk.result; 2 | 3 | 4 | 5 | public enum ResponseMessage { 6 | 7 | /** 8 | * 成功 9 | */ 10 | OK(200,"成功"), 11 | 12 | /** 13 | * 成功 14 | */ 15 | NOCHANGE(200,"未做任何修改"), 16 | 17 | /** 18 | * 错误的请求 19 | */ 20 | BAD_REQUEST(400,"错误的请求"), 21 | 22 | /** 23 | * 错误的请求 24 | */ 25 | NOTNULL_ID(400,"请求ID不能为空"), 26 | 27 | /** 28 | * 错误的请求 29 | */ 30 | NOTNULL_NAME(400,"名称不能为空"), 31 | 32 | /** 33 | * 未授权——未授权客户机访问数据 34 | */ 35 | UNAUTHORIZED(401,"未授权——未授权客户机访问数据"), 36 | 37 | /** 38 | * 需要付款——表示计费系统已有效 39 | */ 40 | PAYMENT_REQUIRED(402,"需要付款——表示计费系统已有效"), 41 | 42 | /** 43 | * 禁止——即使有授权也不需要访问 44 | */ 45 | FORBIDDEN(403,"禁止——即使有授权也不需要访问"), 46 | 47 | /** 48 | * 正在使用,无法删除 49 | */ 50 | UNDELETE(403,"无法删除"), 51 | 52 | UNDELETE_NOTMINE(403,"无法删除——非本人创建"), 53 | 54 | /** 55 | * 找不到——服务器找不到给定的资源;文档不存在 56 | */ 57 | NOT_FOUND(404,"找不到——服务器找不到给定的资源;文档不存在"), 58 | 59 | /** 60 | * 无法接受——不合法的请求数据 61 | */ 62 | UN_ACCEPT(406,"无法接受——不合法的请求数据"), 63 | 64 | /** 65 | * 无法接受——不合法的请求数据 66 | */ 67 | IDS_UNACCEPT(406,"ids参数值不合法"), 68 | 69 | /** 70 | * 代理认证请求 — 客户机首先必须使用代理认证自身 71 | */ 72 | PROXY_AUTHENTICATION_REQUIRED(407,"代理认证请求 — 客户机首先必须使用代理认证自身"), 73 | 74 | /** 75 | * 介质类型不受支持 — 服务器拒绝服务请求,因为不支持请求实体的格式 76 | */ 77 | UNSUPPORTED_MEDIA_TYPE(415,"介质类型不受支持 — 服务器拒绝服务请求,因为不支持请求实体的格式"), 78 | 79 | /** 80 | * 内部错误 81 | */ 82 | INTERNAL_SERVER_ERROR(500, "内部错误"), 83 | 84 | /** 85 | * 还未实现 86 | */ 87 | NOT_IMPLEMENTED(501, "还未实现"), 88 | 89 | /** 90 | * 网关错误 91 | */ 92 | BAD_GATEWAY(502, "网关错误"), 93 | 94 | /** 95 | * 版本号重复 96 | */ 97 | VERSION_NAME_REPETITION(503, "版本号重复"), 98 | 99 | /** 100 | * 找不到数据 101 | */ 102 | DATA_NOT_FOUND(504, "找不到数据"), 103 | 104 | /** 105 | * 信息不完整 106 | */ 107 | INCOMPLETE_INFORMATION(505, "信息不完整"), 108 | 109 | /** 110 | * 参数错误 111 | */ 112 | PARAMETER_ERROR(506, "参数错误"), 113 | 114 | /** 115 | * 版本信息不完整 116 | */ 117 | VERSION_INCOMPLETE_INFORMATION(507, "版本信息不完整"), 118 | 119 | /** 120 | * 基本信息不完整 121 | */ 122 | BASE_INCOMPLETE_INFORMATION(508, "基本信息不完整"), 123 | 124 | /** 125 | * 英文名称重复 126 | */ 127 | E_NAME_REPETITION(509, "英文名称重复"), 128 | 129 | /** 130 | * 中文名称重复 131 | */ 132 | C_NAME_REPETITION(510, "名称重复"), 133 | 134 | /** 135 | * 关系已存在 136 | */ 137 | RELATION_EXIST(510, "关系已存在"), 138 | 139 | /** 140 | * 文件夹名称重复 141 | */ 142 | FOLDER_NAME_REPETITION(511, "文件夹名称重复"), 143 | 144 | /** 145 | * 文件夹名称重复 146 | */ 147 | DOCUMENT_NAME_REPETITION(512, "文档标题重复"), 148 | 149 | /** 150 | * 首页类别名称重复 151 | */ 152 | CATEGORY_NAME_REPETITION(513, "首页类别名称重复"), 153 | 154 | /** 155 | * 首页内容名称重复 156 | */ 157 | CONTENT_NAME_REPETITION(514, "首页内容名称重复"), 158 | 159 | /** 160 | * 操作太頻繁! 161 | */ 162 | FREQUENT_FEEDBACK(515, "操作太频繁,请五分钟后再提交!"), 163 | 164 | /** 165 | * 服务范围格式异常! 166 | */ 167 | RANGE_ERROR_FORMAT (516, "服务范围格式异常!"), 168 | ; 169 | 170 | private final int status; 171 | 172 | private final String message; 173 | 174 | ResponseMessage(int status, String message){ 175 | this.status = status; 176 | this.message = message; 177 | } 178 | 179 | public int getStatus() { 180 | return status; 181 | } 182 | 183 | public String getMessage() { 184 | return message; 185 | } 186 | 187 | } 188 | -------------------------------------------------------------------------------- /src/main/java/com/appleyk/result/ResponseResult.java: -------------------------------------------------------------------------------- 1 | package com.appleyk.result; 2 | 3 | import java.io.Serializable; 4 | import java.util.ArrayList; 5 | import java.util.Date; 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | import org.springframework.context.support.DefaultMessageSourceResolvable; 11 | import org.springframework.validation.BindingResult; 12 | 13 | import com.fasterxml.jackson.annotation.JsonFormat; 14 | import com.fasterxml.jackson.annotation.JsonInclude; 15 | import com.fasterxml.jackson.annotation.JsonInclude.Include; 16 | 17 | public class ResponseResult implements Serializable { 18 | 19 | private static final long serialVersionUID = 2719931935414658118L; 20 | 21 | private final Integer status; 22 | 23 | private final String message; 24 | 25 | @JsonInclude(value = Include.NON_NULL) 26 | private final Object data; 27 | 28 | @JsonInclude(value = Include.NON_EMPTY) 29 | private final String[] exceptions; 30 | 31 | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") 32 | private final Date timestamp; 33 | 34 | public ResponseResult(Integer status, String message) { 35 | 36 | super(); 37 | this.status = status; 38 | this.message = message; 39 | this.data = null; 40 | this.timestamp = new Date(); 41 | this.exceptions = null; 42 | 43 | } 44 | 45 | /** 46 | * 处理返回的resultData 47 | * @param result 48 | */ 49 | public ResponseResult(ResultData result) { 50 | 51 | super(); 52 | 53 | this.status = result.getState().getStatus(); 54 | this.message = result.getState().getMessage(); 55 | this.data = result.getData(); 56 | this.timestamp = new Date(); 57 | this.exceptions = null; 58 | } 59 | 60 | public ResponseResult(ResponseMessage rm){ 61 | super(); 62 | 63 | this.status = rm.getStatus(); 64 | this.message = rm.getMessage(); 65 | this.data = null; 66 | this.timestamp = new Date(); 67 | this.exceptions = null; 68 | } 69 | 70 | //UnauthorizedMessage 为自定义的消息---未认证 71 | // public ResponseResult(UnauthorizedMessage um){ 72 | // super(); 73 | // 74 | // this.status = um.getStatus(); 75 | // this.message = um.getMessage(); 76 | // this.data = null; 77 | // this.timestamp = new Date(); 78 | // this.exceptions = null; 79 | // } 80 | 81 | public ResponseResult(Integer status, String message, Object data) { 82 | 83 | super(); 84 | 85 | this.status = status; 86 | 87 | this.message = message; 88 | 89 | this.data = data; 90 | this.timestamp = new Date(); 91 | this.exceptions = null; 92 | 93 | } 94 | 95 | /** 96 | * 验证失败返回结果 97 | * @param responseMessage 98 | * @param result 99 | */ 100 | public ResponseResult(ResponseMessage responseMessage, BindingResult result) { 101 | 102 | super(); 103 | 104 | /** 105 | * 解析BindingResult,放入map 106 | */ 107 | List> errors = new ArrayList>(); 108 | 109 | for(int i=0;i map = new HashMap(); 111 | DefaultMessageSourceResolvable dm = (DefaultMessageSourceResolvable) result.getAllErrors().get(i).getArguments()[0]; 112 | map.put("field", dm.getDefaultMessage()); 113 | map.put("message", result.getAllErrors().get(i).getDefaultMessage()); 114 | errors.add(map); 115 | } 116 | 117 | this.status = responseMessage.getStatus(); 118 | 119 | this.message = responseMessage.getMessage(); 120 | 121 | this.data = errors; 122 | this.timestamp = new Date(); 123 | this.exceptions = null; 124 | 125 | } 126 | 127 | public ResponseResult(Integer status, String message, String key, Object value) { 128 | 129 | super(); 130 | 131 | this.status = status; 132 | 133 | this.message = message; 134 | 135 | Map map = new HashMap(); 136 | 137 | if (key == null || ("").equals(key)) { 138 | map.put("key", value); 139 | } else { 140 | map.put(key, value); 141 | } 142 | 143 | this.data = map; 144 | 145 | this.timestamp = new Date(); 146 | this.exceptions = null; 147 | 148 | } 149 | 150 | public ResponseResult(Integer status, Throwable ex) { 151 | 152 | super(); 153 | 154 | this.status = status; 155 | this.message = ex.getMessage(); 156 | this.data = null; 157 | StackTraceElement[] stackTeanceElement = ex.getStackTrace(); 158 | this.exceptions = new String[stackTeanceElement.length]; 159 | for (int i = 0; i < stackTeanceElement.length; i++) { 160 | this.exceptions[i] = stackTeanceElement[i].toString(); 161 | } 162 | this.timestamp = new Date(); 163 | } 164 | 165 | public ResponseResult(Integer status, String message, Throwable ex) { 166 | 167 | super(); 168 | 169 | this.status = status; 170 | 171 | this.message = message; 172 | 173 | this.data = null; 174 | 175 | StackTraceElement[] stackTeanceElement = ex.getStackTrace(); 176 | this.exceptions = new String[stackTeanceElement.length]; 177 | for (int i = 0; i < stackTeanceElement.length; i++) { 178 | this.exceptions[i] = stackTeanceElement[i].toString(); 179 | } 180 | 181 | this.timestamp = new Date(); 182 | 183 | } 184 | 185 | public Integer getStatus() { 186 | return status; 187 | } 188 | 189 | public String getMessage() { 190 | return message; 191 | } 192 | 193 | public Object getData() { 194 | return data; 195 | } 196 | 197 | public String[] getExceptions() { 198 | return exceptions; 199 | } 200 | 201 | public Date getTimestamp() { 202 | return timestamp; 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /src/main/java/com/appleyk/result/ResultData.java: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | */ 4 | package com.appleyk.result; 5 | 6 | import java.util.HashMap; 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | 11 | /** 12 | * 13 | * @author yukun24@126.com 14 | * @blob http://blog.csdn.net/appleyk 15 | * @date 2018年4月20日-下午1:13:52 16 | * @param 17 | */ 18 | public class ResultData { 19 | private ResponseMessage state; 20 | private Object data; 21 | private List dataList; 22 | 23 | 24 | public ResultData(ResponseMessage state) { 25 | 26 | this.state = state; 27 | } 28 | 29 | public ResultData(ResponseMessage state, Object data) { 30 | this.data = data; 31 | this.state = state; 32 | } 33 | 34 | public ResultData(ResponseMessage state, long data, boolean isId){ 35 | this.state = state; 36 | Map map = new HashMap(); 37 | map.put("id", data); 38 | this.data = map; 39 | } 40 | 41 | public ResultData(ResponseMessage state, long id){ 42 | this.state = state; 43 | Map map = new HashMap(); 44 | map.put("id", id); 45 | this.data = map; 46 | } 47 | 48 | /** 49 | * @return the data 50 | */ 51 | public Object getData() { 52 | return data; 53 | } 54 | 55 | public ResponseMessage getState(){ 56 | return state; 57 | } 58 | 59 | public List getDataList(){ 60 | return dataList; 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/resources/application.properties: -------------------------------------------------------------------------------- 1 | server.port=8080 2 | server.session.timeout=10 3 | server.tomcat.uri-encoding=utf8 4 | 5 | #在application.properties文件中引入日志配置文件 6 | #===================================== log ============================= 7 | logging.config=classpath:logback-boot.xml 8 | 9 | #Neo4j配置 10 | spring.data.neo4j.username=neo4j 11 | spring.data.neo4j.password=n123 12 | #数据库uri地址 13 | spring.data.neo4j.uri=http://localhost:7474 -------------------------------------------------------------------------------- /src/main/resources/logback-boot.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %d %p (%file:%line\)- %m%n 8 | 9 | UTF-8 10 | 11 | 12 | 13 | 14 | 15 | 17 | 18 | opt/spring-boot-web/logs/sys.log 19 | 20 | 21 | 22 | 23 | 24 | log/sys.%d.%i.log 25 | 26 | 30 27 | 28 | 29 | 10MB 30 | 31 | 32 | 33 | 34 | 35 | %d %p (%file:%line\)- %m%n 36 | 37 | 38 | UTF-8 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | --------------------------------------------------------------------------------