Merge branch 'master' into snapshot

This commit is contained in:
Michael Hunger
2011-04-11 22:58:38 +02:00
17 changed files with 275 additions and 243 deletions

View File

@@ -102,7 +102,7 @@
<xi:include href="reference/samples.xml"/>
<xi:include href="reference/performance.xml" />
<xi:include href="reference/template.xml" />
<xi:include href="reference/aspectj-intro.xml" />
<xi:include href="reference/aspectj-details.xml" />
<xi:include href="reference/neo4j-server.xml" />
</part>
</book>

View File

@@ -1,7 +1,7 @@
<?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:aspectj-intro">
<title>AspectJ introduction</title>
<chapter id="reference:aspectj-details">
<title>AspectJ details</title>
<para>
The object graph mapper of Spring Data Graph relies heavily on AspectJ. AspectJ is the Java implementation of
the <ulink url="https://secure.wikimedia.org/wikipedia/en/wiki/Aspect-oriented_programming">Aspect

View File

@@ -1,7 +1,7 @@
<?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="cross-store">
<title>Cross-store persistence with a graph database</title>
<title>Cross-store persistence</title>
<para>The Spring Data Graph project support cross-store persistence which allows parts of the data mode to be stored in a traditional
JPA datastore (RDBMS) and other parts of the data model (even partial entites, that is some properties or relationships) in a graph
store.

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>Overview of the AspectJ support</title>
<title>AspectJ support</title>
<para>
Behind the scenes, Spring Data Graph leverages <ulink url="http://www.eclipse.org/aspectj/">AspectJ</ulink>
aspects to modify the behavior of simple annotated POJO entities

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>Session handling - attached and detached entities</title>
<title>Detached entities</title>
<para>
By default newly created node entities are in a detached state. When <code>persist()</code> is called on the
entity it is attached to the graph store and its properties and relationships are persisted as well. Changing

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>Bean Validation - JSR-303</title>
<title>Bean validation (JSR-303)</title>
<para>
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).

View File

