equivalent of template.createRelationBetween in SD

2019-07-17 13:51发布

问题:

My project is currently use Spring-Data-Neo4J 3.3.0 and I'm trying to use the new 4.0.0.Release version. In my code I have the following code :

neo4jTemplate.createRelationshipBetween(eltOrRel, attribute, valueClass, GraphRelationType.HAS_ATT_VALUE, true)

What is the equivalent of this code (which is use this method in api in the new version of SDK please ?

More especially I don't know how to create a relation of a given type but for a specific class. How can I write such a creation in cypher please ?

@Luanne Here is a little example of my problem.

Class Element :

@NodeEntity
public class Element {

@GraphId
private Long id;

private int age;

private String  uuid;

@Relationship(type = "HAS_ATT_VALUE")
private Set<HasAttValue> values = new HashSet<HasAttValue>();
...

Class Attribute :

@NodeEntity
public class Attribute {
@GraphId
private Long id;

private String attName;

And class HasAttValue :

@RelationshipEntity(type = "HAS_ATT_VALUE")
public class HasAttValue {

@GraphId
private Long id;

@StartNode
Element element;

@EndNode
Attribute attribute;

private String value;

public HasAttValue() {
}

public HasAttValue(Element element, Attribute attribute, String value) {
    this.element = element;
    this.attribute = attribute;
    this.value = value;
    this.element.getValues().add(this);
}

In this first case, everything works like a charm, and, as in your example I have the following graph (seeing in the server browser) with my value on the HAS_ATT_VALUE relationshipEntity:

(Element)->[HAS_ATT_VALUE]->(attribute)

But my problem is in the following case (which was working well with previous SDN). Instead of the HasAttValue previous class, I have :

@RelationshipEntity(type = "HAS_ATT_VALUE")
public abstract class HasAttValue<T> {

@GraphId
private Long id;

@StartNode
Element element;

@EndNode
Attribute attribute;

private T value;

public HasAttValue() {
}

public HasAttValue(Element element, Attribute attribute, T value) {
    this.element = element;
    this.attribute = attribute;
    this.value = value;
    this.element.getValues().add(this);
}

with for example two subclasses. First one :

public class HasBooleanValue extends HasAttValue<Boolean> {

public HasBooleanValue() {
}

public HasBooleanValue(Element elt, Attribute attribut, Boolean value) {
    super(elt, attribut, value);
}
}

Second one :

public class HasStringValue extends HasAttValue<String> {

private String locale;

public HasStringValue() {
}

public HasStringValue(Element element, Attribute attribut, String value)   {
    super(element, attribut, value);
}

In this case the graph is like the following :

(element)->[HAS_ATT_VALUE]->(HasBooleanValue|HasStringValue)->[ATTRIBUTE]->(Attribute)

and another arc in the graphe (element)<-[ELEMENT]-(HasBooleanValue|HasStringValue)

So how can I do to always have (element)->[HAS_ATT_VALUE]->(attribute) where "has_att_value" is a relationshipentity containing datas but having diffent impletations in my java code ? Again, this was working well in SDN3 when I used the neo4jTemplate.createRelationshipBetween(eltOrRel, attribute, valueClass, GraphRelationType.HAS_ATT_VALUE, true) to create my "hasAttValue" relationshipEntity.

Thank you very much

回答1:

In SDN 4.0, relationships do not need to be created explicitly using Neo4jTemplate methods. Persisting the entity on which @Relationships are defined is enough to create relationships. If you have properties on the relationship, then you'd need a @RelationshipEntity.

An explanation of object models in SDN 4.0 can be found here http://graphaware.com/neo4j/2015/09/03/sdn-4-object-model.html

Update based on additional info from @clement:

Just move the @RelationshipEntity annotation from the HasAttValue class to each subclass, for example

@RelationshipEntity(type = "HAS_ATT_VALUE")
public class HasBooleanValue extends HasAttValue<Boolean> {

Note that you will need the latest OGM snapshot since an issue around abstract relationship entities was just fixed. Please use

  <dependency>
       <groupId>org.neo4j</groupId>
       <artifactId>neo4j-ogm</artifactId>
       <version>1.1.3-SNAPSHOT</version>
  </dependency>
 <repository>
       <id>neo4j-snapshots</id>
       <url>http://m2.neo4j.org/content/repositories/snapshots</url>
       <snapshots>
           <enabled>true</enabled>
       </snapshots>
  </repository> 

Or use the SDN 4.1 snapshot

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-neo4j</artifactId>
    <version>4.1.0.BUILD-SNAPSHOT</version>
</dependency>

Then your graph should look like

Using Cypher directly is not a good idea as you'd have to be able to look up the nodes (maybe by ID), which would mean they have to be saved first.