updated documentation
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
<?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>
|
||||
<section id="reference:programming_model:annotations">
|
||||
<title>Using annotations to define POJO entities and relationships</title>
|
||||
<para>Entities are declared using the <code>@NodeEntity</code> annotation. Relationship entities use the
|
||||
<code>@RelationshipEntity</code>
|
||||
@@ -13,14 +13,17 @@
|
||||
graph store. Simple fields on the entity are mapped by default to properties of the node. Object
|
||||
references to other NodeEntities (whether single or Collection) are mapped via relationships. If
|
||||
the annotation parameter <code>useShortNames</code> is set to false, the properties and relationship
|
||||
names used will be prepended with the class name of the entity. If the parameter <code>fullIndex</code>
|
||||
is set to true, all fields of the entity will be indexed. If the <code>partial</code>
|
||||
parameter is set to true, this entity takes part in a cross-store setting where only
|
||||
the parts of the entity not handled by JPA will be mapped to the graph store.
|
||||
names used will be prepended with the class name of the entity.
|
||||
</para><para>
|
||||
If the <code>partial</code>
|
||||
parameter is set to true, this entity takes part in a cross-store setting /<xref linkend="cross-store"/>)
|
||||
where only the specifically annotated parts of the entity not handled by JPA will be mapped to the graph store.
|
||||
</para>
|
||||
<para>Entity fields can be annotated with @GraphProperty, @RelatedTo, @RelatedToVia, @Indexed and @GraphId
|
||||
<para>Entity fields can be annotated with @GraphProperty, @RelatedTo, @RelatedToVia, @Indexed, @GraphId and
|
||||
@GraphTraversal.
|
||||
</para>
|
||||
<programlisting language="java"><![CDATA[
|
||||
// simplest example
|
||||
@NodeEntity
|
||||
public class Movie {
|
||||
String title;
|
||||
@@ -40,7 +43,7 @@ public class Movie {
|
||||
optional.
|
||||
</para>
|
||||
<para>
|
||||
Relationships to single node entities are created when setting the field and deleted when setting it to
|
||||
Single Relationships to other node entities are created when setting the field and deleted when setting it to
|
||||
null. For multi-relationships the field provides a managed collection (Set) that handles addition and
|
||||
removal of node entities and reflects those in the graph relationships.
|
||||
</para>
|
||||
@@ -66,9 +69,10 @@ public class Actor {
|
||||
<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't be instantiated directly but are rather accessed via
|
||||
@RelationshipEntity. Relationship entities can not be instantiated directly but are rather accessed via
|
||||
node entities, either by @RelatedToVia fields or by the <code>relateTo</code> or
|
||||
<code>getRelationshipTo</code> methods.
|
||||
<code>getRelationshipTo</code> methods <xref linkend="reference:programming-model:introduced-methods"/>.
|
||||
</para><para>
|
||||
Relationship entities may contain fields that are mapped to properties and two special fields that are
|
||||
annotated with @StartNode and @EndNode which point to the start and end node entities respectively. These
|
||||
fields are treated as read only fields.
|
||||
@@ -76,10 +80,10 @@ public class Actor {
|
||||
<programlisting language="java"><![CDATA[
|
||||
@RelationshipEntity
|
||||
public class Role {
|
||||
@StartNode
|
||||
private Actor actor;
|
||||
@EndNode
|
||||
private Movie movie;
|
||||
String title;
|
||||
|
||||
@StartNode private Actor actor;
|
||||
@EndNode private Movie movie;
|
||||
}
|
||||
]]></programlisting>
|
||||
</section>
|
||||
@@ -98,6 +102,12 @@ public class Role {
|
||||
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>
|
||||
</section>
|
||||
@@ -113,18 +123,22 @@ public class Actor {
|
||||
<section>
|
||||
<title>@Indexed: Making entities searchable by field value</title>
|
||||
<para>The @Indexed annotation can be declared on fields that are intended to be indexed by the Neo4j
|
||||
IndexManager, triggered by value modification.
|
||||
indexing facilities, triggered by value modification.
|
||||
The resulting index can be used to later retrieve nodes or relationships that contain a certain property
|
||||
value (for example a name). Often an index is used to establish the start node for a traversal.
|
||||
Indexes are accessed by a Finder for a particular NodeEntity or RelationshipEntity, created via a
|
||||
FinderFactory.
|
||||
Indexes are accessed by a <code>Finder</code> for a particular node or relationship entity, created via a
|
||||
<code>FinderFactory</code>.
|
||||
</para>
|
||||
<para>
|
||||
GraphDatabaseContext exposes the indexes for Nodes and Relationships. Indexes can
|
||||
be named, for instance to keep separate domain concepts in separate indexes. That's why it is possible
|
||||
to specifiy an index name with the @Indexed annotation. It can also be specified at the entity level,
|
||||
this name is then the default index name for all fields of the entity. If no index name is specified,
|
||||
it defaults to the one configured with Neo4j ("node" and "relationship").
|
||||
GraphDatabaseContext exposes the indexes for Nodes and Relationships via the <code>getIndex</code> method.
|
||||
Index names default to the domain class
|
||||
name, but can also be named (<code>indexName</code> attribute)individually to reflect domain concepts.
|
||||
be named, for instance to keep separate domain concepts in separate indexes.
|
||||
</para>
|
||||
<para>
|
||||
Numerical values are indexed as such by default, allowing for range queries.
|
||||
Fulltext indexing is also possible by setting the <code>fulltext</code> attribute to true. For details see
|
||||
the indexing section <xref linkend="reference_programming-model:indexing"/>.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -136,6 +150,25 @@ public class Actor {
|
||||
is created by a TraversalDescriptionBuilder whose class is referred to by the <code>traversalBuilder</code>
|
||||
attribute of the annotation. The class of the expected NodeEntities is provided with the
|
||||
<code>elementClass</code> attribute.
|
||||
<programlisting language="java"><![CDATA[
|
||||
@NodeEntity
|
||||
public class Group {
|
||||
@GraphTraversal(traversalBuilder = PeopleTraversalBuilder.class,
|
||||
elementClass = Person.class, params = "persons")
|
||||
private Iterable<Person> people;
|
||||
|
||||
private static class PeopleTraversalBuilder implements FieldTraversalDescriptionBuilder {
|
||||
@Override
|
||||
public TraversalDescription build(NodeBacked start, Field field, String...params) {
|
||||
return new TraversalDescriptionImpl()
|
||||
.relationships(DynamicRelationshipType.withName(params[0]))
|
||||
.filter(Traversal.returnAllButStartNode());
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
]]></programlisting>
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -143,8 +176,9 @@ public class Actor {
|
||||
<title>@GraphProperty: Cross-store persisted fields</title>
|
||||
<para>It is not necessary to annotate fields as they are persisted by default; all fields that contain primitive
|
||||
values are persisted directly to the graph. All fields
|
||||
convertible to String using the Spring conversion services will be stored as a string. Transient fields are
|
||||
not persisted.
|
||||
convertible to String using the Spring conversion services will be stored as a string.
|
||||
(Spring Data Graph adds a custom conversion factory that comes with converters for Enums and Dates).
|
||||
Transient fields are not persisted.
|
||||
This annotation is mainly used for cross-store persistence.
|
||||
</para>
|
||||
</section>
|
||||
|
||||
@@ -2,24 +2,28 @@
|
||||
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
|
||||
<section>
|
||||
<title>Overview of the AspectJ support</title>
|
||||
<para>Behind the scenes Spring Data Graph leverages AspectJ aspects to modify the behavior of simple POJO entities
|
||||
to be
|
||||
able to be backed by a graph store. Each entity is backed by a node that holds its properties and
|
||||
relationships to other entities. AspectJ is used to intercept field access and to reroute it to the backing
|
||||
state (either its properties or relationships). For relationship entities the fields are similarly mapped to
|
||||
properties. There are two specially annotated fields for the start and the end node of the relationship.
|
||||
<para>Behind the scenes Spring Data Graph leverages <ulink url="http://www.eclipse.org/aspectj/">AspectJ</ulink>
|
||||
(<xref linkend="reference_aspectj-intro"/>)
|
||||
aspects to modify the behavior of simple POJO entities to be able to be backed by a graph store.
|
||||
Each node entity is backed by a graph node that holds its properties and relationships to other entities.
|
||||
AspectJ is used to intercept field access and to retrieve the information from the backing node
|
||||
(either its properties or relationships or dynamic traversals starting from the node).
|
||||
|
||||
For relationship entities the fields are similarly mapped to properties.
|
||||
There are two specially annotated fields for the start and the end node of the relationship.
|
||||
</para>
|
||||
<para>
|
||||
The aspect introduces some internal fields and some public methods to the entities for accessing the backing
|
||||
The aspect introduces some internal fields and some public methods (<xref linkend="reference:programming-model:introduced-methods"/>)
|
||||
to the entities for accessing the backing
|
||||
state via <code>getPersistentState()</code> and creating relationships with <code>relateTo</code>
|
||||
and retrieving relationship entities via<code>getRelationshipTo</code>. It also introduces finder methods like
|
||||
and retrieving relationship entities via <code>getRelationshipTo</code>. It also introduces finder methods like
|
||||
<code>find(Class<? extends NodeEntity>, TraversalDescription)</code>
|
||||
and equals and hashCode delegation.
|
||||
</para>
|
||||
<para>
|
||||
Spring Data Graph internally uses an abstraction called EntityState that the field access and instantiation
|
||||
Spring Data Graph internally uses an abstraction called <code>EntityState</code> that the field access and instantiation
|
||||
advices of the aspect delegate to, keeping the aspect code very small and focused to the pointcuts and
|
||||
delegation code. The EntityState then uses a number of FieldAccessor factories to create a FieldAccessor
|
||||
instance per field that does the specific handling needed for the concrete field.
|
||||
delegation code. The <code>EntityState</code> then uses a number of <code>FieldAccessorFactories</code>
|
||||
to create a <code>FieldAccessor</code> instance per field that does the specific handling needed for the concrete field type.
|
||||
</para>
|
||||
</section>
|
||||
@@ -3,7 +3,7 @@
|
||||
<section>
|
||||
<title>Bean Validation - JSR-303</title>
|
||||
<para>
|
||||
Spring Data Graph supports property based validation support. So whenever a property is changed, it is
|
||||
Spring Data Graph supports property based validation support. So, whenever a property is changed, it is
|
||||
checked against the annotated constraints (.e.g @Min, @Max, @Size, etc).
|
||||
Validation errors throw a ValidationException. For evaluating the constraints the validation support that
|
||||
comes with Spring is used. To use it a validator has to be registered with the GraphDatabaseContext, if there
|
||||
|
||||
@@ -2,49 +2,81 @@
|
||||
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
|
||||
<section>
|
||||
<title>Finding nodes with finders</title>
|
||||
<para>Spring Data Graph also comes with a type bound Repository-like
|
||||
Finder implementation that provides methods for locating nodes
|
||||
and relationships:
|
||||
<itemizedlist>
|
||||
<listitem>
|
||||
<para>using direct access <code>findById(id)</code>,</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>iterating over all nodes of a node entity type (findAll),</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>counting the instances of a node entity type (count),</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>iterating over all indexed instances with a certain property value (findAllByPropertyValue),
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>getting a single instance with a certain property value (findByPropertyValue),</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>iterating over all indexed instances within a certain numerical range (inclusive)
|
||||
(findAllByRange),
|
||||
</para>
|
||||
</listitem>
|
||||
<listitem>
|
||||
<para>iterating over a traversal result (findAllByTraversal).</para>
|
||||
</listitem>
|
||||
</itemizedlist>
|
||||
The Finder instances are created via a FinderFactory to be bound to a
|
||||
concrete node or relationship entity class.
|
||||
The FinderFactory is created in the Spring context and can be
|
||||
injected.
|
||||
<para>Spring Data Graph also comes with a typed, repository-like Finder implementation that provides methods for
|
||||
locating nodes and relationships. Those methods return instances of the node and relationship entities,
|
||||
not the graph primitives from Neo4j. Finders delegate to the configured <code>NodeTypeStrategy</code> for type
|
||||
based queries.
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>loading an instance via the Neo4j node id</term>
|
||||
<listitem> <para> <code>T findById(id)</code></para> </listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>iterating over all nodes of a node entity type</term>
|
||||
<listitem> <para> <code>Iterable<T>findAll()</code> </para> </listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>counting the instances of a node entity type</term>
|
||||
<listitem> <para> <code>long count()</code> </para> </listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>iterating over all indexed instances with a certain property value</term>
|
||||
<listitem> <para> <code>Iterable<T> findAllByPropertyValue(indexName, keyName, value)</code> </para> </listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>getting a single instance with a certain property value</term>
|
||||
<listitem> <para> <code>T findByPropertyValue(indexName, keyName, value)</code> </para> </listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>iterating over all indexed instances within a certain numerical range (inclusive)</term>
|
||||
<listitem> <para> <code>Iterable<T> findAllByRange(indexName, keyName, from, to)</code> </para> </listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>iterating over all indexed instances matching the given fulltext (or QueryContext query)</term>
|
||||
<listitem> <para> <code>Iterable<T> findAllByQuery(indexName, keyName, queryOrQueryContext)</code> </para> </listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>iterating over a traversal result</term>
|
||||
<listitem> <para> <code>Iterable<T> findAllByTraversal(startNode, traversalDescription)</code> </para> </listitem>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
The <code>Finder</code> instances are created via a FinderFactory to be bound to a concrete node or relationship entity class.
|
||||
The <code>FinderFactory</code> is configured in the Spring context and can be injected.
|
||||
<programlisting language="java"><![CDATA[
|
||||
NodeFinder<Person> finder = finderFactory.createNodeEntityFinder(Person.class);
|
||||
|
||||
Person dave=finder.findById(123);
|
||||
int people = finder.count();
|
||||
Person mark = finder.findByPropertyValue("name", "mark");
|
||||
Iterable<Person> devs = finder.findAllByProperyValue("occupation","developer");
|
||||
|
||||
long numberOfPeople = finder.count();
|
||||
|
||||
Person mark = finder.findByPropertyValue(null,"name", "mark");
|
||||
|
||||
Iterable<Person> devs = finder.findAllByProperyValue(null, "occupation","developer");
|
||||
|
||||
Iterable<Person> middleAgedPeople = finder.findAllByRange(null, "age",20,40);
|
||||
|
||||
Iterable<Person> aTeam = finder.findAllByQuery(null, "name","A*");
|
||||
|
||||
Iterable<Person> davesFriends = finder.findAllByTraversal(dave,
|
||||
Traversal.description().pruneAfterDepth(1)
|
||||
.relationships(KNOWS).filter(returnAllButStartNode()));
|
||||
|
||||
]]></programlisting>
|
||||
</para>
|
||||
<section>
|
||||
<title>NodeTypeStrategies: Storing Type Information in the Graph</title>
|
||||
<para>
|
||||
Internally the mapping from java types to the graph is handled by a <code>NodeTypeStrategy</code> instance
|
||||
that is configured with the <code>GraphDatabaseContext</code>. The strategy is called on entity creation and
|
||||
removal and provides methods for retrieving entities based on type. It also comes with methods confirming or
|
||||
retrieving java types from the actual graph node. (see also <xref linkend="nodetypestrategy"/>)
|
||||
</para>
|
||||
<para>
|
||||
The default strategy (<code>IndexingNodeTypeStrategy</code>)
|
||||
uses indexing (index "__types__") and node properties ("__type__") to store the type information in the graph.
|
||||
|
||||
The second strategy uses an in graph structure to represent the inheritance hierarchy links the actual node
|
||||
entity nodes to their concrete class nodes. Instance counts are updated on each of the class nodes in the hierarchy.
|
||||
The last provided strategy is a No-Op strategy that doesn't care about type information.
|
||||
</para>
|
||||
</section>
|
||||
</section>
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<para>
|
||||
The Neo4j graph database can use different index providers for exact lookups and fulltext searches. Lucene is
|
||||
used as a index provider implementation. There is support for distinct indexes for nodes and relationships
|
||||
used as default index provider implementation. There is support for distinct indexes for nodes and relationships
|
||||
which can be configured to be of fulltext or exact types.
|
||||
</para>
|
||||
|
||||
|
||||
@@ -4,8 +4,7 @@
|
||||
<title>Methods added to entity classes</title>
|
||||
<para>
|
||||
The node and relationship aspects introduce (via ITD - inter type declaration) several methods to the
|
||||
entities that make common tasks easier. Unfortunately these methods are not generified yet, so the
|
||||
results have to be casted to the correct return type.
|
||||
entities that make common tasks easier.
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term>persisting the node-entity initially and after changes outside of a transaction,
|
||||
@@ -64,7 +63,7 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>remove the node entity, its relationship and index entries</term>
|
||||
<term>remove the node entity, its relationships and index entries</term>
|
||||
<listitem>
|
||||
<para><code>entity.remove()</code></para>
|
||||
</listitem>
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
<?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:neo4jtemplate">
|
||||
<title>Neo4jTemplate</title>
|
||||
<para>
|
||||
The <code>Neo4jTemplate</code> offers the convenient API of Spring templates for the Neo4j graph database.
|
||||
There are methods for creating nodes and relationships that automatically set provided properties and optionally
|
||||
index certain fields. Other methods (<code>index</code>, <code>autoindex</code>) will index them.
|
||||
</para>
|
||||
<para>
|
||||
For the querying operations Neo4jTemplate unifies the result with the <code>Path</code> abstraction that
|
||||
comes from Neo4j. Much like a resultset a path contains <code>nodes()</code> and <code>relationships()</code>
|
||||
starting at a <code>startNode()</code> and ending with a<code>endNode()</code>, the
|
||||
<code>lastRelationship()</code> is also available separately. The <code>Path</code> abstraction also wraps
|
||||
results that contain just nodes or relationships. Using implementations of <code>PathMapper<T></code>
|
||||
and <code>PathMapper.WithoutResult</code> (comparable with <code>RowMapper</code> and
|
||||
<code>RowCallbackHandler</code>) the paths can be converted to Java objects.
|
||||
</para>
|
||||
<para>
|
||||
Query methods either take a field / value combination to look for exact matches in the index or a lucene query
|
||||
object or string to handle more complex queries.
|
||||
</para>
|
||||
<para>
|
||||
Traversal methods are the bread and butter of graph operations. As such, they are fully supported in the
|
||||
<code>Neo4jTemplate</code>. The <code>traverseNext</code> method traverses to the direct neighbours of the
|
||||
start node filtering the relationships according to its parameters.
|
||||
</para>
|
||||
<para>
|
||||
The <code>traverse</code> method covers the full fledged traversal operation that takes a powerful
|
||||
<code>TraversalDescription</code> (most probably built from the <code>Traversal.description()</code>
|
||||
DSL) and runs it from the start node. Each path that is returned via the traversal is passed to the
|
||||
<code>PathMapper</code> to be processed accordingly.
|
||||
</para>
|
||||
<para>
|
||||
The <code>Neo4jTemplate</code> provides configurable implicit transactions for all its methods. By default
|
||||
it creates a transaction for each call (which is a no-op if there is already a transaction running). If
|
||||
you call the constructor with the <code>useExplicitTransactions</code> parameter set to true, it won't
|
||||
create any transactions so you have to provide them using @Transactional or the TransactionTemplate.
|
||||
</para>
|
||||
<programlisting language="java"><![CDATA[
|
||||
Neo4jOperations neo = new Neo4jTemplate(grapDatabase);
|
||||
Node michael = neo.createNode(_("name","Michael"),"name");
|
||||
Node mark = neo.createNode(_("name","Mark"));
|
||||
Node thomas = neo.createNode(_("name","Thomas"));
|
||||
neo.createRelationship(mark,thomas, WORKS_WITH, _("project","spring-data"));
|
||||
neo.index("devs",thomas, "name","Thomas");
|
||||
neo.autoIndex("devs",mark, "name");
|
||||
assert "Mark".equals(neo.query("devs","name","Mark",new NodeNamePathMapper()));
|
||||
]]></programlisting>
|
||||
|
||||
</section>
|
||||
@@ -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>
|
||||
<title>Reified types for entities</title>
|
||||
<section id="nodetypestrategy">
|
||||
<title>Storing Type Information in the Graph</title>
|
||||
<para>
|
||||
There are several ways to represent the Java type hierarchy of the data model in the graph. In general for all
|
||||
node and relationship entities type information is needed to perform certain repository operations. Some of
|
||||
|
||||
@@ -17,6 +17,5 @@
|
||||
<xi:include href="nodetypestrategy.xml"/>
|
||||
<xi:include href="introducedmethods.xml"/>
|
||||
<xi:include href="projection.xml"/>
|
||||
<xi:include href="neo4jtemplate.xml"/>
|
||||
<xi:include href="beanvalidation.xml"/>
|
||||
</chapter>
|
||||
|
||||
Reference in New Issue
Block a user