@@ -1,135 +1,142 @@
<?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:indexing">
<section id="reference:programming-model:indexing">
<title>Indexing</title>
<para>
The Neo4j graph database can use different index providers for exact lookups and fulltext searches. Lucene is
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.
The Neo4j graph database can use different so-called index providers for exact lookups and fulltext
searches. Lucene is the default index provider implementation. Each named index is configured to be
fulltext or exact.
</para>
<section>
<title>Exact and Numeric Index</title>
<para>
Using the standard Neo4j API, Nodes and Relationships and their indexed field-value combinations
have to be added manually to the appropriate index. When using Spring Data Graph, this task is simplified by
eased by applying an <code>@Indexed</code> annotation on entity fields. This will result in updates to the
index on every change.
</para><para>
Numerical fields are indexed numerically so that they are available for range queries.
All other fields are indexed with their string representation.
</para><para>
The @Indexed annotation can also set the
index-name to be used the default index name is the simple class name of the entity. So the same field names
from different classes don't end up in the same index by default. That would return different domain objects
for a single index query.
</para>
<para>
Query access to the index happens with the Node- and Relationship-Repostories that are created via an instance of
<code>org.springframework.data.graph.neo4j.repository.DirectGraphRepositoryFactory</code>. The methods
<code>findByPropertyValue</code> and <code>findAllByPropertyValue</code> work on the exact indexes and
return the first or all matches. To do range queries, use <code>findAllByRange</code> (please note that
currently both values are inclusive).
</para>
<programlisting language="java"><![CDATA[
<title>Exact and numeric index</title>
<para>
When using the standard Neo4j API, nodes and relationships have to be manually indexed with
key-value pairs, typically being the property name and value. When using Spring Data Graph,
this task is simplified to just adding an <code>@Indexed</code> annotation on entity fields
by which the entity should be searchable. This will result in automatic updates of the index
every time an indexed field changes.
</para>
<para>
Numerical fields are indexed numerically so that they are available for range queries. All
other fields are indexed with their string representation.
</para>
<para>
The @Indexed annotation also provides the option of using a custom index. The default index
name is the simple class name of the entity, so that each class typically gets its own index.
It is recommended to not have two entity classes with the same class name, regardless of
package.
</para>
<para>
The indexes can be queried by using a repository (see <xref linkend="reference:repositories" />).
Typically, the repository is an instance of
<code>org.springframework.data.graph.neo4j.repository.DirectGraphRepositoryFactory</code>.
The methods <code>findByPropertyValue()</code> and <code>findAllByPropertyValue()</code> work on
the exact indexes and return the first or all matches. To do range queries, use
<code>findAllByRange()</code> (please note that currently both values are inclusive).
</para>
<example>
<title>Indexing entities</title>
<programlisting language="java"><![CDATA[
@NodeEntity
class Person {
@Indexed(indexName = "people")
String name;
// automatically indexed numerically
@Indexed
int age;
@Indexed(indexName = "people") String name;
@Indexed int age;
}
GraphRepository<Person> graphRepository = graphRepositoryFactory.createGraphRepository(Person.class);
// exact graphRepository
Person mark = graphRepository.findByProperyValue("people","name","mark");
// Exact match, in named index
Person mark = graphRepository.findByPropertyValue("people", "name", "mark");
// numeric range queries
for (Person middleAgedDeveloper : graphRepository.findAllByRange( "age", 20, 40)) {
// Numeric range query, index name inferred automatically
for (Person middleAgedDeveloper : graphRepository.findAllByRange("age", 20, 40)) {
Developer developer=middleAgedDeveloper.projectTo(Developer.class);
}
]]></programlisting>
</section>
</example>
</section>
<section>
<title>Fulltext Indexes</title>
<title>Fulltext indexes</title>
<para>
Spring Data Graph also supports full-text indexes. By default indexed fields are stored in an exact-lookup
index. To have them analyzed and prepared for fulltext search, the <code>@Indexed</code> annotation has
the boolean <code>fulltext</code> attribute. Please note that fulltext-indexes require a separate index name
as the fulltext-configuration is stored in the index itself.
Spring Data Graph also supports fulltext indexes. By default, indexed fields are stored in
an exact lookup index. To have them analyzed and prepared for fulltext search, the
<code>@Indexed</code> annotation has the boolean <code>fulltext</code> attribute.
Please note that fulltext indexes require a separate index name as the fulltext configuration
is stored in the index itself.
</para>
<para>
Access to the fulltext index is provided by the <code>findAllByQuery</code> method of the repositories. Wildcard
like * are allowed. Otherwise the fulltext querying rules of the underlying index provider apply. (In most
cases this will be lucene.
Access to the fulltext index is provided by the <code>findAllByQuery()</code> repository method.
Wildcards like <code>*</code> are allowed. Generally though, the fulltext querying rules of the
underlying index provider apply. See the
<ulink url="http://lucene.apache.org/java/3_0_1/">Lucene documentation</ulink> for more
information on this.
</para>
<para>
<programlisting language="java"><![CDATA[
<example>
<title>Fulltext indexing</title>
<programlisting language="java"><![CDATA[
@NodeEntity
class Person {
@Indexed(indexName = "person-name", fulltext=true)
String name;
@Indexed(indexName = "person-name", fulltext=true) String name;
}
GraphRepository<Person> graphRepository = graphRepositoryFactory.createGraphRepository(Person.class);
// exact graphRepository
Person mark = graphRepository.findAllByQuery("people-search","name","ma*");
Person mark = graphRepository.findAllByQuery("people-search", "name", "ma*");
]]></programlisting>
</example>
</para>
<note>
<para>
Please note that indexes are currently created on demand, so whenever an index that doesn't exist
is requested from a query or get operation it is created. This is subject to change but has currently
the implication that those indexes won't be configured as fulltext which causes subsequent fulltext-
updates to those indexes to fail.
</para>
Please note that indexes are currently created on demand, so whenever an index that doesn't exist
is requested from a query or get operation it is created. This is subject to change but has
currently the implication that those indexes won't be configured as fulltext which causes
subsequent fulltext updates to those indexes to fail.
</note>
</section>
<section>
<title>Raw Index Access</title>
<para>The raw index for a domain class is also available from <code>GraphDatabaseContext</code> via the
<code>getIndex</code> method. The second parameter is optional and takes the index-name if it doesn't default
to the simple domain class name. It returns the Index implementation that is provided by Neo4j.
<title>Manual index access</title>
<para>
The index for a domain class is also available from <code>GraphDatabaseContext</code> via
the <code>getIndex()</code> method. The second parameter is optional and takes the index name
if it should not be inferred from the class name. It returns the index implementation that is
provided by Neo4j.
</para>
<example>
<title>Manual index usage</title>
<programlisting language="java"><![CDATA[
@Autowired GraphDatabaseContext gdc;
// exact index
Index<Node> personIndex=gdc.getIndex(Person.class,null);
personIndex.add(node,"name","Mark");
// Default index
Index<Node> personIndex = gdc.getIndex(Person.class);
personIndex.query(new QueryContext(NumericRangeQuery.newÍntRange("age", 20, 40, true, true))
.sort(new Sort(new SortField("age", SortField.INT, false))));
Index<Node> namedPersonIndex=gdc.getIndex(Person.class,"people");
namedPersonIndex.get("name","Mark");
// Named index
Index<Node> namedPersonIndex = gdc.getIndex(Person.class, "people");
namedPersonIndex.get("name", "Mark");
// complex range & sort query
namedPersonIndex.query( new QueryContext( NumericRangeQuery.newÍntRange( "age", 20, 40, true, true ) )
.sort( new Sort( new SortField( "age", SortField.INT, false ) ) ) );
// fulltext index
Index<Node> personFulltextIndex=gdc.getIndex(Person.class,"person-name",true);
namedPersonIndex.query("name","Ma*");
namedPersonIndex.query("{name:Ma*}");
]]></programlisting>
</para>
// Fulltext index
Index<Node> personFulltextIndex = gdc.getIndex(Person.class, "person-name", true);
personFulltextIndex.query("name", "*cha*");
personFulltextIndex.query("{name:*cha*}");
]]></programlisting>
</example>
</section>
<section>
<title>Indexing in Neo4jTemplate</title>
<para>
Neo4jTemplate also offers index support, providing auto-indexing for fields at creation time of nodes and
relationships. There is an <code>autoIndex</code> method that can also add indexes for a set of fields in one
go.
Neo4jTemplate also offers index support, providing auto-indexing for fields at creation time.
There is an <code>autoIndex</code> method that can also add indexes for a set of fields in one go.
</para>
<para>
For querying the index, the template offers query-methods that take either the exact match parameters or a query
object / query expression and push the results wrapped uniformly as Paths to the supplied
<code>PathMapper</code> to be converted or collected.
For querying the index, the template offers query methods that take either the exact match
parameters or a query object/expression, and push the results wrapped uniformly as Paths to
the supplied <code>PathMapper</code> to be converted or collected.
</para>
</section>
</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 id="reference:programming-model:introduced-methods">
<title>Methods added to entity classes</title>
<title>Introduced methods</title>
<para>
The node and relationship aspects introduce (via AspectJ ITD - inter type declaration) several
methods to the entities.

View File

@@ -1,9 +1,10 @@
<?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>Annotations define POJO node entities</title>
<para>Entities are declared using the <code>@NodeEntity</code> annotation.
Relationship entities use the <code>@RelationshipEntity</code> annotation.
<title>Defining node entities</title>
<para>
Node entities are declared using the <code>@NodeEntity</code> annotation. Relationship entities use
the <code>@RelationshipEntity</code> annotation.
</para>
<section>
<title>@NodeEntity: The basic building block</title>
@@ -61,7 +62,7 @@ String title;
<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"/>.
the indexing section <xref linkend="reference:programming-model:indexing"/>.
</para>
</section>

View File

@@ -1,7 +1,7 @@
<?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="programming-model" xmlns:xi="http://www.w3.org/2001/XInclude">
<title>Programming model for Spring Data Graph</title>
<title>Programming model</title>
<para>
This chapter covers the fundamentals of the programming model behind Spring Data Graph. It discusses the
AspectJ features used and the annotations provided by Spring Data Graph and how to use them.

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>Dynamic typing - Projection to unrelated, fitting types</title>
<title>Projecting entities</title>
<para>
As the underlying data model of a graph database doesn't imply and enforce strict type constraints like a
relational model does, it offers much more flexibility on how to model your domain classes and which of

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:relationships">
<title>Relationships relate node entities</title>
<title>Relating 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
@@ -9,13 +9,6 @@
Spring Data Graph has special support to represent Neo4j relationships as entities too, but it is often
not needed.
</para>
<section>
<title>@NodeEntity</title>
<para>
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>

View File

@@ -1,142 +1,154 @@
<?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>GraphRepositories for basic CRUD and find-operations</title>
<section id="reference:repositories">
<title>CRUD with repositories</title>
<para>
The repositories provided by Spring Data Graph build on the composable repository infrastructure contained
The repositories provided by Spring Data Graph build on the composable repository infrastructure
in <ulink url="http://static.springsource.org/spring-data/data-jpa/docs/1.0.0.M2/reference/html/#repositories.custom-implementations">Spring Data Commons</ulink>.
Those repositories allow the interface based composition of the final repository consisting of provided default
They allow for interface based composition of repositories consisting of provided default
implementations for certain interfaces and additional custom implementations for other methods.
</para>
<note>
<para>
Spring Data Graph provides only the infrastructure and some default repository implementations so far. In future
releases support for finders derived from method names, named queries and annotated query methods will be added.
Spring Data Graph provides only the infrastructure and some default repository implementations
so far. Future releases will support finders derived from method names, named queries, and
annotated query methods.
(e.g.
findByName(name),
@Query(name = "find-by-name-query") findByName(name),
@Query(query = "{name:%s}") findByName(name))
<code>findByName(name)</code>,
<code>@Query(name="find-by-name-query") findByName(name)</code>, and
<code>@Query(query="{name:%s}") findByName(name)</code>)
</para>
</note>
<para>Spring Data Graph comes with typed repository implementations that provide methods for
locating node and relationship entities. There are 3 types of basic repository interfaces and implementations.
One CRUD-Repository (<code>CRUDGraphRepository&lt;T&gt;</code>) that provides basic operations, a <code>IndexQueryExecutor</code>
that delegates to Neo4j's internal indexing subsystem for executing queries. And last but not least
a <code>TraversalQueryExecutor</code> that handles Neo4J Traversals.
<para>
Spring Data Graph comes with typed repository implementations that provide methods for
locating node and relationship entities. There are 3 types of basic repository interfaces
and implementations. <code>CRUDRepository</code> provides basic operations,
<code>IndexRepository</code> and <code>NamedIndexRepository</code> delegate to Neo4j's internal
indexing subsystem for queries, and <code>TraversalRepository</code> handles Neo4j traversals.
</para>
<para>
<code>CRUDGraphRepository</code> delegates to the configured <code>TypeRepresentationStrategy</code>
(<xref linkend="reference:programming-model:typerepresentationstrategy"/>)
<code>CRUDRepository</code> delegates to the configured <code>TypeRepresentationStrategy</code>
(see <xref linkend="reference:programming-model:typerepresentationstrategy"/>)
for type based queries.
<variablelist>
<varlistentry>
<term>loading an instance via the Neo4j node id</term>
<listitem> <para> <code>T findOne(id)</code></para> </listitem>
<term>Load an instance via a Neo4j node id</term>
<listitem><para><code>T findOne(id)</code></para></listitem>
</varlistentry>
<varlistentry>
<term>checks for existence via the Neo4j node id</term>
<listitem> <para> <code>boolean exists(id)</code></para> </listitem>
<term>Check for existence of a Neo4j node id</term>
<listitem><para><code>boolean exists(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> (supported in future versions: <code>Iterable&lt;T&gt; findAll(Sort)</code> and <code>Page&lt;T&gt; findAll(Pageable)</code>)</para> </listitem>
<term>Iterate over all nodes of a node entity type</term>
<listitem><para><code>Iterable&lt;T&gt; findAll()</code>
(supported in future versions:
<code>Iterable&lt;T&gt; findAll(Sort)</code> and
<code>Page&lt;T&gt; findAll(Pageable)</code>)</para></listitem>
</varlistentry>
<varlistentry>
<term>counting the instances of a node entity type</term>
<listitem> <para> <code>Long count()</code> </para> </listitem>
<term>Count the instances of a node entity type</term>
<listitem><para><code>Long count()</code></para></listitem>
</varlistentry>
<varlistentry>
<term>saves the graph entities</term>
<listitem> <para> <code>T save(T)</code> and <code>Iterable&lt;T&gt; save(Iterable&lt;T&gt;)</code> </para> </listitem>
<term>Save a graph entity</term>
<listitem><para><code>T save(T)</code> and <code>Iterable&lt;T&gt; save(Iterable&lt;T&gt;)</code></para></listitem>
</varlistentry>
<varlistentry>
<term>deletes the graph entities</term>
<listitem> <para> <code>void delete(T)</code>, <code>void; delete(Iterable&lt;T&gt;)</code> and <code>deleteAll()</code></para> </listitem>
<term>Delete a graph entity</term>
<listitem><para><code>void delete(T)</code>, <code>void; delete(Iterable&lt;T&gt;)</code>,
and <code>deleteAll()</code></para></listitem>
</varlistentry>
</variablelist>
</para>
<para>
<code>IndexQueryExecutor</code> works with the indexing subsystem and provides methods to find entities by indexed properties, ranged queries of combination thereof.
</para>
<para>
<code>IndexRepository</code> works with the indexing subsystem and provides methods to find
entities by indexed properties, ranged queries, and combinations thereof. The index key is
the name of the indexed entity field, unless overridden in the <code>@Indexed</code> annotation.
<variablelist>
<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>
<term>Iterate over all indexed entity instances with a certain field value</term>
<listitem><para><code>Iterable&lt;T> findAllByPropertyValue(key, 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>
<term>Get a single entity instance with a certain field value</term>
<listitem><para><code>T findByPropertyValue(key, 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>
<term>Iterate over all indexed entity instances with field values in a certain numerical range (inclusive)</term>
<listitem><para><code>Iterable&lt;T> findAllByRange(key, 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>
<term>Iterate over all indexed entity instances with field values matching the given fulltext string or QueryContext query</term>
<listitem><para><code>Iterable&lt;T> findAllByQuery(key, queryOrQueryContext)</code></para></listitem>
</varlistentry>
</variablelist>
</para>
</variablelist>
There is also a <code>NamedIndexRepository</code> with the same methods, but with an additional index
name parameter, making it possible to query any index.
</para>
<para>
<code>TraversalQueryExecutor</code> works with the traversal framework.
<code>TraversalRepository</code> delegates to the Neo4j traversal framework.
<variablelist>
<varlistentry>
<term>iterating over a traversal result</term>
<listitem> <para> <code>Iterable&lt;T&gt; findAllByTraversal(startNode, traversalDescription)</code> </para> </listitem>
<term>Iterate over a traversal result</term>
<listitem><para><code>Iterable&lt;T> findAllByTraversal(startEntity, traversalDescription)</code></para></listitem>
</varlistentry>
</variablelist>
</para>
<para>
The <code>Repository</code> instances are either created manually via a DirectGraphRepositoryFactory to be bound
o a concrete node or relationship entity class.
The <code>Repository</code> instances are either created manually via a
<code>DirectGraphRepositoryFactory</code>, bound to a concrete node or relationship entity class.
The <code>DirectGraphRepositoryFactory</code> is configured in the Spring context and can be injected.
<example>
<title>Using GraphRepositories</title>
</para>
<example>
<title>Using GraphRepositories</title>
<programlisting language="java"><![CDATA[
GraphRepository<Person> graphRepository = graphRepositoryFactory.createGraphRepository(Person.class);
Person michael = graphRepository.save(new Person("Michael",36));
Person michael = graphRepository.save(new Person("Michael", 36));
Person dave=graphRepository.findOne(123);
Person dave = graphRepository.findOne(123);
Long numberOfPeople = graphRepository.count();
Person mark = graphRepository.findByPropertyValue("name", "mark");
Iterable<Person> devs = graphRepository.findAllByProperyValue("occupation","developer");
Iterable<Person> devs = graphRepository.findAllByProperyValue("occupation", "developer");
Iterable<Person> middleAgedPeople = graphRepository.findAllByRange("age",20,40);
Iterable<Person> middleAgedPeople = graphRepository.findAllByRange("age", 20, 40);
Iterable<Person> aTeam = graphRepository.findAllByQuery("name","A*");
Iterable<Person> aTeam = graphRepository.findAllByQuery("name", "A*");
Iterable<Person> davesFriends = graphRepository.findAllByTraversal(dave,
Traversal.description().pruneAfterDepth(1)
.relationships(KNOWS).filter(returnAllButStartNode()));
]]></programlisting>
</example>
</para>
</example>
<section>
<title>Composing Repositories</title>
<para>
The recommended way of providing repositories is to define a repository-interface per domain class and have the
mechanisms provided by the repository infrastructure automatically detect them and additional implementation
classes and create an injectable repository implementation to be used in services or other spring beans.
<title>Composing repositories</title>
<para>
The recommended way of providing repositories is to define a repository interface per domain
class. The mechanisms provided by the repository infrastructure will automatically detect
them, along with additional implementation classes, and create an injectable repository
implementation to be used in services or other spring beans.
</para>
<example>
<title>Composing Repositories</title>
<title>Composing repositories</title>
<programlisting language="java"><![CDATA[
public interface PersonRepository extends GraphRepository<Person>, PersonRepositoryExtension {
}
public interface PersonRepository extends GraphRepository<Person>, PersonRepositoryExtension {}
// alternatively select some of the required repositories individually
public interface PersonRepository extends CRUDGraphRepository<Node,Person>, IndexQueryExecutor<Node,Person>,
TraversalQueryExecutor<Node,Person>, PersonRepositoryExtension {
}
TraversalQueryExecutor<Node,Person>, PersonRepositoryExtension {}
// provide a custom extension if needed
public interface PersonRepositoryExtension {
Iterable<Person> findFriends(Person person);
}
public class PersonRepositoryImpl implements PersonRepositoryExtension {
public class PersonRepositoryImpl implements PersonRepositoryExtension {
// optionally inject default repository, or use DirectGraphRepositoryFactory
@Autowired PersonRepository baseRepository;
public Iterable<Person> findFriends(Person person) {
@@ -151,18 +163,17 @@ public class PersonRepositoryImpl implements PersonRepositoryExtension {
@Autowired
PersonRepository personRepository;
Person michael = personRepository.save(new Person("Michael",36));
Person michael = personRepository.save(new Person("Michael",36));
Person dave=personRepository.findOne(123);
Person dave=personRepository.findOne(123);
Iterable<Person> devs = personRepository.findAllByProperyValue("occupation","developer");
Iterable<Person> devs = personRepository.findAllByProperyValue("occupation","developer");
Iterable<Person> aTeam = graphRepository.findAllByQuery( "name","A*");
Iterable<Person> aTeam = graphRepository.findAllByQuery( "name","A*");
Iterable<Person> friends = personRepository.findFriends(dave);
]]></programlisting>
Iterable<Person> friends = personRepository.findFriends(dave);
]]></programlisting>
</example>
</para>
</section>
</section>

View File

@@ -1,93 +1,113 @@
<?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>Transactions in Spring Data Graph</title>
<title>Transactions</title>
<para>
Neo4j is a transactional datastore which only allows modifications within transaction boundaries and fullfills
the ACID properties. Reading from the store is also possible outside of transactions.
Neo4j is a transactional database, only allowing modifications to be performed within transaction
boundaries. Reading data does however not require transactions.
</para>
<para>Spring Data Graph integrates with transaction managers configured using Spring. The simplest scenario of
just running the graph database uses a SpringTransactionManager provided by the Neo4j kernel to be used
with Spring's JtaTransactionManager.
Note: The explicit XML configuration given below is encoded in the <code>Neo4jConfiguration</code>
configuration bean that uses Spring's @Configuration functioanlity. This simplifies the configuration.
An example is shown further below.
<para>
Spring Data Graph integrates with transaction managers configured using Spring. The simplest
scenario of just running the graph database uses a SpringTransactionManager provided by the
Neo4j kernel to be used with Spring's JtaTransactionManager. That is, configuring Spring to
use Neo4j's transaction manager.
</para>
<programlisting language="xml"><![CDATA[
<note>
<para>
The explicit XML configuration given below is encoded in the <code>Neo4jConfiguration</code>
configuration bean that uses Spring's <code>@Configuration</code> feature. This greatly
simplifies the configuration of Spring Data Graph.
<!--An example is shown further below.-->
</para>
</note>
<example>
<title>Simple transaction manager configuration</title>
<programlisting language="xml"><![CDATA[
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="org.neo4j.kernel.impl.transaction.SpringTransactionManager">
<constructor-arg ref="graphDatabaseService"/>
</bean>
</property>
<property name="userTransaction">
<bean class="org.neo4j.kernel.impl.transaction.UserTransactionImpl">
<constructor-arg ref="graphDatabaseService"/>
</bean>
</property>
<property name="transactionManager">
<bean class="org.neo4j.kernel.impl.transaction.SpringTransactionManager">
<constructor-arg ref="graphDatabaseService"/>
</bean>
</property>
<property name="userTransaction">
<bean class="org.neo4j.kernel.impl.transaction.UserTransactionImpl">
<constructor-arg ref="graphDatabaseService"/>
</bean>
</property>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
]]></programlisting>
</example>
<para>
For scenarios running multiple transactional resources there are two options.
First of all you can have Neo4j participate in the externally set up transaction manager using the new
SpringProvider by enabling the configuration parameter for your graph database. Either via the spring config
or the configuration file (neo4j.properties).
For scenarios with multiple transactional resources there are two options. The first option
is to have Neo4j participate in the externally configured transaction manager by using the
Spring support in Neo4j by enabling the configuration parameter for your graph database.
Neo4j will then use Spring's transaction manager instead of its own.
</para>
<programlisting language="xml"><![CDATA[
<example>
<title>Neo4j Spring integration</title>
<programlisting language="xml"><![CDATA[
<context:annotation-config />
<context:spring-configured/>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean id="jotm" class="org.springframework.data.graph.neo4j.transaction.JotmFactoryBean"/>
</property>
<property name="transactionManager">
<bean id="jotm" class="org.springframework.data.graph.neo4j.transaction.JotmFactoryBean"/>
</property>
</bean>
<bean class="org.neo4j.kernel.EmbeddedGraphDatabase" destroy-method="shutdown">
<constructor-arg value="target/test-db"/>
<constructor-arg>
<map>
<entry key="tx_manager_impl" value="spring-jta"/>
</map>
</constructor-arg>
<constructor-arg value="target/test-db"/>
<constructor-arg>
<map>
<entry key="tx_manager_impl" value="spring-jta"/>
</map>
</constructor-arg>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
]]></programlisting>
]]></programlisting>
</example>
<para>
You can configure a stock XA transaction manager to be used with Neo4j and the other resources (e.g. Atomikos,
JOTM, App-Server-TM). For a bit less secure but fast 1 phase commit best effort, use the implementation coming
with Spring Data Graph (<code>ChainedTransactionManager</code>). It takes a list of transaction-managers as
constructor params and will handle them in order for transaction start and commit (or rollback) in the reverse
order.
One can also configure a stock XA transaction manager (e.g. Atomikos, JOTM, App-Server-TM) to be
used with Neo4j and the other resources. For a bit less secure but fast 1 phase commit best effort,
use <code>ChainedTransactionManager</code>, which comes bundled with Spring Data Graph. It takes a
list of transaction managers as constructor params and will handle them in order for transaction
start and commit (or rollback) in the reverse order.
</para>
<programlisting language="xml"><![CDATA[
<example>
<title>ChainedTransactionManager example</title>
<programlisting language="xml"><![CDATA[
<bean id="jpaTransactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="jtaTransactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="org.neo4j.kernel.impl.transaction.SpringTransactionManager">
<constructor-arg ref="graphDatabaseService" />
</bean>
</property>
<property name="userTransaction">
<bean class="org.neo4j.kernel.impl.transaction.UserTransactionImpl">
<constructor-arg ref="graphDatabaseService" />
</bean>
</property>
</bean>
<bean id="transactionManager"
class="org.springframework.data.graph.neo4j.transaction.ChainedTransactionManager" >
class="org.springframework.data.graph.neo4j.transaction.ChainedTransactionManager">
<constructor-arg>
<list>
<bean class="org.springframework.orm.jpa.JpaTransactionManager" id="jpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean
class="org.springframework.transaction.jta.JtaTransactionManager">
<property name="transactionManager">
<bean class="org.neo4j.kernel.impl.transaction.SpringTransactionManager">
<constructor-arg ref="graphDatabaseService" />
</bean>
</property>
<property name="userTransaction">
<bean class="org.neo4j.kernel.impl.transaction.UserTransactionImpl">
<constructor-arg ref="graphDatabaseService" />
</bean>
</property>
</bean>
<ref bean="jpaTransactionManager"/>
<ref bean="jtaTransactionManager"/>
</list>
</constructor-arg>
</bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
]]></programlisting>
</example>
</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 id="reference:programming-model:typerepresentationstrategy">
<title>Storing type information in the graph</title>
<title>Entity types stored</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

@@ -2,7 +2,7 @@
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<chapter id="samples">
<title>Samples</title>
<title>Sample code</title>
<section id="samples_introduction">
<title>Introduction</title>

View File

@@ -1,7 +1,7 @@
<?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="setup">
<title>Setup required for Spring Data Graph</title>
<title>Environment setup</title>
<para>To use Spring Data Graph in your application, some setup is required. For building the application the necessary Maven dependencies must be included and
for the AspectJ weaving some extensions of the compile goal are necessary. This chapter also discusses the Spring configuration needed to set up
Spring Data Graph. Examples for this setup can be found in the <ulink url="http://github.com/SpringSource/spring-data-graph-examples">Spring Data Graph examples</ulink>.