updated documentation

This commit is contained in:
Michael Hunger
2011-03-28 02:23:20 +02:00
parent 4af1f342ee
commit f00a713069
15 changed files with 257 additions and 212 deletions

View File

@@ -52,6 +52,7 @@
</partintro>
<xi:include href="reference/preface.xml"/>
<xi:include href="reference/spring-data.xml" />
<xi:include href="reference/neo4j.xml"/>
<xi:include href="reference/programming-model/programming-model.xml"/>
<xi:include href="reference/setup.xml"/>
@@ -59,10 +60,7 @@
<xi:include href="reference/samples.xml"/>
<xi:include href="reference/performance.xml" />
<xi:include href="reference/template.xml" />
<xi:include href="reference/annotations.xml" />
<xi:include href="reference/aspectj-intro.xml" />
<xi:include href="reference/neo4j-intro.xml" />
<xi:include href="reference/spring-data.xml" />
<xi:include href="reference/neo4j-server.xml" />
</part>
</book>

View File

@@ -1,50 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="reference_annotations">
<title>Annotation-driven persistence</title>
<para>
...
</para>
<section>
<title>Annotations</title>
<para>
... this is the most important part
</para>
</section>
<section>
<title>Introduced methods</title>
<para>
...
</para>
</section>
<section>
<title>Finders</title>
<para>
...
</para>
</section>
<section>
<title>GraphDatabaseContext</title>
<para>
...
</para>
</section>
<section>
<title>Indexing</title>
<para>
...
</para>
</section>
<section>
<title>Traversal</title>
<para>
...
</para>
</section>
<section>
<title>EntityMapper and Path</title>
<para>
...
</para>
</section>
</chapter>

View File

