我使用Spring Boot 1.5.3和2.1.2的OGM。 SDN版本是4.2.3,我使用neo4j 3.2.1数据库。我修改了配置文件以修复chyper版本的小问题,所以我使用chyper 3.1作为默认语言。
在这个用例中,我只有一个名为category的简单域类。每个类别都可以有一个父类和多个子类,如经典树结构。
由于类别数量众多,我更喜欢数据库所需的磁盘空间性能。这是我的域类:
@NodeEntity
public class Category {
@GraphId
Long id;
@Convert(UuidStringConverter.class)
@Index(unique = true, primary = true)
UUID uuid;
@DateString("yy-MM-dd")
private Date dateAdded;
@Index(unique = true, primary = false)
private String name;
@Relationship(type = "parent", direction = Relationship.OUTGOING)
private Category parent;
@Relationship(type = "children", direction = Relationship.OUTGOING)
private Set<Category> children;
public Category() {
dateAdded = new Date();
uuid = UUID.randomUUID();
}
public Category(String name) {
this();
this.name = name;
}
public Category(String name, Category parent) {
this(name);
this.parent = parent;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Category getParent() {
return parent;
}
public void setParent(Category parent) {
this.parent = parent;
}
public UUID getUuid() {
return uuid;
}
public void setUuid(UUID uuid) {
this.uuid = uuid;
}
/**
* @return the dateAdded
*/
public Date getDateAdded() {
return dateAdded;
}
/**
* @param dateAdded
* the dateAdded to set
*/
public void setDateAdded(Date dateAdded) {
this.dateAdded = dateAdded;
}
/**
* @return the children
*/
public Set<Category> getChildren() {
return children;
}
/**
* @param children
* the children to set
*/
public void setChildren(Set<Category> children) {
this.children = children;
}
public void addChildren(Category c) {
if (children == null) {
children = new HashSet<>();
}
children.add(c);
}
public void removeChildren(Category c) {
if (children != null) {
children.remove(c);
if (children.size() == 0) {
children = null;
}
};
}
public String toString(){
return name;
}
}
在实践中,没有必要将对类别的父母和子女的引用保持为neo4j&#34;方向不可知&#34;但这是由于与绩效相关的问题。
SDN的一个非常奇怪的行为是,如果我创建一个类别(非小说)和一个子类别(数学),一切正常。如果我在同一主要类别下创建新的子类别(生物学),则前一个子类别与主要类别(数学和非小说)之间将存在意外关系。 日志显示以下内容:
Create Non-fiction main category
2017-06-14 09:47:06.312 DEBUG 6788 --- [nio-8083-exec-4] o.s.b.w.f.OrderedRequestContextFilter : Bound request context to thread: org.apache.catalina.connector.RequestFacade@241797fe
2017-06-14 09:47:06.331 INFO 6788 --- [nio-8083-exec-4] o.n.o.drivers.http.request.HttpRequest : Thread: 21, url: http://neo4j:password@localhost:7474/db/data/transaction/commit, request: {"statements":[{"statement":"MATCH (n:`Category`) WHERE n.`name` = { `name_0` } WITH n MATCH p=(n)-[*0..1]-(m) RETURN p, ID(n)","parameters":{"name_0":"Non-fiction"},"resultDataContents":["graph","row"],"includeStats":false}]}
2017-06-14 09:47:06.390 INFO 6788 --- [nio-8083-exec-4] o.n.o.drivers.http.request.HttpRequest : Thread: 21, url: http://localhost:7474/db/data/transaction/23, request: {"statements":[{"statement":"MATCH (n) WHERE n.uuid = { id } WITH n MATCH p=(n)-[*0..1]-(m) RETURN p","parameters":{"id":"3a497cec-d67c-4c44-ab86-e6639dc60d13"},"resultDataContents":["graph"],"includeStats":false}]}
2017-06-14 09:47:06.465 INFO 6788 --- [nio-8083-exec-4] o.n.o.drivers.http.request.HttpRequest : Thread: 21, url: http://localhost:7474/db/data/transaction/24, request: {"statements":[{"statement":"UNWIND {rows} as row MERGE (n:`Category`{uuid: row.props.uuid}) SET n=row.props RETURN row.nodeRef as ref, ID(n) as id, row.type as type","parameters":{"rows":[{"nodeRef":-684249223,"type":"node","props":{"name":"Non-fiction","uuid":"3a497cec-d67c-4c44-ab86-e6639dc60d13","dateAdded":"17-06-14"}}]},"resultDataContents":["row"],"includeStats":false}]}
2017-06-14 09:47:06.545 INFO 6788 --- [nio-8083-exec-4] h.b.services.CategoryServiceImpl : Non-fiction category were created
2017-06-14 09:47:06.547 INFO 6788 --- [nio-8083-exec-4] o.n.o.drivers.http.request.HttpRequest : Thread: 21, url: http://localhost:7474/db/data/transaction/25, request: {"statements":[{"statement":"MATCH (n:`Category`) WITH n MATCH p=(n)-[*0..1]-(m) RETURN p","parameters":{},"resultDataContents":["graph"],"includeStats":false}]}
2017-06-14 09:47:06.571 DEBUG 6788 --- [nio-8083-exec-4] o.s.b.w.f.OrderedRequestContextFilter : Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@241797fe
Create Math subcategory of Non-fiction parent category
2017-06-14 09:48:26.865 DEBUG 6788 --- [nio-8083-exec-7] o.s.b.w.f.OrderedRequestContextFilter : Bound request context to thread: org.apache.catalina.connector.RequestFacade@241797fe
2017-06-14 09:48:26.881 INFO 6788 --- [nio-8083-exec-7] o.n.o.drivers.http.request.HttpRequest : Thread: 24, url: http://neo4j:password@localhost:7474/db/data/transaction/commit, request: {"statements":[{"statement":"MATCH (n:`Category`) WHERE n.`name` = { `name_0` } WITH n MATCH p=(n)-[*0..1]-(m) RETURN p, ID(n)","parameters":{"name_0":"Math"},"resultDataContents":["graph","row"],"includeStats":false}]}
2017-06-14 09:48:26.916 INFO 6788 --- [nio-8083-exec-7] o.n.o.drivers.http.request.HttpRequest : Thread: 24, url: http://localhost:7474/db/data/transaction/30, request: {"statements":[{"statement":"MATCH (n) WHERE n.uuid = { id } WITH n MATCH p=(n)-[*0..1]-(m) RETURN p","parameters":{"id":"3a839cc1-9af7-45fd-a29c-bfe96705655e"},"resultDataContents":["graph"],"includeStats":false}]}
2017-06-14 09:48:26.939 INFO 6788 --- [nio-8083-exec-7] o.n.o.drivers.http.request.HttpRequest : Thread: 24, url: http://localhost:7474/db/data/transaction/31, request: {"statements":[{"statement":"UNWIND {rows} as row MERGE (n:`Category`{uuid: row.props.uuid}) SET n=row.props RETURN row.nodeRef as ref, ID(n) as id, row.type as type","parameters":{"rows":[{"nodeRef":-1188832417,"type":"node","props":{"name":"Math","uuid":"3a839cc1-9af7-45fd-a29c-bfe96705655e","dateAdded":"17-06-14"}}]},"resultDataContents":["row"],"includeStats":false}]}
2017-06-14 09:48:26.995 INFO 6788 --- [nio-8083-exec-7] o.n.o.drivers.http.request.HttpRequest : Thread: 24, url: http://localhost:7474/db/data/transaction/31, request: {"statements":[{"statement":"UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MERGE (startNode)-[rel:`parent`]->(endNode) RETURN row.relRef as ref, ID(rel) as id, row.type as type","parameters":{"rows":[{"startNodeId":7,"relRef":-240693881,"type":"rel","endNodeId":6}]},"resultDataContents":["row"],"includeStats":false},{"statement":"UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MERGE (startNode)-[rel:`children`]->(endNode) RETURN row.relRef as ref, ID(rel) as id, row.type as type","parameters":{"rows":[{"startNodeId":6,"relRef":-12081903,"type":"rel","endNodeId":7}]},"resultDataContents":["row"],"includeStats":false}]}
2017-06-14 09:48:27.288 INFO 6788 --- [nio-8083-exec-7] o.n.o.drivers.http.request.HttpRequest : Thread: 24, url: http://localhost:7474/db/data/transaction/32, request: {"statements":[{"statement":"MATCH (n:`Category`) WITH n MATCH p=(n)-[*0..1]-(m) RETURN p","parameters":{},"resultDataContents":["graph"],"includeStats":false}]}
2017-06-14 09:48:27.344 DEBUG 6788 --- [nio-8083-exec-7] o.s.b.w.f.OrderedRequestContextFilter : Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@241797fe
Create Biology subcategory of Non-fiction parent category
2017-06-14 09:51:12.367 DEBUG 6788 --- [nio-8083-exec-1] o.s.b.w.f.OrderedRequestContextFilter : Bound request context to thread: org.apache.catalina.connector.RequestFacade@241797fe
2017-06-14 09:51:12.385 INFO 6788 --- [nio-8083-exec-1] o.n.o.drivers.http.request.HttpRequest : Thread: 18, url: http://neo4j:password@localhost:7474/db/data/transaction/commit, request: {"statements":[{"statement":"MATCH (n:`Category`) WHERE n.`name` = { `name_0` } WITH n MATCH p=(n)-[*0..1]-(m) RETURN p, ID(n)","parameters":{"name_0":"Biology"},"resultDataContents":["graph","row"],"includeStats":false}]}
2017-06-14 09:51:12.394 INFO 6788 --- [nio-8083-exec-1] o.n.o.drivers.http.request.HttpRequest : Thread: 18, url: http://localhost:7474/db/data/transaction/37, request: {"statements":[{"statement":"MATCH (n) WHERE n.uuid = { id } WITH n MATCH p=(n)-[*0..1]-(m) RETURN p","parameters":{"id":"8004d142-85c5-461b-862e-aee7ddfc90fa"},"resultDataContents":["graph"],"includeStats":false}]}
2017-06-14 09:51:12.405 INFO 6788 --- [nio-8083-exec-1] o.n.o.drivers.http.request.HttpRequest : Thread: 18, url: http://localhost:7474/db/data/transaction/38, request: {"statements":[{"statement":"UNWIND {rows} as row MERGE (n:`Category`{uuid: row.props.uuid}) SET n=row.props RETURN row.nodeRef as ref, ID(n) as id, row.type as type","parameters":{"rows":[{"nodeRef":-1174392366,"type":"node","props":{"name":"Biology","uuid":"8004d142-85c5-461b-862e-aee7ddfc90fa","dateAdded":"17-06-14"}}]},"resultDataContents":["row"],"includeStats":false}]}
2017-06-14 09:51:12.414 INFO 6788 --- [nio-8083-exec-1] o.n.o.drivers.http.request.HttpRequest : Thread: 18, url: http://localhost:7474/db/data/transaction/38, request: {"statements":[{"statement":"UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MERGE (startNode)-[rel:`parent`]->(endNode) RETURN row.relRef as ref, ID(rel) as id, row.type as type","parameters":{"rows":[{"startNodeId":8,"relRef":-1580985829,"type":"rel","endNodeId":6}]},"resultDataContents":["row"],"includeStats":false},{"statement":"UNWIND {rows} as row MATCH (startNode) WHERE ID(startNode) = row.startNodeId MATCH (endNode) WHERE ID(endNode) = row.endNodeId MERGE (startNode)-[rel:`children`]->(endNode) RETURN row.relRef as ref, ID(rel) as id, row.type as type","parameters":{"rows":[{"startNodeId":7,"relRef":-2084880007,"type":"rel","endNodeId":6},{"startNodeId":6,"relRef":-38658551,"type":"rel","endNodeId":8}]},"resultDataContents":["row"],"includeStats":false}]}
2017-06-14 09:51:12.456 INFO 6788 --- [nio-8083-exec-1] o.n.o.drivers.http.request.HttpRequest : Thread: 18, url: http://localhost:7474/db/data/transaction/39, request: {"statements":[{"statement":"MATCH (n:`Category`) WITH n MATCH p=(n)-[*0..1]-(m) RETURN p","parameters":{},"resultDataContents":["graph"],"includeStats":false}]}
2017-06-14 09:51:12.520 DEBUG 6788 --- [nio-8083-exec-1] o.s.b.w.f.OrderedRequestContextFilter : Cleared thread-bound request context: org.apache.catalina.connector.RequestFacade@241797fe
我创建新子类别的代码如下:
@PostMapping("/admin/category/newMid")
String newMidCategory(Model m, @RequestParam("newMidCategory") String newMidCategoryName,
@RequestParam("selectedMainCategory") Category mainCategory) {
if (mainCategory != null) {
Category existing = categoryService.findCategoryByName(newMidCategoryName);
if (existing == null) {
// indeed it is new category
Category newMidCategory = new Category(newMidCategoryName, mainCategory);
mainCategory.addChildren(newMidCategory);
categoryService.insertNewCategory(newMidCategory);
} else {
m.addAttribute("midCatError", ctx.getMessage("error.admin.MidCategoryExistsAlready", null,
new Locale(env.getProperty("spring.mvc.locale"))));
}
} else {
m.addAttribute("midCatError", ctx.getMessage("error.admin.mainCategoryNotSelected", null,
new Locale(env.getProperty("spring.mvc.locale"))));
}
m.addAttribute("midCategories", categoryService.getChildrenOfParent(mainCategory));
m.addAttribute("allMainCategories", categoryService.getAllMainCategories());
return "admin/category :: #categoryForm";
}
经过几个小时的调试后发现,不知何故,子类别(Math)子集具有非小说主类别的成员,因此OGM只是正确映射它。
问题是如何在不调用公共方法addChildren(类别c)的情况下修改我的私有子属性。我的addChildren方法中有一个System.out.println()行来查看它何时被调用。它只被调用两次:首先我们添加数学子类别,第二次添加生物子类别。 没有addChildren调用Math子类别有子项? 这是什么?
答案 0 :(得分:0)
这看起来像个错误。
您可以尝试注释关系字段的setter作为解决方法:
@Relationship(type = "parent", direction = Relationship.OUTGOING)
private Category parent;
@Relationship(type = "children", direction = Relationship.OUTGOING)
private Set<Category> children;
@Relationship(type = "parent", direction = Relationship.OUTGOING)
public void setParent(Category parent) {
this.parent = parent;
}
@Relationship(type = "children", direction = Relationship.OUTGOING)
public void setChildren(Set<Category> children) {
this.children = children;
}
如果您可以使用SDN / OGM问题模板重现它,那就太棒了。 https://github.com/neo4j-examples/neo4j-sdn-ogm-issue-report-template
答案 1 :(得分:0)
如果两个字段的结束节点类型相同,则可能需要使用与字段相同的@Relationship注释setter。我相信这在2.1.4中已得到修复。 https://github.com/neo4j/neo4j-ogm/issues/361