neo4j rest java_java – 用于公开Neo4j节点的REST接口实现

我将我的节点表示为域实体.我想通过REST接口公开我的节点,使用GET通过id查询,POST保存一个节点及其相关节点和PUT来更新节点及其相关节点. GET工作正常,但我有一个关于POST和PUT案例的实现问题.让我来说明问题,因为代码经常说的不仅仅是单词.

在此示例中,有两个相关的节点类型表示为域实体.协作可以包含多个标记,标记可以属于多个协作.所以我们有很多关系.它们共享相同的基类NodeBacked

它基本上用作底层节点的包装器.

NodeBacked

abstract class NodeBacked {

private Node node;

public NodeBacked(final Node node) {

this.node = node;

}

public Long getId() {

return this.node.getId();

}

@Override

public int hashCode() {

return this.node.hashCode();

}

@JsonIgnore

public Node getNode() {

return this.node;

}

}

合作

public class Collaboration extends NodeBacked {

public Collaboration(final Node node) {

super(node);

}

// Leaving out some properties for clearness

@JsonProperty(NAME_JSON)

public String getName() {

return (String) getNode().getProperty(NAME);

}

@JsonProperty(TAGS_JSON)

public Iterable getTags() {

return new IterableWrapper(Traversal.description().breadthFirst()

.relationships(Relationships.HAS, Direction.OUTGOING).uniqueness(Uniqueness.NODE_GLOBAL)

.evaluator(Evaluators.atDepth(1)).evaluator(Evaluators.excludeStartPosition()).traverse(getNode()))

{

@Override

protected Tag underlyingObjectToObject(final Path path) {

return new Tag(path.endNode());

}

};

}

public void setName(final String name) {

final Index index = getNode().getGraphDatabase().index().forNodes(Indexes.NAMES);

getNode().setProperty(NAME, name);

if (StringUtils.isNotEmpty(getName())) {

index.remove(getNode(), NAME, name);

}

index.add(getNode(), NAME, name);

}

public void addTag(final Tag tag) {

if (!Traversal.description().breadthFirst().relationships(Relationships.HAS, Direction.OUTGOING)

.uniqueness(Uniqueness.NODE_GLOBAL).evaluator(Evaluators.atDepth(1))

.evaluator(Evaluators.excludeStartPosition())

.evaluator(Evaluators.includeWhereEndNodeIs(tag.getNode())).traverse(getNode()).iterator().hasNext

()) {

getNode().createRelationshipTo(tag.getNode(), Relationships.HAS);

}

}

@Override

public boolean equals(final Object o) {

return o instanceof Collaboration && getNode().equals(((Collaboration) o).getNode());

}

}

标签

public class Tag extends NodeBacked {

public Tag(final Node node) {

super(node);

}

@JsonProperty(NAME_JSON)

public String getName() {

return (String) getNode().getProperty(NAME);

}

public void setName(final String name) {

final Index index = getNode().getGraphDatabase().index().forNodes(Indexes.NAMES);

getNode().setProperty(NAME, name);

if (StringUtils.isNotEmpty(getName())) {

index.remove(getNode(), NAME, name);

}

index.add(getNode(), NAME, name);

}

@JsonProperty(COLLABORATIONS_JSON)

@JsonSerialize(using = SimpleCollaborationSerializer.class)

private Iterable getCollaborations(int depth) {

return new IterableWrapper(Traversal.description().breadthFirst()

.relationships(Relationships.HAS, Direction.INCOMING).uniqueness(Uniqueness.NODE_GLOBAL)

.evaluator(Evaluators.atDepth(1)).evaluator(Evaluators.excludeStartPosition()).traverse(getNode()))

{

@Override

protected Collaboration underlyingObjectToObject(final Path path) {

return new Collaboration(path.endNode());

}

};

}

@Override

public boolean equals(final Object o) {

return o instanceof Tag && getNode().equals(((Tag) o).getNode());

}

}

我通过REST(Spring 3.2)公开了Collaboration,如下所示. MappingJackson2HttpMessageConverter用于将POJO转换为JSON,反之亦然.

@Controller

@RequestMapping(value = CollaborationController.CONTEXT_PATH)

public class CollaborationController {

public static final String CONTEXT_PATH = "/collaborations";

@Autowired

private GraphDatabaseService db;

@Transactional

@RequestMapping(value = "/{id}", method = RequestMethod.GET)

public @ResponseBody Collaboration getCollaboration(final @PathVariable Long id) {

// should use a service layer but doing this for clearness

return new Collaboration(db.getNodeById(id));

}

}

这非常有效. getters在节点中查询它的属性,并返回一个体面的JSON字符串. GET / collaborations / 1的示例JSON字符串:

{

"name" : "Dummy Collaboration",

"tags" : [ {

"name" : "test",

"id" : 3

}, {

"name" : "dummy",

"id" : 2

} ],

"id" : 1

}

那么,问题是什么呢?想象一下带有JSON主体的POST请求,如下所示:

{

"name" : "Second collaboration",

"tags" : [ {

"name" : "tagged"

} ]

}

CollaborationController具有以下方法来处理POST请求:

@Transactional

@RequestMapping(method = RequestMethod.POST, headers = JSON_CONTENT_TYPE)

public @ResponseBody ResponseEntity persist(final @RequestBody Collaboration collaboration,

final UriComponentsBuilder builder) {

final Collaboration collab = new Collaboration(db.createNode(Labels.COLLAB));

// Problem!!

collab.setName(collaboration.getName());

final HttpHeaders headers = new HttpHeaders();

headers.setLocation(builder.path(CONTEXT_PATH + "/{id}").buildAndExpand(collab.getId()).toUri());

return new ResponseEntity(collab, headers, HttpStatus.CREATED);

}

collab.setName行(collaboration.getName());将无法工作,因为协作类不包含自己的属性,并使用直接查询基础节点的getter.在这种情况下,没有任何节点可用,因为Jackson应使用Spring的MappingJackson2HttpMessageConverter将协作从JSON转换为POJO.没有任何属性,所以没有什么可以设置的……

我正在研究解决这个问题的最干净的解决方案,但还没找到.我可以使用POJO(或VO或…)作为持久化方法的传入参数,但这不是真正可维护的.更改属性需要更新Collaboration类以及CollaborationVO(POJO)类.

建议非常欢迎! Spring Data Neo4j主要解决了所有这些问题,但我对它的性能并不满意.这就是我尝试另一种方法的确切原因.

我希望这个解释很清楚.谢谢你的支持!

使用的框架:

>春季3.2.3.RELEASE

> Neo4j 2.0.0-M3(嵌入式)

>杰克逊2.2.2

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值