@@ -2,6 +2,25 @@
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="neo4j">
<title>Introduction to Neo4j</title>
<section>
<title>What is a graph database?</title>
<para>A graph database is a storage engine that is specialized in storing and retrieving vast networks of
data. It efficiently stores nodes and relationships and allows high performance traversal of those
structures. With property graphs it is possible to add an arbitrary number of properties to nodes
and relationships.</para>
<para>
Graph databases are well suited to model most kinds of domains. In almost all domains there are certain
things connected to other things. The classes of things are not the most important aspect, rather that each
invidual instance is represented correctly (with all its necessary properties) in the domain model. In most
other modelling approaches the relationships between things are reduced to a single link without identity
and attributes. Graph databases allow to keep the rich relationshiops that originate from the domain equally
well represented in the model without resorting to model relationships as "things". So there is no impedance
mismatch when putting real life domains into graph databases.
</para>
</section>
<section>
<title>About Neo4j</title>
<para>
<ulink url="http://neo4j.org/">Neo4j</ulink> is a graph database. It is a fully ACID transactional database that
stores data structured as graphs. A graph consists of nodes, connected by relationships. It is a flexible
@@ -32,28 +51,30 @@
</itemizedlist>
</para>
<para>
In addition, Neo4j includes the usual database features: ACID transactions, durable persistence,
In addition, Neo4j includes the usual database characteristics: ACID transactions, durable persistence,
concurrency control, transaction recovery, high availability and everything else youd expect from an
enterprise database. Neo4j is released under a dual free software/commercial license model.</para>
<section>
<title>What is a graph database?</title>
<para>A graph database is a storage engine that is specialized in storing and retrieving vast networks of
data. It efficiently stores nodes and relationship and allows high performance traversal of those
structures. With property graphs it is possible to add an arbitrary number of properties to nodes
and relationships.</para>
</section>
<section>
<title>GraphDatabaseService</title>
<para>The interface org.neo4j.graphdb.GraphDatabaseService provides access to the storage engine. Its features include creating and retrieving Nodes and Relationships, managing indexes, via an IndexManager, database lifecycle callbacks, transation management and more.
<para>The interface org.neo4j.graphdb.GraphDatabaseService provides access to the storage engine. Its features
include creating and retrieving Nodes and Relationships, managing indexes, via an IndexManager, database
lifecycle callbacks, transation management and more.
</para>
<para>
The EmbeddedGraphDatabaseService is an implementation of GraphDatabaseService that is used to embed Neo4j in a Java application. This implmentation is used so as to provide the highest and tightest integration. There are other,
remote implementations that provide access to Neo4j stores via REST.</para>
The EmbeddedGraphDatabaseService is an implementation of GraphDatabaseService that is used to embed Neo4j in
a Java application. This implmentation is used so as to provide the highest and tightest integration. Besides
the embedded mode, the
<ulink url="http://wiki.neo4j.org/content/Getting_Started_With_Neo4j_Server">Neo4j server</ulink> provides
access to the graph database via a convenient REST-API.</para>
</section>
<section>
<title>Creating Nodes and Relationships</title>
<para>Using the API of GraphDatabaseService it is easy to create nodes and relate them to each other. Relationships are named. Both nodes and relationships can have properties. Property values can be primitive Java types and Strings, byte arrays for binary data, or arrays of other Java primitives or Strings.
Node creation and modification has to happen within a transaction, while reading from the graph store can be done with or without a transaction.
<para>Using the API of GraphDatabaseService it is easy to create nodes and relate them to each other. Relationships
are named. Both nodes and relationships can have properties. Property values can be primitive Java types and
Strings, byte arrays for binary data, or arrays of other Java primitives or Strings.
Node creation and modification has to happen within a transaction, while reading from the graph store can be
achieved with or without a transaction.
<programlisting language="java" ><![CDATA[
GraphDatabaseService graphDb = new EmbeddedGraphDatabase( "helloworld" );
Transaction tx = graphDb.beginTx();

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<preface id="preface">
<preface id="reference:preface">
<title>Preface</title>
<para>The Spring Data Graph project applies core Spring concepts to the development of solutions using a graph style data store.
@@ -11,7 +11,10 @@
special relationship entities that provide access to the properties of graph relationships.
</para>
<para>
For the developer of a Spring Data Graph backed application only the public annotations are relevant, basic knowledge of graph stores is needed
to access advanced functionality like traversals. Traversal results can also be mapped to fields of entities.
For the developer of a Spring Data Graph backed application only the public annotations
(<xref linkend="reference:programming_model:annotations"/>) and the additional,
added entity methods (<xref linkend="reference:programming-model:introduced-methods"/>) are relevant.
Basic knowledge of graph stores is needed to access advanced functionality like traversals.
Traversal results can also be mapped to fields of entities.
</para>
</preface>

View File

@@ -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>

View File

@@ -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&lt;? extends NodeEntity&gt;, 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>

View File

@@ -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

View File

@@ -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&lt;T&gt;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&lt;T&gt; 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&lt;T&gt; 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&lt;T&gt; findAllByQuery(indexName, keyName, queryOrQueryContext)</code> </para> </listitem>
</varlistentry>
<varlistentry>
<term>iterating over a traversal result</term>
<listitem> <para> <code>Iterable&lt;T&gt; 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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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&lt;T&gt;</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>

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>
<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

View File

@@ -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>

View File

@@ -3,6 +3,9 @@
<chapter id="reference_spring-data">
<title>Spring Data</title>
<para>
...
<ulink url="http://springsource.org/spring-data">Spring Data</ulink> is a SpringSource project that aims to
provide Spring's convenient programming model and well known conventions for NoSQL databases. Currently there
is support for Graph (e.g. Neo4j), Key-Value (e.g. Redis), Document (e.g. MongoDB) and Relational (e.g. Oracle)
databases. Mark Pollack, the author of Spring.NET is the project lead for the Spring Data project.
</para>
</chapter>

View File

@@ -1,38 +1,91 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN" "http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="reference_template">
<title>Neo4jTemplate</title>
<para>
...
</para>
<section>
<title>Transaction handling/management</title>
<title>Neo4jTemplate</title>
<para>
...
The <code>Neo4jTemplate</code> offers the convenient API of Spring templates for the Neo4j graph database.
It is initialized with a <code>GraphDatabaseService</code> which is thread-safe to use.
</para>
</section>
<section>
<title>Basic operations</title>
<para>
...
For direct retrieval of nodes and relationships the <code>getReferenceNode</code>, <code>getNode</code> and
<code>getRelationship</code> can be used.
</para>
<para>
There are methods (<code>createNode</code> and <code>createRelationship</code>) for creating nodes and
relationships that automatically set provided properties and optionally index certain fields.
</para>
<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>
</para>
</section>
<section>
<title>Indexing</title>
<para>
...
Adding nodes and relationships to an index is achieved using the <code>index</code> and <code>autoindex</code>)
methods.
</para>
<para>
<code>Query</code> 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. All <code>query</code> methods provide
<code>Path</code> results to a PathMapper.
</para>
</section>
<section>
<title>Traversal</title>
<para>
...
Traversal methods are at the core 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 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>
</section>
<section>
<title>Path abstraction and PathMapper</title>
<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.
</para>
<para>
Using implementations of <code>PathMapper&lt;T&gt;</code>
and <code>PathMapper.WithoutResult</code> (comparable with <code>RowMapper</code> and
<code>RowCallbackHandler</code>) the paths can be converted to arbitrary Java objects.
</para>
<para>
With <code>EntityPath</code> and <code>EntityMapper</code> there is also support for using annotation based
NodeEntities within the <code>Path</code> and <code>PathMapper</code> constructs.
</para>
</section>
<section>
<title>PathMapper</title>
<title>Transaction handling/management</title>
<para>
... path as general return type?
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>
</section>
</chapter>