Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Migrating Spring Data Neo4j 3.x to 4.0 - Graph Entities

DZone's Guide to

Migrating Spring Data Neo4j 3.x to 4.0 - Graph Entities

In this installment, we get to the heart of dealing with graphs in Spring Data Neo4j: Graph entities, namely, nodes and relationships (as Neo4j refers to them). Read on and learn more.

· Database Zone
Free Resource

Whether you work in SQL Server Management Studio or Visual Studio, Redgate tools integrate with your existing infrastructure, enabling you to align DevOps for your applications with DevOps for your SQL Server databases. Discover true Database DevOps, brought to you in partnership with Redgate.

In this installment, we get to the heart of dealing with graphs in Spring Data Neo4j: Graph entities, namely, nodes and relationships (as Neo4j refers to them).

"Finally," you faithful readers are sighing, "the stuff I'm really interested in!  Right up there with 'free drinks' and Netflix."

Image title

Fair point.

The good news is that these entities are largely the same in SDN 4.0 as they were in previous versions; however, there are a few differences that we will highlight and navigate—nothing this crowd can't handle!

The largest similarity is that you still annotate your POJOs that represent nodes and relationships.

Just like previous versions of SDN, relationships POJOs are only necessary when you need to store properties of a relationship, so if you just need a plain relationship with no properties, simply annotating the appropriate properties in your node POJO will suffice!

Let's have a closer look at each entity type.

I Nodes What You Are Thinking

Von Neumann's Store is nothing without its customers!  So let's have a peak at some important parts of the Customer POJO, shall we?

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

    private String username;

    private String firstName;
    private String lastName;
    private String email;

    @Relationship(type = "FRIEND", direction = Relationship.UNDIRECTED)
    Set<Customer> friends;

    @Relationship(type = "PURCHASED", direction = Relationship.OUTGOING)
    Iterable<Purchase> purchases;

    @Relationship(type = "HAS_ADDRESS", direction = Relationship.OUTGOING)
    Address address;

    ...
}

A lot of this should look very familiar.

  • @NodeEntity is just the same as before.  When Customer is persisted to the graph, a :Customer label is automatically created and used.  Previously, if we wanted to use a different label, we would have had to have used the @TypeAlias annotation—not so anymore!  @NodeEntity has available an attribute called "label" that allows you to set a different label, e.g. @NodeEntity(label = "LifeBloodOfBusiness").

  • @GraphId is needed just as before, and it must be of type Long; however, if you have a property called "id" of type Long, the @GraphId annotation is not required as SDN will automatically use the field for its purposes.  It's worth noting that the type must be the non-primitive Long.  And, as an important reminder, remember that 0 is a valid value for a Neo4j node ID.

  • Other primitive (both single and array-based) and string fields are automatically persisted into the node.

  • What might jump out at you is the use of @Relationship.  Let's talk about this a bit more.

Relationships Are Now a Lot Less Work

Image title

Spring Data Neo4j won't judge you!

@Relationship has replaced both @RelatedTo and @RelatedToVia.  Recall that the former was used to relate a node to another node (or group of nodes) and that the latter was used to designate a relationship entity (recall what relationship entities are used for as stated above) to use for a specific relationship.

These two annotations have both been replaced by @Relationship.  Simpler is better!  SDN is smart enough to know what you mean based on the type of the field.  All that is required is a "type" and a "direction".

Also notice that Relationship.* (where "*" can be one of INCOMING, OUTOING, or UNDIRECTED) has replaced Direction.* when specifying the relationship's direction.  It is important to note that while the use of UNDIRECTED simply ignores the relationship direction actually stored in the graph, the persisted relationship does not, in fact, lack direction.

"But what if you have relationships that are of the same name but point to different node types?" the astute reader (that is, you) is asking.  In previous versions of SDN, we had to specify an "enforceTargetType" attribute into the annotation.  Not so anymore!  SDN is smart enough to know what you mean, and so this kind of situation is made easier to deal with.

(It is worth noting that the target types must be of differeing types.)

Another quick reminder: If you are relating a group of nodes to your node POJO and need the group to be modifiable, you would generally use a Set<T> (or some other Collection-based container); otherwise, you should use Iterable<T> for read-only fields.  Also, be careful if order is important: A Set cannot relied about for order, while Iterable can.

Phew, okay, let's now have a look at relationship entities!

A Graph Without Relationships Is Like a Day Without Sunshine!

Relationships form the heart of any graph—they are what give the graph meaning.

Image title

SHOW ME THE MONEY! ...no, wait...

(Courtesy: indatimes.in and TriStar Pictures)

Now, ordinarily, we don't need relationship POJOs if we are persisting relationships that have no properties; however, when we do need to persist properties on a relationship, we require the use of a relationship entity.

Let's have a look at one!

@RelationshipEntity(type = "PURCHASED")
public class Purchase {
    @GraphId
    private Long id;

    @StartNode
    private Customer customer;

    @EndNode
    private Stock item;

    private int quantity = 0;

    ...
}

Again, a lot of similarities exist here with the previous version of SDN:

  • @RelationshipEntity operates just like it used to, with the "type" attribute being required (after all, what good is a relationship without a type/name?)
  • @GraphId is used in exactly the same way as for node entities, with exactly the same caveats and semantics.

  • @StartNode and @EndNode work just as before and are required, specifying the "source" of the relationship and the "destination" of the relationship.

So, as you can see, there really is no appreciable difference between older versions of SDN and SDN 4.0 when it comes to relationships.  Awesome!

Conclusion

In this post we have seen the differences and uses of the annotations that are at the heart of Spring Data Neo4j.  Node entities and relationship entities are both crucial to persisting and retrieving our graphs, and make our lives significantly easier when dealing with such an integration.

The good news is that the use of these entities, while similar and familar, have been improved to help speed up productivity and avoid some pitfalls that used to exist.

In the next post, we will have a quick look at indices in Spring Data Neo4j and wrap up this series. I know, I know—I'm just as sad as you are, but, all good things must come to an end.  Or not. Hopefully not.  

See you in the next post!

It’s easier than you think to extend DevOps practices to SQL Server with Redgate tools. Discover how to introduce true Database DevOps, brought to you in partnership with Redgate

Topics:
spring data neo4j ,neo4j ,java ,spring ,spring data ,integration ,database

Opinions expressed by DZone contributors are their own.

THE DZONE NEWSLETTER

Dev Resources & Solutions Straight to Your Inbox

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

X

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}