Edited relationships reference chapter.

This commit is contained in:
David Montag
2011-04-07 20:56:14 -07:00
parent b10ecc8c58
commit 1a050d9dd1
2 changed files with 126 additions and 99 deletions

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<section id="reference:programming_model:annotations">
<title>Using annotations to define POJO Node Entities</title>
<title>Annotations define POJO node entities</title>
<para>Entities are declared using the <code>@NodeEntity</code> annotation.
Relationship entities use the <code>@RelationshipEntity</code> annotation.
</para>

View File

@@ -1,74 +1,84 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<section id="reference:programming_model:relationships">
<title>How to relate Node Entities using Relationships</title>
<para>As relationships are first level citizens in Neo4j, associations between Node-Entities are represented by
relationships. In general, relationships are categorized by a type and start and end-nodes (which also imply its direction).
They can have an arbitrary number of properties. Spring Data Graph has special support to represent Neo4j relationships
as Relationship Entities but this is not mandatory.
<title>Relationships relate node entities</title>
<para>
Since relationships are first-class citizens in Neo4j, associations between node entities are represented
by relationships. In general, relationships are categorized by a type, and start and end nodes (which
imply the direction of the relationship). Relationships can have an arbitrary number of properties.
Spring Data Graph has special support to represent Neo4j relationships as entities too, but it is often
not needed.
</para>
<section>
<title>@RelatedTo: Connecting NodeEntities</title>
<title>@NodeEntity</title>
<para>
Every attribute of a Node Entity that refers to one or more Node Entity represents relationships and
is handled by the field-aspects to be reflected in the graph.
Any class annotated with @NodeEntity will be backed by a node in the graph. Its fields will, if their
types are supported, be persisted as properties to the node for each entity.
</para>
</section>
<section>
<title>@RelatedTo: Connecting node entities</title>
<para>
Every field of a node entity that references one or more other node entities is backed by relationships
in the graph. These relationships are managed by Spring Data Graph automatically.
</para>
<para>
Those can either be single relationships (1:1) or multiple relationships (1:N).
In most cases single relationships to other node entities don't have to be annotated, as Spring Data Graph
can extract all necessary information
from the field using reflection. In the case of multiple relationships, the <code>elementClass</code>
parameter of @RelatedTo must be specified because of type erasure. The <code>direction</code>
(default OUTGOING) and <code>type</code> (inferred from field name) parameters of the annotation are
optional.
The simplest kind of relationship is a single field pointing to another node entity (1:1).
In this case, the field does not have to be annotated at all, although the annotation may be
used to control the direction and type of the relationship. When setting the field, a
relationship is created. If the field is set to <code>null</code>, the relationship is removed.
</para>
<para>
Single Relationships to other node entities are created when setting the field (deleting previously set
relationships) and deleted when setting it to null.
</para>
<para>
References to a set of Node Entities are declared as fields with a <code>Set&lt;T&gt;</code> type, where T
is a concrete Node-Entity. @RelatedTo is used again to provide information about type-name, elementClass and
direction.
It is not necessary to initialize the set as it is managed by Spring Data Graph, representing the relationships
from (to) this entity with the given type. Adding and removing from the set is reflected on the graph.
</para>
<para>
Spring Data Graph also ensures that there is only one relationship of the given type between two
given entities.
</para>
<note>
By setting direction to BOTH, relationships are created in the outgoing direction, but when the 1:N field
is read, it will include relationships in both directions. A cardinality of M:N is not necessary because
relationships can be navigated in both directions.
</note>
<example>
<title>Node Entity with Relationships</title>
<programlisting language="java"><![CDATA[
<example>
<title>Single relationship field</title>
<programlisting language="java"><![CDATA[
@NodeEntity
public class Movie {
private Actor topActor;
}
@NodeEntity
public class Person {
@RelatedTo(type = "topActor", direction = Direction.INCOMING)
private Movie wasTopActorIn;
}
@NodeEntity
public class Actor {
@RelatedTo(type = "ACTS_IN", elementClass = Movie.class)
private Set<Movie> movies;
private Actor mostPaidActor;
}
]]></programlisting>
</example>
</example>
<para>
Other means of handling relationships are the introduced <code>entity.getRelationshipTo(target,type)</code> and
<code>entity.relateTo(target,type)</code> methods that are available on each NodeEntity. Those methods create
and return Neo4j relationships. It is possible to remove relationships manually using
<code>entity.removeRelationshipTo(target,type)</code>. For creating and accessing relationship-entities,
their equivalents are available.
It is also possible to have fields that reference a set of node entities (1:N). These fields come in
two forms, modifiable or read-only. Modifiable fields are of the type <code>java.util.Set&lt;T></code>,
and read-only fields are <code>java.lang.Iterable&lt;T></code>, where T is a @NodeEntity-annotated
class. The Java implementation of generics uses type erasure, meaning that the type parameters are
typically not available at runtime. Therefore, the <code>elementClass</code> attribute must be
specified on the annotation, which must always be present for 1:N fields.
</para>
<example>
<title>Node entity with relationships</title>
<programlisting language="java"><![CDATA[
@NodeEntity
public class Actor {
@RelatedTo(type = "mostPaidActor", direction = Direction.INCOMING, elementClass = Movie.class)
private Set<Movie> mostPaidIn;
@RelatedTo(type = "ACTS_IN", elementClass = Movie.class)
private Set<Movie> movies;
}
]]></programlisting>
</example>
<para>
Fields referencing other entities should not be manually initialized, as they are managed by
Spring Data Graph under the hood. 1:N fields can be accessed immediately, and Spring Data Graph
will provide a java.util.Set representing the relationships. If the returned set is modified,
the changes are reflected in the graph. Spring Data Graph also ensures that there is only one
relationship of a given type between any two given entities.
</para>
<note>
By setting direction to BOTH, relationships are created in the outgoing direction, but when the
1:N field is read, it will include relationships in both directions. A cardinality of M:N is
not necessary because relationships can be navigated in both directions.
</note>
<para>
The relationships can also be accessed by using the aspect-introduced methods
<code>entity.getRelationshipTo(target, type)</code> and
<code>entity.relateTo(target, type)</code> available on each NodeEntity.
These methods find and create Neo4j relationships. It is also possible to manually remove
relationships by using <code>entity.removeRelationshipTo(target, type)</code>.
Using these methods is rarely necessary though.
</para>
</section>
@@ -76,54 +86,71 @@ private Set<Movie> movies;
<title>@RelationshipEntity: Rich relationships</title>
<para>
To access the full data model of graph relationships, POJOs can also be annotated with
@RelationshipEntity. Relationship entities can not be instantiated directly but are rather accessed via
node entities, either by @RelatedToVia fields or by the introduced
<code>entity.relateTo(target,relationshipClass,type)</code> and
<code>entity.getRelationshipTo(target,relationshipClass,type)</code> methods
(<xref linkend="reference:programming-model:introduced-methods"/>).
</para><para>
Relationship entities may contain fields that are mapped to simple properties and two special fields that are
annotated with <code>@StartNode</code> and <code>@EndNode</code> which point to the start and end node entities respectively. These
fields are treated as read only fields.
<code>@RelationshipEntity</code>, making them relationship entities. Just as node entities represent
nodes in the graph, relationship entities represent relationships. As described above,
fields annotated with <code>@RelatedTo</code> provide a way to link node entities together
via relationships, but it provides no way of accessing the relationships themselves.
</para>
<example>
<title>Relationship Entity</title>
<programlisting language="java"><![CDATA[
@RelationshipEntity
public class Role {
String title;
@StartNode private Actor actor;
@EndNode private Movie movie;
}
]]></programlisting>
</example> </section>
<section>
<title>@RelatedToVia: Connecting Node Entitites via Relationship Entities</title>
<para>
To provide easy programmatic access to the richer relationship entities of the data model, a different
annotation <code>@RelatedToVia</code> can be declared on fields of <code>Iterable</code>s of the relationship entity type.
These Iterables then provide read only access to instances of the entity that backs the relationship of this
relationship type. Those instances are initialized with the properties of the relationship and the start
and end node.
Relationship entities cannot be instantiated directly but are rather created via
node entities, either by @RelatedToVia-annotated fields
(see <xref linkend="reference:programming_model:relationships:relatedtovia"/>),
or by the introduced
<code>entity.relateTo(target, relationshipClass, type)</code> and
<code>entity.getRelationshipTo(target, relationshipClass, type)</code> methods
(see <xref linkend="reference:programming-model:introduced-methods"/>).
</para>
<example>
<title>Using Relationship Entities and @RelatedToVia</title>
<programlisting language="java"><![CDATA[
<para>
Fields in relationship entities are, similarly to node entities, persisted as properties on
the relationship. For accessing the two endpoints of the relationship, two special annotations
are available: <code>@StartNode</code> and <code>@EndNode</code>. A field annotated with
one of these annotations will provide read-only access to the corresponding endpoint, depending
on the chosen annotation.
</para>
<example>
<title>Relationship entity</title>
<programlisting language="java"><![CDATA[
@NodeEntity
public class Actor {
@RelatedToVia(type = "ACTS_IN", elementClass = Role.class)
private Iterable<Role> roles;
public Role playedIn(Movie movie, String title) {
Role role=relateTo(movie,Role.class,"ACTS_IN");
role.setTitle(title);
return role;
public Role playedIn(Movie movie, String title) {
return relatedTo(movie, Role.class, "ACTS_IN");
}
}
@RelationshipEntity
public class Role {
String title;
@StartNode private Actor actor;
@EndNode private Movie movie;
}
]]></programlisting>
</example>
</section>
<section id="reference:programming_model:relationships:relatedtovia">
<title>@RelatedToVia: Accessing relationship entities</title>
<para>
To provide easy programmatic access to the richer relationship entities of the data model,
the annotation <code>@RelatedToVia</code> can be added on fields of type
<code>java.lang.Iterable&lt;T></code>, where T is a <code>@RelationshipEntity</code>-annotated
class. These fields provide read-only access to relationship entities.
</para>
<example>
<title>Accessing relationship entities using @RelatedToVia</title>
<programlisting language="java"><![CDATA[
@NodeEntity
public class Actor {
@RelatedToVia(type = "ACTS_IN", elementClass = Role.class)
private Iterable<Role> roles;
public Role playedIn(Movie movie, String title) {
Role role = relateTo(movie, Role.class, "ACTS_IN");
role.setTitle(title);
return role;
}
}
]]></programlisting>
</example>
</example>
</section>
</section>