diff --git a/src/docbkx/index.xml b/src/docbkx/index.xml
index 6730dd806..442c611db 100644
--- a/src/docbkx/index.xml
+++ b/src/docbkx/index.xml
@@ -52,6 +52,7 @@
+
@@ -59,10 +60,7 @@
-
-
-
diff --git a/src/docbkx/reference/annotations.xml b/src/docbkx/reference/annotations.xml
deleted file mode 100644
index 4eb3e85b6..000000000
--- a/src/docbkx/reference/annotations.xml
+++ /dev/null
@@ -1,50 +0,0 @@
-
-
-
- Annotation-driven persistence
-
- ...
-
-
- Annotations
-
- ... this is the most important part
-
-
-
- Introduced methods
-
- ...
-
-
-
-
- GraphDatabaseContext
-
- ...
-
-
-
-
-
- EntityMapper and Path
-
- ...
-
-
-
diff --git a/src/docbkx/reference/neo4j.xml b/src/docbkx/reference/neo4j.xml
index aace3d190..21db044c3 100644
--- a/src/docbkx/reference/neo4j.xml
+++ b/src/docbkx/reference/neo4j.xml
@@ -2,6 +2,25 @@
Introduction to Neo4j
+
+
+ What is a graph database?
+ 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.
+
+ 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.
+
+
+
+ About Neo4j
Neo4j 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 @@
- 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 you’d expect from an
enterprise database. Neo4j is released under a dual free software/commercial license model.
-
- What is a graph database?
- 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.
GraphDatabaseService
- 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.
+ 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.
- 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.
+ 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
+ Neo4j server provides
+ access to the graph database via a convenient REST-API.
Creating Nodes and Relationships
- 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.
+ 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.
-
+
Preface
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.
- 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
+ () and the additional,
+ added entity 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.
diff --git a/src/docbkx/reference/programming-model/annotations.xml b/src/docbkx/reference/programming-model/annotations.xml
index 7b1985e77..a4ee07134 100644
--- a/src/docbkx/reference/programming-model/annotations.xml
+++ b/src/docbkx/reference/programming-model/annotations.xml
@@ -1,6 +1,6 @@
-
+
Using annotations to define POJO entities and relationships
Entities are declared using the @NodeEntity annotation. Relationship entities use the
@RelationshipEntity
@@ -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 useShortNames is set to false, the properties and relationship
- names used will be prepended with the class name of the entity. If the parameter fullIndex
- is set to true, all fields of the entity will be indexed. If the partial
- 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.
+
+ If the partial
+ parameter is set to true, this entity takes part in a cross-store setting /)
+ where only the specifically annotated parts of the entity not handled by JPA will be mapped to the graph store.
- Entity fields can be annotated with @GraphProperty, @RelatedTo, @RelatedToVia, @Indexed and @GraphId
+ Entity fields can be annotated with @GraphProperty, @RelatedTo, @RelatedToVia, @Indexed, @GraphId and
+ @GraphTraversal.
- 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.
@@ -66,9 +69,10 @@ public class Actor {
@RelationshipEntity: Rich relationships
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 relateTo or
- getRelationshipTo methods.
+ getRelationshipTo methods .
+
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 {
@@ -98,6 +102,12 @@ public class Role {
public class Actor {
@RelatedToVia(type = "ACTS_IN", elementClass = Role.class)
private Iterable roles;
+
+ public Role playedIn(Movie movie, String title) {
+ Role role=relateTo(movie,Role.class,"ACTS_IN");
+ role.setTitle(title);
+ return role;
+ }
}
]]>
@@ -113,18 +123,22 @@ public class Actor {
@Indexed: Making entities searchable by field value
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 Finder for a particular node or relationship entity, created via a
+ FinderFactory.
- 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 getIndex method.
+ Index names default to the domain class
+ name, but can also be named (indexName attribute)individually to reflect domain concepts.
+ be named, for instance to keep separate domain concepts in separate indexes.
+
+
+ Numerical values are indexed as such by default, allowing for range queries.
+ Fulltext indexing is also possible by setting the fulltext attribute to true. For details see
+ the indexing section .
@@ -136,6 +150,25 @@ public class Actor {
is created by a TraversalDescriptionBuilder whose class is referred to by the traversalBuilder
attribute of the annotation. The class of the expected NodeEntities is provided with the
elementClass attribute.
+ 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());
+
+ }
+ }
+}
+
+]]>
@@ -143,8 +176,9 @@ public class Actor {
@GraphProperty: Cross-store persisted fields
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.
diff --git a/src/docbkx/reference/programming-model/aspectj.xml b/src/docbkx/reference/programming-model/aspectj.xml
index 461f2f2f8..318318307 100644
--- a/src/docbkx/reference/programming-model/aspectj.xml
+++ b/src/docbkx/reference/programming-model/aspectj.xml
@@ -2,24 +2,28 @@
Overview of the AspectJ support
- 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.
+ 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 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.
- 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 ()
+ to the entities for accessing the backing
state via getPersistentState() and creating relationships with relateTo
- and retrieving relationship entities viagetRelationshipTo. It also introduces finder methods like
+ and retrieving relationship entities via getRelationshipTo. It also introduces finder methods like
find(Class<? extends NodeEntity>, TraversalDescription)
and equals and hashCode delegation.
- Spring Data Graph internally uses an abstraction called EntityState that the field access and instantiation
+ Spring Data Graph internally uses an abstraction called EntityState 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 EntityState then uses a number of FieldAccessorFactories
+ to create a FieldAccessor instance per field that does the specific handling needed for the concrete field type.
\ No newline at end of file
diff --git a/src/docbkx/reference/programming-model/beanvalidation.xml b/src/docbkx/reference/programming-model/beanvalidation.xml
index da2bdfaea..c02a63e44 100644
--- a/src/docbkx/reference/programming-model/beanvalidation.xml
+++ b/src/docbkx/reference/programming-model/beanvalidation.xml
@@ -3,7 +3,7 @@
Bean Validation - JSR-303
- 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
diff --git a/src/docbkx/reference/programming-model/finders.xml b/src/docbkx/reference/programming-model/finders.xml
index f547f4760..3d17be1de 100644
--- a/src/docbkx/reference/programming-model/finders.xml
+++ b/src/docbkx/reference/programming-model/finders.xml
@@ -2,49 +2,81 @@
Finding nodes with finders
- Spring Data Graph also comes with a type bound Repository-like
- Finder implementation that provides methods for locating nodes
- and relationships:
-
-
- using direct access findById(id),
-
-
- iterating over all nodes of a node entity type (findAll),
-
-
- counting the instances of a node entity type (count),
-
-
- iterating over all indexed instances with a certain property value (findAllByPropertyValue),
-
-
-
- getting a single instance with a certain property value (findByPropertyValue),
-
-
- iterating over all indexed instances within a certain numerical range (inclusive)
- (findAllByRange),
-
-
-
- iterating over a traversal result (findAllByTraversal).
-
-
- 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.
+ 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 NodeTypeStrategy for type
+ based queries.
+
+
+ loading an instance via the Neo4j node id
+ T findById(id)
+
+
+ iterating over all nodes of a node entity type
+ Iterable<T>findAll()
+
+
+ counting the instances of a node entity type
+ long count()
+
+
+ iterating over all indexed instances with a certain property value
+ Iterable<T> findAllByPropertyValue(indexName, keyName, value)
+
+
+ getting a single instance with a certain property value
+ T findByPropertyValue(indexName, keyName, value)
+
+
+ iterating over all indexed instances within a certain numerical range (inclusive)
+ Iterable<T> findAllByRange(indexName, keyName, from, to)
+
+
+ iterating over all indexed instances matching the given fulltext (or QueryContext query)
+ Iterable<T> findAllByQuery(indexName, keyName, queryOrQueryContext)
+
+
+ iterating over a traversal result
+ Iterable<T> findAllByTraversal(startNode, traversalDescription)
+
+
+ The Finder instances are created via a FinderFactory to be bound to a concrete node or relationship entity class.
+ The FinderFactory is configured in the Spring context and can be injected.
finder = finderFactory.createNodeEntityFinder(Person.class);
+
Person dave=finder.findById(123);
-int people = finder.count();
-Person mark = finder.findByPropertyValue("name", "mark");
-Iterable devs = finder.findAllByProperyValue("occupation","developer");
+
+long numberOfPeople = finder.count();
+
+Person mark = finder.findByPropertyValue(null,"name", "mark");
+
+Iterable devs = finder.findAllByProperyValue(null, "occupation","developer");
+
+Iterable middleAgedPeople = finder.findAllByRange(null, "age",20,40);
+
+Iterable aTeam = finder.findAllByQuery(null, "name","A*");
+
Iterable davesFriends = finder.findAllByTraversal(dave,
Traversal.description().pruneAfterDepth(1)
.relationships(KNOWS).filter(returnAllButStartNode()));
-
]]>
+
+ NodeTypeStrategies: Storing Type Information in the Graph
+
+ Internally the mapping from java types to the graph is handled by a NodeTypeStrategy instance
+ that is configured with the GraphDatabaseContext. 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 )
+
+
+ The default strategy (IndexingNodeTypeStrategy)
+ 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.
+
+
\ No newline at end of file
diff --git a/src/docbkx/reference/programming-model/indexing.xml b/src/docbkx/reference/programming-model/indexing.xml
index 6ab070a16..896a1a329 100644
--- a/src/docbkx/reference/programming-model/indexing.xml
+++ b/src/docbkx/reference/programming-model/indexing.xml
@@ -5,7 +5,7 @@
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.
diff --git a/src/docbkx/reference/programming-model/introducedmethods.xml b/src/docbkx/reference/programming-model/introducedmethods.xml
index 683011073..8b9aa2ee3 100644
--- a/src/docbkx/reference/programming-model/introducedmethods.xml
+++ b/src/docbkx/reference/programming-model/introducedmethods.xml
@@ -4,8 +4,7 @@
Methods added to entity classes
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.
persisting the node-entity initially and after changes outside of a transaction,
@@ -64,7 +63,7 @@
- remove the node entity, its relationship and index entries
+ remove the node entity, its relationships and index entries
entity.remove()
diff --git a/src/docbkx/reference/programming-model/neo4jtemplate.xml b/src/docbkx/reference/programming-model/neo4jtemplate.xml
deleted file mode 100644
index 5684ecd20..000000000
--- a/src/docbkx/reference/programming-model/neo4jtemplate.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
- Neo4jTemplate
-
- The Neo4jTemplate 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 (index, autoindex) will index them.
-
-
- For the querying operations Neo4jTemplate unifies the result with the Path abstraction that
- comes from Neo4j. Much like a resultset a path contains nodes() and relationships()
- starting at a startNode() and ending with aendNode(), the
- lastRelationship() is also available separately. The Path abstraction also wraps
- results that contain just nodes or relationships. Using implementations of PathMapper<T>
- and PathMapper.WithoutResult (comparable with RowMapper and
- RowCallbackHandler) the paths can be converted to Java objects.
-
-
- 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.
-
-
- Traversal methods are the bread and butter of graph operations. As such, they are fully supported in the
- Neo4jTemplate. The traverseNext method traverses to the direct neighbours of the
- start node filtering the relationships according to its parameters.
-
-
- The traverse method covers the full fledged traversal operation that takes a powerful
- TraversalDescription (most probably built from the Traversal.description()
- DSL) and runs it from the start node. Each path that is returned via the traversal is passed to the
- PathMapper to be processed accordingly.
-
-
- The Neo4jTemplate 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 useExplicitTransactions parameter set to true, it won't
- create any transactions so you have to provide them using @Transactional or the TransactionTemplate.
-
-
-
-
diff --git a/src/docbkx/reference/programming-model/nodetypestrategy.xml b/src/docbkx/reference/programming-model/nodetypestrategy.xml
index 796f5d763..ba50c7db6 100644
--- a/src/docbkx/reference/programming-model/nodetypestrategy.xml
+++ b/src/docbkx/reference/programming-model/nodetypestrategy.xml
@@ -1,7 +1,7 @@
-
- Reified types for entities
+
+ Storing Type Information in the Graph
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
diff --git a/src/docbkx/reference/programming-model/programming-model.xml b/src/docbkx/reference/programming-model/programming-model.xml
index 4cea04b08..a0c764e90 100644
--- a/src/docbkx/reference/programming-model/programming-model.xml
+++ b/src/docbkx/reference/programming-model/programming-model.xml
@@ -17,6 +17,5 @@
-
diff --git a/src/docbkx/reference/spring-data.xml b/src/docbkx/reference/spring-data.xml
index 2d6c64597..405838a78 100644
--- a/src/docbkx/reference/spring-data.xml
+++ b/src/docbkx/reference/spring-data.xml
@@ -3,6 +3,9 @@
Spring Data
- ...
+ Spring Data 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.
diff --git a/src/docbkx/reference/template.xml b/src/docbkx/reference/template.xml
index 0954a88f3..f67ddee9d 100644
--- a/src/docbkx/reference/template.xml
+++ b/src/docbkx/reference/template.xml
@@ -1,38 +1,91 @@
- Neo4jTemplate
-
- ...
-
-
- Transaction handling/management
+ Neo4jTemplate
- ...
+ The Neo4jTemplate offers the convenient API of Spring templates for the Neo4j graph database.
+ It is initialized with a GraphDatabaseService which is thread-safe to use.
-
Basic operations
- ...
+ For direct retrieval of nodes and relationships the getReferenceNode, getNode and
+ getRelationship can be used.
+
+
+ There are methods (createNode and createRelationship) for creating nodes and
+ relationships that automatically set provided properties and optionally index certain fields.
+
+
+
Indexing
- ...
+ Adding nodes and relationships to an index is achieved using the index and autoindex)
+ methods.
+
+
+ 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. All query methods provide
+ Path results to a PathMapper.
Traversal
- ...
+ Traversal methods are at the core of graph operations. As such, they are fully supported in the
+ Neo4jTemplate. The traverseNext method traverses to the direct neighbours of the
+ start node filtering the relationships according to its parameters.
+
+
+ The traverse method covers the full traversal operation that takes a powerful
+ TraversalDescription (most probably built from the Traversal.description()
+ DSL) and runs it from the start node. Each path that is returned via the traversal is passed to the
+ PathMapper to be processed accordingly.
+
+
+
+
+ Path abstraction and PathMapper
+
+ For the querying operations Neo4jTemplate unifies the result with the Path abstraction that
+ comes from Neo4j. Much like a resultset a path contains nodes() and relationships()
+ starting at a startNode() and ending with aendNode(), the
+ lastRelationship() is also available separately. The Path abstraction also wraps
+ results that contain just nodes or relationships.
+
+
+ Using implementations of PathMapper<T>
+ and PathMapper.WithoutResult (comparable with RowMapper and
+ RowCallbackHandler) the paths can be converted to arbitrary Java objects.
+
+
+ With EntityPath and EntityMapper there is also support for using annotation based
+ NodeEntities within the Path and PathMapper constructs.
- PathMapper
+ Transaction handling/management
- ... path as general return type?
+ The Neo4jTemplate 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 useExplicitTransactions parameter set to true, it won't
+ create any transactions so you have to provide them using @Transactional or the TransactionTemplate.