merge documentation updates

This commit is contained in:
Michael Hunger
2011-04-18 13:27:13 +02:00
36 changed files with 632 additions and 798 deletions

View File

@@ -4,10 +4,16 @@
<bookinfo>
<title>Good Relationships</title>
<subtitle>The Spring Data Graph Guidebook</subtitle>
<subtitle>The Spring Data Graph Guide Book</subtitle>
<releaseinfo>&version;</releaseinfo>
<date/>
<mediaobject>
<imageobject>
<imagedata fileref="springdatagraph.png" scalefit="1" contentwidth="15cm"/>
</imageobject>
</mediaobject>
<authorgroup>
<author>
<firstname>Michael</firstname>
@@ -27,11 +33,6 @@
</author>
</authorgroup>
<mediaobject>
<imageobject>
<imagedata fileref="springdatagraph.png" scalefit="1" contentwidth="15cm"/>
</imageobject>
</mediaobject>
<legalnotice>
<para>
Copies of this document may be made for your own use and for distribution

View File

@@ -2,38 +2,46 @@
<!DOCTYPE preface PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<preface>
<title>About this Guide Book</title>
<title>About this guide book</title>
<para>
<mediaobject>
<imageobject>
<imagedata fileref="springdatagraph.png" contentwidth="15cm" scalefit="1"/>
</imageobject>
</mediaobject>
Welcome to the Spring Data Graph Guide Book. Thank you for taking the time to get an in depth look
into <ulink url="https://github.com/SpringSource/spring-data-graph">Spring Data Graph</ulink>.
This project is part of the <ulink url="http://springsource.org/spring-data">Spring Data project</ulink>,
which brings the convenient programming model of the Spring Framework to modern NOSQL databases.
Spring Data Graph, as the name alludes to, aims to provide support for graph databases. It currently
supports <ulink url="http://neo4j.org">Neo4j</ulink>.
</para>
<para>
Welcome to the Spring Data Graph Guide Book. Thank you for taking the time to get an in depth look into <ulink url="https://github.com/SpringSource/spring-data-graph">Spring Data Graph Library</ulink>. Spring Data Graph is part of the <ulink url="http://springsource.org/spring-data">Spring Data project</ulink> which
brings the convenient programming model of the Spring Framework to modern (mainly NOSQL) datastores.
Spring Data Graph currently provides integration for the <ulink url="http://neo4j.org">Neo4j Graph Database</ulink>.
</para><para>
It was written by developers for developers. So hopefully we've created a documentation that is well received by
our peers.
</para><para>
If you have any feedback to the Spring Data Graph Library or this book, please provide it via <ulink url="https://jira.springsource.org/browse/DATAGRAPH">SpringSource JIRA</ulink>,
the <ulink url="http://forum.springsource.org/forumdisplay.php?f=80">SpringSource NOSQL Forum</ulink>, <ulink
url="https://github.com/SpringSource/spring-data-graph/issues">github comments or issues</ulink> or the <ulink url="http://neo4j.org/community/list/">Neo4j mailing list</ulink>.
</para><para>
This book is presented as a <ulink url="http://martinfowler.com/bliki/DuplexBook.html">duplex book</ulink>, a term coined by <ulink url="http://martinfowler.com/bliki/DuplexBook.html">Martin Fowler</ulink>. A duplex book consists of at least two
parts. The first part is an easily accessible narrative, that gives the reader an overview of the topics contained
in the book. It contains lots of examples and more general discussion topics. This should be the only part of
the book that is required to be read cover-to-cover.
</para><para>
We chose a tutorial describing the creation of a web applicaton (cineasts.net) that allows movie enthusiasts to
find the favorites, rate them, connect with each other and enjoy social features. The application is running on
Neo4j using Spring Data Graph and the well known Spring Web Stack.
</para><para>
The second part is the classic reference documentation containing the detailed information about the library.
It discusses the programming model, the underlying assumptions, used toolset (like aspectj) as well as the APIs
for the object-graph mapping and the template approach. The reference docs should be mainly used to look up
concrete bits of information or to dig deeper into certain topics.
It was written by developers for developers. Hopefully we've created a document that is well received
by our peers.
</para>
</preface>
<para>
If you have any feedback on Spring Data Graph or this book, please provide it via the
<ulink url="https://jira.springsource.org/browse/DATAGRAPH">SpringSource JIRA</ulink>, the
<ulink url="http://forum.springsource.org/forumdisplay.php?f=80">SpringSource NOSQL Forum</ulink>,
<ulink url="https://github.com/SpringSource/spring-data-graph/issues">github comments or issues</ulink>,
or the <ulink url="http://neo4j.org/community/list/">Neo4j mailing list</ulink>.
</para>
<para>
This book is presented as a <ulink url="http://martinfowler.com/bliki/DuplexBook.html">duplex book</ulink>,
a term coined by Martin Fowler. A duplex book consists of at least two parts. The first part is an easily
accessible tutorial that gives the reader an overview of the topics contained in the book. It contains lots
of examples and discussion topics. This part of the book is highly suited for cover-to-cover reading.
</para>
<para>
We chose a tutorial describing the creation of a web application that allows movie enthusiasts to
find their favorite movies, rate them, connect with fellow movie geeks, and enjoy social features such as
recommendations. The application is running on Neo4j using Spring Data Graph and the well-known Spring
Web Stack.
</para>
<para>
The second part of the book is the classic reference documentation, containing detailed information about
the library. It discusses the programming model, the underlying assumptions, and internals, as well as the
APIs for the object-graph mapping. The reference documentation is typically used to look up concrete bits of
information, or to drill down into certain topics. For hackers wanting to really delve into Spring Data
Graph, it can of course also be read cover-to-cover.
</para>
<para>
Enjoy the book!
</para>
</preface>

View File

@@ -1,11 +1,10 @@
<?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>
<title>Foreword by Emil Eifrem</title>
<para>
Emil Eifrem, CEO of Neo Technology
</para>
</preface>
<preface>
<title>Foreword by Emil Eifrem</title>
<para>
Emil Eifrem, CEO of Neo Technology
</para>
</preface>

View File

@@ -1,93 +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="get-started">
<title>Getting Started</title>
<para>NOSQL databases have only recently come to prominence, even though some of them have existed for a few years now.
That's why this document will not only guide you through the relevant parts of the Spring Data Graph
API, but also explain some key concepts of graph databases.
</para>
<para>
After reading this document, you should be able to integrate Spring Data Graph into your applications.
If there are any inaccuracies, issues or if you just think the explanations are too complicated, please feed that back to us. Your input will also benefit future readers of this documentation. For details on how to get help
and provide feedback, see <xref linkend="get-started:help"/>.
</para>
<section id="get-started:first-steps">
<title>First Steps</title>
<para>As explained in <xref linkend="why-sd-graph"/>, Spring Data Graph provides integration
between the Spring framework and graph databases. As we said in the introduction <xref linkend="introduction"/>, familiarity with the Spring framework is assumed to get the most out of this book.
But we will explain graph databases and Neo4j in particular in a little more detail.
The main focus of this document is to explain the steps needed to get an interesting Spring Data Graph application up and running.
</para>
<section id="get-started:first-steps:spring">
<title>Knowing Spring</title>
<para>Spring Data Graph makes heavy use of Spring Framework's <ulink url="http://static.springframework.org/spring/docs/3.0.x/reference/spring-core.html">core</ulink> functionality,
such as the <ulink url="http://static.springframework.org/spring/docs/3.0.x/reference/beans.html">IoC</ulink> container,
<ulink url="http://static.springsource.org/spring/docs/3.0.x/reference/validation.html#core-convert">converter</ulink> API and the
<ulink url="http://static.springframework.org/spring/docs/3.0.x/reference/aop.html">AOP</ulink> infrastructure. While it is less important
to know the Spring APIs, understanding the concepts behind them is essential.
The Spring Framework documentation
<ulink url="http://www.springsource.org/documentation">home page</ulink> is a good starting point for
developers who want to become more familiar with the Spring Framework.</para>
</section>
<section id="get-started:first-steps:nosql">
<title>Knowing NOSQL and graph databases</title>
<para>The recent interest in NOSQL databases has been driven by the need to find the better storage solutions for different kinds of data and access patterns. The NOSQL mantra is that databases should fit the data, not the other way round.
The NOSQL space is overflowing with interesting and useful technology. But as a consequence, each store tends to implement its own data access API, leading to a steep learning curve for developers intent on using polyglot persistence. Spring Data aims to ease this burden by
providing consistent abstractions over those underlying data access APIs.
</para>
<para>
Graph databases are a particularly good fit for large networks of connected information (objects). They map objects to nodes and connections to
relationships. Examples of such datasets are social networks, geospatial information, network layouts, and hardware or dependency graphs.
Neo4j is the first graph database that is tightly integrated with the Spring Data Graph project.
</para>
</section>
<section id="get-started:first-steps:samples">
<title>Trying Out The Samples</title>
<para>Spring Data Graph comes with a number of <ulink url="http://github.com/SpringSource/spring-data-graph-examples">samples</ulink>
and unit test cases (if you accessed the sources via
<ulink url="http://github.com/SpringSource/spring-data-graph">github</ulink> or Maven).
</para>
<para>For more information on the samples, see <xref linkend="samples"/>.</para>
</section>
</section>
<section id="get-started:help">
<title>Need Help?</title>
<para>If you encounter issues or you are just looking for advice, feel free to use one of the links below:</para>
<section id="get-started:help:community">
<title>Spring Data homepage</title>
<para>The Spring Data <ulink url="http://www.springsource.org/spring-data">homepage</ulink> provides all the necessary links for information, community forums and code repositories.
</para>
</section>
<section id="get-started:help:professional">
<title>Professional Support</title>
<para>Professional, from-the-source support, with guaranteed response time, is available from <ulink url="http://www.springsource.com">SpringSource</ulink>,
the company behind Spring Data and the Spring Framework.
</para>
</section>
</section>
<section id="get-started:up-to-date">
<title>Follow the Development</title>
<para>For information on the Spring Data source code repository, nightly builds and snapshot artifacts please see the Spring Data home
<ulink url="http://www.springsource.org/spring-data">page</ulink>.
</para>
<para>You can help make Spring Data better serve the needs of the Spring community by interacting with developers through the
<ulink url="http://forum.springsource.org/forumdisplay.php?f=27">community forums</ulink>.</para>
<para>If you find a bug or want to suggest an improvement,
please create a ticket on the <ulink url="https://jira.springframework.org/browse/Spring Data Graph">Spring Data Graph issue tracker</ulink>.</para>
<para>To stay up to date with the latest news and announcements in the Spring eco system, subscribe to the
<ulink url="http://www.springframework.org/">Spring Community Portal</ulink>.</para>
<para>Lastly, you can follow the <ulink url="http://blog.springsource.com/category/data-access/">SpringSource Data blog</ulink> or the project team on Twitter
(@<ulink url="http://twitter.com/SpringData">SpringData</ulink>)</para>
</section>
</chapter>

View File

@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE partintro PUBLIC "-//OASIS//DTD DocBook XML V4.4//EN"
"http://www.oasis-open.org/docbook/xml/4.4/docbookx.dtd">
<partintro>
<para>
This document is the reference guide for Spring Data Graph.
It explains the underlying concepts, usage, infrastructure of the framework and the behaviour of the underlying graph database.
</para>
<para>For an introduction to graph databases, Spring, or Spring Data examples, please refer to
<xref linkend="get-started"/>. This documentation refers only to Spring Data Graph and
assumes that the reader is familiar with Spring concepts.</para>
</partintro>

View File

@@ -1,18 +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="requirements">
<title>Requirements</title>
<para>Spring Data Graph 1.x requires JDK level 6.0 or higher,
and <ulink url="http://www.springsource.org/documentation">Spring Framework</ulink>
3.0.x or higher.</para>
<para>
For the graph database, <ulink url="http://neo4j.org/">Neo4j</ulink> 1.2 or higher is required.
Neo4j has a dependency on Apache Lucene for indexing. Users are encouraged to use the latest version of Neo4j
available.
</para>
<para>
For building the project, Apache Maven (version 2.10 and above) is recommended.
</para>
</chapter>

View File

@@ -1,43 +1,47 @@
<?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>
<preface>
<title>Foreword by Rod Johnson</title>
<para>
Im excited about Spring Data Graph for several reasons.
</para>
<para>
<para>
Im excited about Spring Data Graph for several reasons.
</para>
<para>
First, this project is in a very important space. We are in an era of transition. A very few years ago, a
relational database was a given for storing nearly all the data in nearly all applications. While relational
databases remain important, new application requirements and massive data proliferation have prompted a richer
choice of data stores. Graph databases have some very interesting strengths, and Neo4J is proving itself
valuable in many applications. Its a choice you should add to your toolbox.
</para><para>
choice of data stores. Graph databases have some very interesting strengths, and Neo4j is proving itself
valuable in many applications. It's a choice you should add to your toolbox.
</para>
<para>
Second, Spring Data Graph is an innovative project, which makes it easy to work with one of the most interesting
new data stores. Unfortunately, the proliferation of new data stores has not been matched by innovation in
programming models to work with them. Ironically, just after modern ORM mapping made working with relational
data in Java relatively easy, the data store disruption occurred, and developers were back to square one:
struggling once more with clumsy, low level APIs. Working with most non-relational technologies is overly
complex and imposes too much work on developers. Spring Data Graph makes working with Neo4J amazingly easy, and
complex and imposes too much work on developers. Spring Data Graph makes working with Neo4j amazingly easy, and
therefore has the potential to make you more successful as a developer. Its use of AspectJ to eliminate
persistence code from your domain model is truly innovative, and on the cutting edge of todays Java
technologies.
</para><para>
Third, Im excited about Spring Data Graph for personal reasons. I no longer get to write code as often as I
would like. My initial convictions that Spring and AspectJ could both make building applications with Neo4J
</para>
<para>
Third, I'm excited about Spring Data Graph for personal reasons. I no longer get to write code as often as I
would like. My initial convictions that Spring and AspectJ could both make building applications with Neo4j
dramatically easier and cross-store object navigation possible gave me an excuse for a much-needed coding binge
early in 2011. This led to a prototype of what became Spring Data Graph — at times written paired with Emil. Im
sure the vast majority of my code has long since been replaced (probably for the better) by coders who arent
early in 2010. This led to a prototype of what became Spring Data Graph — at times written paired with Emil. Im
sure the vast majority of my code has long since been replaced (probably for the better) by coders who aren't
rusty — thanks Michael and Thomas! — but I retain my pleasant memories.
</para><para>
</para>
<para>
Finally, Spring Data Graph is part of the broader Spring Data project: one of the key areas in which Spring is
innovating to help meet new application requirements. I encourage you to explore Spring Data, and — better
still — become involved in the community and contribute.
</para><para>
</para>
<para>
Enjoy the Spring Data Graph book, and happy coding!
</para>
</para>
<para>
Rod Johnson, Founder, Spring and SVP, Application Platform, VMware
</para>
</preface>
</preface>

View File

@@ -1,39 +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="why-sd-graph">
<title>Why Spring Data Graph?</title>
<para><ulink url="http://en.wikipedia.org/wiki/NOSQL">NOSQL</ulink>
stores provide novel storage solutions to suit the
data storage requirements of modern applications.
</para>
<para>
Graph databases provide excellent support for connected data - that is data that easily can
be structured as connected nodes in a network.
Property graph databases like Neo4j support an arbitrary number of named properties on
nodes and relationships. Neo4j is highly performant when traversing large, highly-connected datasets with
millions of nodes and relationships, even on commodity hardware.
</para>
<para>
Neo4j is an open source graph database written in Java. It has excellent performance characteristics while providing ACID
semantics and full transactional support (both JTA and XA transactions). Neo4j can run as a lightweight embedded database as well as a standalone
server that exposes the API via a rich REST interface.
</para>
<para>The Spring Data Graph framework makes it easy to
integrate graph databases in existing or new Spring applications. It provides
infrastructure that reduces boilerplate data access code and uses
common patterns and idioms that are well-known in the Spring community, such as declarative transaction management.
Those practices are based on a simple POJO programming model that leverages
annotations to add metadata. It can be integrated in any part of a Spring application,
including the Web or service layers.
</para>
<para>
A special use case of Spring Data Graph is the cross-store functionality that can extend
existing JPA data models with new, graph database backed parts (properties, entities, relationships).
These parts are stored exclusively in the graph database while being transparently
integrated with the JPA entities. This enables easy and seamless addition of new features
that have not been available to JPA-based applications previously.
</para>
</chapter>

View File

@@ -3,56 +3,55 @@
<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
Oriented Programming</ulink> paradigm that allows easy extraction and controlled application of so called
cross cutting concerns. Cross cutting concerns are repetitive tasks in a system (e.g. logging, security,
auditing, caching, transaction scoping) that are difficult to extract using the normal OO paradigms. The means
of the OO paradigm, of subclassing, polymorphism, overriding and delegation are still very cumbersome to use
with many of those concerns applied in the codebase. Also the flexibility is limited or would add quite a number
of configuration options or parameters.
The object graph mapper of Spring Data Graph relies heavily on AspectJ. AspectJ is a Java implementation
of the <ulink url="https://secure.wikimedia.org/wikipedia/en/wiki/Aspect-oriented_programming">aspect-oriented
programming</ulink> paradigm that allows easy extraction and controlled application of so-called
cross-cutting concerns. Cross-cutting concerns are typically repetitive tasks in a system (e.g. logging,
security, auditing, caching, transaction scoping) that are difficult to extract using the normal OO
paradigms. Many OO concepts, such as subclassing, polymorphism, overriding and delegation are still
cumbersome to use with many of those concerns applied in the code base. Also, the flexibility becomes
limited, potentially adding quite a number of configuration options or parameters.
</para>
<para>
The learning curve for the AspectJ pointcut language is quite slow but the developer who uses Spring Data Graph
will not be confronted with that. Users do not have care about to hooking into a framework mechanism or having
to extend a framework superclass.
The AspectJ pointcut language can be intimidating, but a developer using Spring Data Graph will not have
to deal with that. Users don't have care about to hooking into a framework mechanism, or having to extend
a framework superclass.
</para>
<para>
That's why AspectJ uses a declarative approach, defining concrete advice, which is just
the piece of code that contains the implementation of the concern. AspectJ advice can for instance
be applied before, after, or instead of a method or constructor call, or variable access. This is declared
using AspectJ's expressive pointcut language that is able to express any place within a code structure
or flow.
AspectJ is also able to introduce new methods, fields, annotations, interfaces, and superclasses
to existing classes.
AspectJ uses a declarative approach, defining concrete advice, which is just pieces of code that contain
the implementation of the concern. AspectJ advice can for instance be applied before, after, or instead
of a method or constructor call. It can also be applied on variable and field access. This is declared
using AspectJ's expressive pointcut language, able to express any place within a code structure or flow.
AspectJ is also able to introduce new methods, fields, annotations, interfaces, and superclasses to
existing classes.
</para>
<para>
Spring Data Graph uses both mechanisms internally. First, when encountering <code>@NodeEntity</code> or
<code>@RelationshipEntity</code> annotations it introduces a new interface <code>NodeBacked</code> or
<code>RelationshipBacked</code>, depending on the annotation type. Secondly, it introduces fields and methods
to the annotated class. See <xref linkend="reference:programming-model:introduced-methods"/> for more
information on the methods introduced.
Spring Data Graph uses a mix of these mechanisms internally. First, when encountering the
<code>@NodeEntity</code> or <code>@RelationshipEntity</code> annotations it introduces a new interface
<code>NodeBacked</code> or <code>RelationshipBacked</code> to the annotated class. Secondly, it introduces
fields and methods to the annotated class. See <xref linkend="reference:programming-model:introduced-methods"/>
for more information on the methods introduced.
</para>
<para>
Spring Data Graph also leverages AspectJ to intercept access to fields, delegating the calls to the graph
database instead. Under the hood, properties and relationships will be created.
</para>
<para>
So how is an aspect applied to a concrete class? This can be either done at compile time with the
AspectJ Java compiler (ajc) that takes source files and aspect definitions, and then compiles the source files
while adding all the necessary interception code for the aspects to hook in where they're declared to. This is
known as compile-time weaving. At runtime only a small AspectJ runtime is needed, as the bytecode of the
classes has already been rewritten to delegate appropriate calls via the declared advice in the aspects.
So how is an aspect applied to a concrete class? At compile time , the AspectJ Java compiler (ajc) takes
source files and aspect definitions, and compiles the source files while adding all the necessary
interception code for the aspects to hook in where they're declared to. This is known as compile-time
<emphasis>weaving</emphasis>. At runtime only a small AspectJ runtime is needed, as the byte code of the
classes has already been rewritten to delegate the appropriate calls via the declared advice in the aspects.
</para>
<note>
<para>
A caveat of using compile-time weaving is that all source files that should be part of the weaving process must
be compiled with the AspectJ compiler. Fortunately, this is all taken care of seamlessly by the AspectJ Maven
plugin.
A caveat of using compile-time weaving is that all source files that should be part of the weaving
process must be compiled with the AspectJ compiler. Fortunately, this is all taken care of seamlessly
by the AspectJ Maven plugin.
</para>
</note>
<para>
AspectJ also supports other types of weaving, for example load-time weaving and runtime weaving. These are
AspectJ also supports other types of weaving, e.g. load-time weaving and runtime weaving. These are
currently not supported by Spring Data Graph.
</para>
</chapter>

View File

@@ -1,142 +1,159 @@
<?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</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.
</para>
<para>
This allows existing JPA-based applications to embrace NOSQL data stores to evolve certain parts of their model.
Possible use cases are adding social network or geospatial information to existing applications.
</para>
<section>
<title>Partial graph persistence</title>
<title>Cross-store persistence</title>
<para>
The Spring Data Graph project support cross-store persistence, which allows for parts of the data to be
stored in a traditional JPA data store (RDBMS), and other parts in a graph store. This means that an entity
can be partially stored in e.g. MySQL, and partially stored in Neo4j.
</para>
<para>
This allows existing JPA-based applications to embrace NOSQL data stores for evolving certain parts
of their data model. Possible use cases include adding social networking or geospatial information to
existing applications.
</para>
<section>
<title>Partial entities</title>
<para>
Partial graph persistence is achieved by restricting the Spring Data Graph aspects to explicitly annotated parts of
the entity. Those fields will be made transient by the aspect so that JPA ignores them and won't try to persist those
attributes.
Partial graph persistence is achieved by restricting the Spring Data Graph aspects to manage only
explicitly annotated parts of the entity. Those fields will be made <code>@Transient</code> by the
aspect so that JPA ignores them.
</para>
<para>
A backing node in the graph store is only created when the entity has been assigned a JPA id. Only then will the connection between the
two stores be kept. Until the entity has been persisted, its state is just kept inside the POJO (detached state) and flushed to the
backing graph store afterwards.
</para>
<para>
The connection between the two entities is kept via a FOREIGN_ID field in the node that contains the JPA id
(currently only single value ids are supported). The entity class can be resolved via the
TypeRepresentationStrategy that manages the Java type hierarchy within the graph. With the id and class,
you can then retrieve the appropriate JPA entity for a given node.
A backing node in the graph store is only created when the entity has been assigned a JPA ID. Only
then will the association between the two stores be established. Until the entity has been persisted,
its state is just kept inside the POJO (in detached state), and then flushed to the backing graph
database on <code>persist()</code>.
</para>
<para>
The other direction is handled by indexing the Node with the FOREIGN_ID index which contains a concatenation of the fully qualified class
name of the JPA entity and the id. So it is possible on instantiation of a JPA id via the entity manager (or some other means like creating
the POJO and setting its id manually) to find the matching node using the index facilities and reconnect them.
</para>
<para>
Using those mechanisms and the Spring Data Graph aspects a single POJO can contain fields that are handled by JPA and other fields
(which might be relationships as well) that are handled by Spring Data Graph.
</para>
<section>
<title>@NodeEntity(partial = "true")</title>
<para>
When annotating an entity with partial true, Spring Data Graph assumes that this is a cross-store entity. So its only responsibility is for the fields
annotated with Spring Data Graph annotations. JPA should not take care of these fields (they should be annotated with @Transient). In this mode of
operation Spring Data Graph also handles the cross-store connection via the content of the JPA id field.
</para>
</section>
<section>
<title>@GraphProperty</title>
<para>
For common fields containing primitive or convertible values that wouldn't have to be annotated in exclusive Spring Data Graph operations this
explicit declaration is necessary to be sure that they are intended to be stored in the graph. These fields should then be made transient
so that JPA doesn't try to take care of them as well.
</para>
</section>
<para>
The following example is taken from the <ulink url="http://github.com/SpringSource/spring-data-graph-examples">Spring Data Graph examples</ulink>,
it is contained in the myrestaurant-social project.
</para>
<programlisting language="java" ><![CDATA[
@Entity
@Table(name = "user_account")
@NodeEntity(partial = true)
public class UserAccount {
private String userName;
private String firstName;
private String lastName;
<para>
The association between the two entities is maintained via a FOREIGN_ID field in the node, that
contains the JPA ID. Currently only single-value IDs are supported. The entity class can be resolved
via the <code>TypeRepresentationStrategy</code> that manages the Java type hierarchy within the graph
database. Given the ID and class, you can then retrieve the appropriate JPA entity for a given node.
</para>
<para>
The other direction is handled by indexing the Node with the FOREIGN_ID index which contains a
concatenation of the fully qualified class name of the JPA entity and the ID. The matching node
can then be found using the indexing facilities, and the two entities can be reassociated.
</para>
<para>
Using these mechanisms and the Spring Data Graph aspects, a single POJO can contain some fields
handled by JPA and others handles by Spring Data Graph. This also includes relationship fields persisted
in the graph database.
</para>
</section>
<section>
<title>Cross-store annotations</title>
<para>
Cross-store persistence only requires the use of one additional annotation: <code>@GraphProperty</code>.
See below for details and an example.
</para>
<section>
<title>@NodeEntity(partial = "true")</title>
<para>
When annotating an entity with <code>partial = true</code>, this marks it as a cross-store entity.
Spring Data Graph will thus only manage fields explicitly annotated with <code>@GraphProperty</code>.
</para>
</section>
<section>
<title>@GraphProperty</title>
<para>
Fields of primitive or convertible types do not normally have to be annotated in order to be
persisted by Spring Data Graph. In cross-store mode, Spring Data Graph <emphasis>only</emphasis>
persists fields explicitly annotated with <code>@GraphProperty</code>. JPA will ignore these fields.
</para>
</section>
<para>
The following example is taken from the
<ulink url="http://github.com/SpringSource/spring-data-graph-examples">Spring Data Graph examples</ulink>
myrestaurants-social project:
</para>
<example>
<title>Cross-store node entity</title>
<programlisting language="java"><![CDATA[@Entity
@Table(name = "user_account")
@NodeEntity(partial = true)
public class UserAccount {
private String userName;
private String firstName;
private String lastName;
@GraphProperty
String nickname;
@GraphProperty
String nickname;
@RelatedTo(type = "friends", elementClass = UserAccount.class)
Set<UserAccount> friends;
@RelatedTo(type = "friends", elementClass = UserAccount.class)
Set<UserAccount> friends;
@RelatedToVia(type = "recommends", elementClass = Recommendation.class)
Iterable<Recommendation> recommendations;
@RelatedToVia(type = "recommends", elementClass = Recommendation.class)
Iterable<Recommendation> recommendations;
@Temporal(TemporalType.TIMESTAMP)
@DateTimeFormat(style = "S-")
private Date birthDate;
@Temporal(TemporalType.TIMESTAMP)
@DateTimeFormat(style = "S-")
private Date birthDate;
@ManyToMany(cascade = CascadeType.ALL)
private Set<Restaurant> favorites;
@ManyToMany(cascade = CascadeType.ALL)
private Set<Restaurant> favorites;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "id")
private Long id;
@Transactional
public void knows(UserAccount friend) {
relateTo(friend, "friends");
}
@Transactional
public void knows(UserAccount friend) {
relateTo(friend, "friends");
}
@Transactional
public Recommendation rate(Restaurant restaurant, int stars, String comment) {
Recommendation recommendation = relateTo(restaurant, Recommendation.class, "recommends");
recommendation.rate(stars, comment);
return recommendation;
}
public Iterable<Recommendation> getRecommendations() {
return recommendations;
}
}
@Transactional
public Recommendation rate(Restaurant restaurant, int stars, String comment) {
Recommendation recommendation = relateTo(restaurant, Recommendation.class, "recommends");
recommendation.rate(stars, comment);
return recommendation;
}
public Iterable<Recommendation> getRecommendations() {
return recommendations;
}
}
]]></programlisting>
</section>
<section>
<title>Configuring cross-store persistence</title>
<para>
Configuring cross-store persistence is done similarly to the default Spring Data Graph operations. As soon as you refer
to an <code>entityManagerFactory</code> in the xml-namespace it is set up for cross-store persistence.
</para>
<programlisting language="xml" ><![CDATA[
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
</example>
</section>
<section>
<title>Configuring cross-store persistence</title>
<para>
Configuring cross-store persistence is done similarly to the default Spring Data Graph configuration.
All you need to do is to specify an <code>entityManagerFactory</code> in the XML namespace
<code>config</code> element, and Spring Data Graph will configure itself for cross-store use.
</para>
<example>
<title>Cross-store Spring configuration</title>
<programlisting language="xml"><![CDATA[<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:datagraph="http://www.springframework.org/schema/data/graph"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/data/graph
http://www.springframework.org/schema/data/graph/datagraph-1.0.xsd
">
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/data/graph
http://www.springframework.org/schema/data/graph/datagraph-1.0.xsd
">
<context:annotation-config/>
<context:annotation-config/>
<datagraph:config storeDirectory="target/config-test"
entityManagerFactory="entityManagerFactory"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
id="entityManagerFactory">
id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>
</bean>
</beans>
]]></programlisting>
</example>
</section>
</section>
</chapter>

View File

@@ -3,80 +3,87 @@
<chapter id="reference_neo4j-server">
<title>Neo4j Server</title>
<para>
Neo4j is not only available in embedded mode, it can also be installed and run as a server that is accessed
via a REST API. Spring Data Graph provides two-fold integration for infrastructure.
Neo4j is not only available in embedded mode. It can also be installed and run as a stand-alone server
accessible via a REST API. Developers can integrate Spring Data Graph into the Neo4j server infrastructure
in two ways: in an unmanaged server extension, or via the REST API.
</para>
<section>
<title>Server Extension</title>
<para>
What is the use-case for writing server extensions? The REST API is a pretty generic representation of the
Neo4j core API. It is nice for getting started and simple scenarios. For more involved solutions that require
high speed and high volume access to the embedded graph database, writing a server extension that is able to
process external parameters and return just the relevant information to the calling client is preferrable.
When should you write a server extension? The default REST API is essentially a REST'ified representation
of the Neo4j core API. It is nice for getting started, and for simpler scenarios. For more involved
solutions that require high-volume access or more complex operations, writing a server extension that
is able to process external parameters, do all the computations locally in the plugin, and then return
just the relevant information to the calling client is preferable.
</para>
<para>
The Neo4j server has two built in extension mechanisms.
It is possible to add extensions to existing endpoints
like the graph database, nodes or relationships - add new URIs or methods to those. This is achieved by
writing <ulink url="http://docs.neo4j.org/chunked/milestone/server-plugins.html">Server Plugins</ulink>.
The Neo4j Server has two built-in extension mechanisms. It is possible to extend existing URI endpoints
like the graph database, nodes, or relationships, adding new URIs or methods to those. This is achieved
by writing a <ulink url="http://docs.neo4j.org/chunked/milestone/server-plugins.html">server plugin</ulink>.
This plugin type has some restrictions though.
</para>
<para>
For complete freedom in your implementation an <ulink
url="http://docs.neo4j.org/chunked/milestone/server-unmanaged-extensions.html">unmanaged extension</ulink>
might be the right solution. Unmanaged
extensions are <ulink url="http://jersey.java.net/">Jersey</ulink> resource implementations.
The resources constructors or methods can get the <code>GraphDatabaseService</code> injected to execute the
necessary operations and return appropriate Representations.
For complete freedom in the implementation, an
<ulink url="http://docs.neo4j.org/chunked/milestone/server-unmanaged-extensions.html">unmanaged extension</ulink>
can be used. Unmanaged extensions are essentially <ulink url="http://jersey.java.net/">Jersey</ulink>
resource implementations. The resource constructors or methods can get the
<code>GraphDatabaseService</code> injected to execute the necessary operations and return appropriate
<code>Representations</code>.
</para>
<para>
Both kinds of extensions have to be packaged as a jar and added to the Neo4j-Server's plugin directory.
Server Plugins are picked up at server startup when they provide the necessary
<code>META-INF.services/org.neo4j.server.plugins.ServerPlugin</code> file for Javas service loader mechanism.
Unmanaged extensions have to be registered with the Neo4j Server configuration.
<programlisting language="ini"><![CDATA[
org.neo4j.server.thirdparty_jaxrs_classes=com.example.mypackage=/my-context
]]></programlisting>
Both kinds of extensions have to be packaged as JAR files and added to the Neo4j Server's plugin
directory. Server Plugins are picked up by the server at startup if they provide the necessary
<code>META-INF.services/org.neo4j.server.plugins.ServerPlugin</code> file for Java's ServiceLoader
facility. Unmanaged extensions have to be registered with the Neo4j Server configuration.
</para>
<example>
<title>Configuring an unmanaged extension</title>
<programlisting language="ini"><![CDATA[org.neo4j.server.thirdparty_jaxrs_classes=com.example.mypackage=/my-context]]></programlisting>
</example>
<para>
Running Spring Data Graph on the server is easy. You need to tell the server where to find the Spring Context
file, and which beans from it to expose, using what type:
<programlisting language="java"><![CDATA[
public class HelloWorldInitializer extends SpringPluginInitializer {
Running Spring Data Graph on the Neo4j Server is easy. You need to tell the server where to find the
Spring context configuration file, and which beans from it to expose:
<example>
<title>Server plugin initialization</title>
<programlisting language="java"><![CDATA[public class HelloWorldInitializer extends SpringPluginInitializer {
public HelloWorldInitializer() {
super(new String[]{"spring/helloWorldServer-Context.xml"},
Pair.of("worldRepository", WorldRepository.class),
Pair.of("graphRepositoryFactory", GraphRepositoryFactory.class));
super(new String[]{"spring/helloWorldServer-Context.xml"},
Pair.of("worldRepository", WorldRepository.class),
Pair.of("graphRepositoryFactory", GraphRepositoryFactory.class));
}
}
]]></programlisting>
Now, your resources can be annotated with the beans they need, like this:
<programlisting language="java"><![CDATA[
@Path( "/path" )
@POST
@Produces( MediaType.APPLICATION_JSON )
public void foo( @Context WorldRepository repo ) {
...
}
]]></programlisting>
The <code>SpringPluginInitializer</code> merges the graph database service
with the spring configuration and registers the named beans as jersey Injectables.
It is still necessary to list the initializer fully qualified class name in a
file named META-INF/services/org.neo4j.server.plugins.PluginLifecycle. Then the Neo4j Server can pick up
and run the initialization classes before the the extensions are loaded.
</example>
Now, your resources can be annotated with the beans they need, like this:
<example>
<title>Jersey resource</title>
<programlisting language="java"><![CDATA[@Path( "/path" )
@POST
@Produces( MediaType.APPLICATION_JSON )
public void foo( @Context WorldRepository repo ) {
...
}
]]></programlisting>
</example>
The <code>SpringPluginInitializer</code> merges the GraphDatabaseService with the Spring configuration
and registers the named beans as Jersey <code>Injectables</code>. It is still necessary to list the
initializer's fully qualified class name in a file named
<code>META-INF/services/org.neo4j.server.plugins.PluginLifecycle</code>. The Neo4j Server can then pick
up and run the initialization classes before the extensions are loaded.
</para>
</section>
<section>
<title>Using Spring Data Graph as a REST-Client</title>
<title>Using Spring Data Graph as a REST client</title>
<para>
Spring Data Graph can use the Java Rest Bindings which come as a drop in replacement for the
GraphDatabaseService API. Just by configuring the <code>graphDatabaseService</code> to be a
<code>RestGraphDatabaseService</code> pointing to the correct URL, a Neo4j-REST server can be used.
Spring Data Graph can use a set of Java REST bindings which come as a drop in replacement for the
GraphDatabaseService API. By simply configuring the <code>graphDatabaseService</code> to be a
<code>RestGraphDatabase</code> pointing to a Neo4j Server instance.
</para>
<note>
<para>
The Neo4j REST API does not allow keeping transactions open, which means that SDG is not transactional
when running against REST.
The Neo4j Server REST API does not allow for transactions to span across requests, which means
that Spring Data Graph is not transactional when running with a <code>RestGraphDatabase</code>.
</para>
</note>
@@ -91,19 +98,19 @@ public class HelloWorldInitializer extends SpringPluginInitializer {
<version>1.0.0.RELEASE</version>
</dependency>
]]></programlisting>
</example>
Now, you set up the normal SDG configuration, but point the database to an URL instead of a local file, like this:
<example>
<title>REST-Client configuration - application context</title>
<programlisting language="xml"><![CDATA[
<datagraph:config graphDatabaseService="graphDatabaseService"/>
</example>
Now, you set up the normal Spring Data Graph configuration, but point the database to an URL instead
of a local directory, like so:
<example>
<title>REST client configuration - application context</title>
<programlisting language="xml"><![CDATA[<datagraph:config graphDatabaseService="graphDatabaseService"/>
<bean id="graphDatabaseService" class="org.neo4j.rest.graphdb.RestGraphDatabase">
<constructor-arg value="http://localhost:7474/db/data/"/>
</bean>
]]></programlisting>
</example>
Your project is now set up to work against a remote Neo4j Server.
</example>
Your project is now set up to work against a remote Neo4j Server.
</para>
</section>
</chapter>

View File

@@ -81,8 +81,7 @@
</para>
<example>
<title>Neo4j usage</title>
<programlisting language="java" ><![CDATA[
GraphDatabaseService graphDb = new EmbeddedGraphDatabase( "helloworld" );
<programlisting language="java" ><![CDATA[GraphDatabaseService graphDb = new EmbeddedGraphDatabase( "helloworld" );
Transaction tx = graphDb.beginTx();
try {
Node firstNode = graphDb.createNode();
@@ -110,8 +109,7 @@ try {
</para>
<example>
<title>Traversal usage</title>
<programlisting language="java" ><![CDATA[
TraversalDescription traversalDescription = Traversal.description()
<programlisting language="java" ><![CDATA[TraversalDescription traversalDescription = Traversal.description()
.depthFirst()
.relationships(KNOWS)
.relationships(LIKES, Direction.INCOMING)
@@ -139,9 +137,7 @@ for (Path position : traversalDescription.traverse(myStartNode)) {
</note>
<example>
<title>Index usage</title>
<programlisting language="java"><![CDATA[
IndexManager indexManager = graphDb.index();
<programlisting language="java"><![CDATA[IndexManager indexManager = graphDb.index();
Index<Node> nodeIndex = indexManager.forNodes("a-node-index");
Node node = ...;
Transaction tx = graphDb.beginTx();

View File

@@ -3,38 +3,36 @@
<chapter id="reference_performance">
<title>Performance considerations</title>
<para>
Although adding another layer of abstraction is always the solution to look for in software development,
each of those layers adds overhead and performance penalties. This chapter discusses the performance
implications of using Spring Data Graph on top of the native Neo4j API.
Although adding layers of abstraction is a common pattern in software development, each of these layers
generally adds overhead and performance penalties. This chapter discusses the performance implications
of using Spring Data Graph instead of the Neo4j API directly.
</para>
<section>
<title>When to use SDG?</title>
<title>When is Spring Data Graph right</title>
<para>
The focus of Spring Data Graph is to add a convenience layer on top of the native Neo4j API. This should
enable developers to get up and running with the graph database very quickly, having their domain objects
mapped to the graph. Building on this foundation one can later explore other, more efficient ways to
explore and process the graph - if the performance requirements demand it.
</para>
<para>
Like any other object mapping framework, the domain entities that are created, read or persisted represent
only a small fraction of the data stored in the database. This is the set needed for a certain use-case to
be displayed, edited or processed in a low throughput fashion. The main advantages of using an object mapper
in this case is the ease of use of real domain objects in your business logic and also with existing
frameworks and libraries that expect Java POJOs as input or create them as results.
</para>
<para>
Spring Data Graph was not designed with a major performance focus. It adds some overhead to pure graph operations.
Something to keep in mind is, that the access of properties and relationships is a read trough in the attached
case. So to avoid multiple read-throughs it is sensible to store the result in a local variable at the scope of
use (method, class or jsp for example).
</para>
<para>
Most of the overhead comes from the use of the Java Reflection API, which is leveraged to provide
information about Annotations, Fields and Constructors.
Some of the information is already cached by the JVM and the library, so that only the first access gets a
performance penalty.
The focus of Spring Data Graph is to add a convenience layer on top of the Neo4j API. This enables
developers to get up and running with a graph database very quickly, having their domain objects
mapped to the graph with very little work. Building on this foundation, one can later explore other,
more efficient ways to explore and process the graph - if the performance requirements demand it.
</para>
<!--<para>-->
<!--Like any other object mapping framework, the domain entities that are created, read, or persisted -->
<!--represent only a small fraction of the data stored in the database. This is the set needed for a -->
<!--certain use-case to be displayed, edited or processed in a low throughput fashion. The main advantages -->
<!--of using an object mapper in this case are the ease of use of real domain objects in your business -->
<!--logic and also with existing-->
<!--frameworks and libraries that expect Java POJOs as input or create them as results.-->
<!--</para>-->
<para>
Spring Data Graph was however not designed with a major focus on performance. It does add some overhead
to pure graph operations. Something to keep in mind is that any access of properties and relationships
will in general read through down to the database. To avoid multiple reads, it is sensible to store the
result in a local variable in suitable scope (e.g. method, class or jsp).
</para>
<para>
Most of the overhead comes from the use of the Java Reflection API, which is used to provide
information about annotations, fields and constructors. Some of the information is already cached
by the JVM and the library, so that only the first access gets a performance penalty.
</para>
</section>
</chapter>

View File

@@ -11,8 +11,7 @@
</para>
<example>
<title>Bean validation</title>
<programlisting language="java"><![CDATA[
@NodeEntity
<programlisting language="java"><![CDATA[@NodeEntity
class Person {
@Size(min = 3, max = 20)
String name;

View File

@@ -39,8 +39,7 @@
</para>
<example>
<title>Indexing entities</title>
<programlisting language="java"><![CDATA[
@NodeEntity
<programlisting language="java"><![CDATA[@NodeEntity
class Person {
@Indexed(indexName = "people") String name;
@Indexed int age;
@@ -80,8 +79,7 @@ for (Person middleAgedDeveloper : graphRepository.findAllByRange("age", 20, 40))
<para>
<example>
<title>Fulltext indexing</title>
<programlisting language="java"><![CDATA[
@NodeEntity
<programlisting language="java"><![CDATA[@NodeEntity
class Person {
@Indexed(indexName = "person-name", fulltext=true) String name;
}
@@ -111,8 +109,7 @@ Person mark = graphRepository.findAllByQuery("people-search", "name", "ma*");
</para>
<example>
<title>Manual index usage</title>
<programlisting language="java"><![CDATA[
@Autowired GraphDatabaseContext gdc;
<programlisting language="java"><![CDATA[@Autowired GraphDatabaseContext gdc;
// Default index
Index<Node> personIndex = gdc.getIndex(Person.class);

View File

@@ -24,9 +24,9 @@
reporting or auditing) and only project them to a concrete, more functional target type when the business
logic requires it.
</para>
<programlisting language="java"><![CDATA[
// not related to Person at all
@NodeEntity
<example>
<title>Projection of entities</title>
<programlisting language="java"><![CDATA[@NodeEntity
class Trainee {
String name;
@RelatedTo(elementClass=Training.class);
@@ -40,5 +40,7 @@ for (Person person : graphRepository.findAllByProperyValue("occupation","develop
}
}
]]></programlisting>
</example>
</section>

View File

@@ -24,8 +24,7 @@
<example>
<title>Single relationship field</title>
<programlisting language="java"><![CDATA[
@NodeEntity
<programlisting language="java"><![CDATA[@NodeEntity
public class Movie {
private Actor mostPaidActor;
}
@@ -42,8 +41,7 @@ public class Movie {
</para>
<example>
<title>Node entity with relationships</title>
<programlisting language="java"><![CDATA[
@NodeEntity
<programlisting language="java"><![CDATA[@NodeEntity
public class Actor {
@RelatedTo(type = "mostPaidActor", direction = Direction.INCOMING,
elementClass = Movie.class)
@@ -103,8 +101,7 @@ public class Actor {
</para>
<example>
<title>Relationship entity</title>
<programlisting language="java"><![CDATA[
@NodeEntity
<programlisting language="java"><![CDATA[@NodeEntity
public class Actor {
public Role playedIn(Movie movie, String title) {
return relatedTo(movie, Role.class, "ACTS_IN");
@@ -132,8 +129,7 @@ public class Role {
</para>
<example>
<title>Accessing relationship entities using @RelatedToVia</title>
<programlisting language="java"><![CDATA[
@NodeEntity
<programlisting language="java"><![CDATA[@NodeEntity
public class Actor {
@RelatedToVia(type = "ACTS_IN", elementClass = Role.class)
private Iterable<Role> roles;

View File

@@ -132,28 +132,27 @@
</para>
<example>
<title>Using GraphRepositories</title>
<programlisting language="java"><![CDATA[
GraphRepository<Person> graphRepository = graphRepositoryFactory
.createGraphRepository(Person.class);
<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();
Long numberOfPeople = graphRepository.count();
Person mark = graphRepository.findByPropertyValue("name", "mark");
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>
Iterable<Person> davesFriends = graphRepository.findAllByTraversal(dave,
Traversal.description().pruneAfterDepth(1)
.relationships(KNOWS).filter(returnAllButStartNode()));
]]></programlisting>
</example>
</section>
@@ -167,8 +166,7 @@
</para>
<example>
<title>Composing repositories</title>
<programlisting language="java"><![CDATA[
public interface PersonRepository extends GraphRepository<Person>, PersonRepositoryExtension {}
<programlisting language="java"><![CDATA[public interface PersonRepository extends GraphRepository<Person>, PersonRepositoryExtension {}
// alternatively select some of the required repositories individually
public interface PersonRepository extends CRUDGraphRepository<Node,Person>,

View File

@@ -22,8 +22,7 @@
</note>
<example>
<title>Simple transaction manager configuration</title>
<programlisting language="xml"><![CDATA[
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
<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"/>
@@ -47,8 +46,7 @@
</para>
<example>
<title>Neo4j Spring integration</title>
<programlisting language="xml"><![CDATA[
<context:annotation-config />
<programlisting language="xml"><![CDATA[<context:annotation-config />
<context:spring-configured/>
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
@@ -78,8 +76,7 @@
</para>
<example>
<title>ChainedTransactionManager example</title>
<programlisting language="xml"><![CDATA[
<bean id="jpaTransactionManager"
<programlisting language="xml"><![CDATA[<bean id="jpaTransactionManager"
class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>

View File

@@ -2,210 +2,227 @@
<!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>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>.
<para>
Spring Data Graph dramatically simplifies development, but some setup is naturally required.
For building the application, Maven needs to be configured to include the Spring Data Graph dependencies,
and configure the AspectJ weaving. After the build setup is complete, the Spring application needs to be
configured to make use of 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>.-->
</para>
<section>
<title>Maven Configuration</title>
<title>Maven configuration</title>
<para>
As stated in the requirements chapter, Spring Data Graph projects are easiest to build with Apache Maven. The main dependencies are Spring Data Graph itself, Spring Data Commons, some parts of the Spring Framework and of course the Neo4j graph database.
Spring Data Graph projects are easiest to build with Apache Maven. The main dependencies are: Spring
Data Graph itself, Spring Data Commons, parts of the Spring Framework, and the Neo4j graph database.
</para>
<section>
<title>Repositories</title>
<title>Repositories</title>
<para>
The milestone releases of Spring Data Graph are available from the dedicated milestone repository. Neo4j
releases and milestones are available from Maven Central.
The milestone releases of Spring Data Graph are available from the dedicated milestone
repository. Neo4j releases and milestones are available from Maven Central.
</para>
<programlisting language="xml"><![CDATA[
<repository>
<id>spring-maven-milestone</id>
<name>Springframework Maven Repository</name>
<url>http://maven.springframework.org/milestone</url>
<example>
<title>Spring milestone repository</title>
<programlisting language="xml"><![CDATA[<repository>
<id>spring-maven-milestone</id>
<name>Springframework Maven Repository</name>
<url>http://maven.springframework.org/milestone</url>
</repository>
]]></programlisting>
</section>
<section>
<title>Dependencies</title>
<para>The dependency on <code>spring-data-neo4j</code>
should transitively pull in Spring Framework (core, context, aop,
aspects, tx), Aspectj, Neo4j and Spring Data Commons. If you already use these (or different versions of
these) in your project, then include those dependencies on your own.
</para>
<programlisting language="xml"><![CDATA[
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.11.RELEASE</version>
</dependency>
]]></programlisting>
]]></programlisting>
</example>
</section>
<section>
<title>AspectJ build configuration</title>
<para>As Spring Data Graph uses AspectJ for build time aspect weaving of your entities, it is necessary to add the aspectj-plugin to the build phases. The plugin has its own dependencies. You also need to explicitely specifiy libraries containing aspects (spring-aspects and spring-data-neo4j)</para>
<programlisting language="xml"><![CDATA[
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.0</version>
<dependencies>
<!-- NB: You must use Maven 2.0.9 or above or these are ignored (see MNG-2972) -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.6.11.RELEASE</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
<aspectLibrary>
<groupId>org.springframework.data</groupId>
<artifactId>spring-datastore-neo4j</artifactId>
</aspectLibrary>
</aspectLibraries>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
]]></programlisting>
</section>
</section>
<section>
<title>Setting Up Spring Data Graph - Spring Configuration</title>
<para>The concrete configuration for Spring Data Graph is quite verbose as there is no autowiring involved. It sets up the following parts.
<itemizedlist>
<listitem>
<para>GraphDatabaseService for the embedded Neo4j storage engine</para>
</listitem>
<listitem>
<para>Spring transaction manager, Neo4j transaction manager</para>
</listitem>
<listitem>
<para>aspects and instantiators for node and relationship entities</para>
</listitem>
<listitem>
<para>EntityState and FieldAccessFactories needed for the different field handling</para>
</listitem>
<listitem>
<para>Conversion services</para>
</listitem>
<listitem>
<para>Repository support</para>
</listitem>
<listitem>
<para>TypeRepresentationStrategies</para>
</listitem>
</itemizedlist>
</para>
<section>
<title>XML-Namespace</title>
<title>Dependencies</title>
<para>
To simplify the configuration we provide a xml namespace <code>datagraph</code> that allows configuration of any
Spring Data Graph project with a single line of xml code. There are three possible parameters. You can use <code>storeDirectory</code>
or the reference to <code>graphDatabaseService</code> alternatively. For cross-store configuration just refer
to an <code>entityManagerFactory</code>.
The dependency on <code>spring-data-neo4j</code> will transitively pull in the necessary parts of
Spring Framework (core, context, aop, aspects, tx), Aspectj, Neo4j, and Spring Data Commons. If you
already use these (or different versions of these) in your project, then include those dependencies
on your own.
</para>
<programlisting language="xml"><![CDATA[
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<example>
<title>Maven dependencies</title>
<programlisting language="xml"><![CDATA[<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>1.0.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.11.RELEASE</version>
</dependency>
]]></programlisting>
</example>
</section>
<section>
<title>AspectJ build configuration</title>
<para>
Since Spring Data Graph uses AspectJ for build-time aspect weaving of entities, it is necessary to
hook in the AspectJ Maven plugin to the build process. The plugin also has its own dependencies. You
also need to explicitly specify the aspect libraries (spring-aspects and spring-data-neo4j).
</para>
<example>
<title>AspectJ configuration</title>
<programlisting language="xml"><![CDATA[<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.0</version>
<dependencies>
<!-- NB: You must use Maven 2.0.9 or above or these are ignored (see MNG-2972) -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.11.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjtools</artifactId>
<version>1.6.11.RELEASE</version>
</dependency>
</dependencies>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<aspectLibraries>
<aspectLibrary>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
</aspectLibrary>
<aspectLibrary>
<groupId>org.springframework.data</groupId>
<artifactId>spring-datastore-neo4j</artifactId>
</aspectLibrary>
</aspectLibraries>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
]]></programlisting>
</example>
</section>
</section>
<section>
<title>Spring configuration</title>
<para>
Users of Spring Data Graph have two ways of very concisely configuring it. Either they can use a
Spring Data Graph XML configuration namespace, or they can use a Java-based bean configuration.
</para>
<section>
<title>XML namespace</title>
<para>
The XML namespace can be used to configure Spring Data Graph. The <code>config</code> element
provides an XML-based configuration of Spring Data Graph in one line. It has three attributes.
<code>graphDatabaseService</code> points out the Neo4j instance to use. For convenience,
<code>storeDirectory</code> can be set instead of <code>graphDatabaseService</code> to
point to a directory where a new <code>EmbeddedGraphDatabase</code> will be created. For
cross-store configuration, the <code>entityManagerFactory</code> attribute needs to be
configured.
</para>
<example>
<title>XML configuration with store directory</title>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:datagraph="http://www.springframework.org/schema/data/graph"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/data/graph
http://www.springframework.org/schema/data/graph/datagraph-1.0.xsd
">
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:datagraph="http://www.springframework.org/schema/data/graph"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/data/graph
http://www.springframework.org/schema/data/graph/datagraph-1.0.xsd">
<context:annotation-config/>
<datagraph:config storeDirectory="target/config-test"/>
</beans>
]]></programlisting>
<programlisting language="xml"><![CDATA[
<context:annotation-config/>
]]></programlisting>
</example>
<example>
<title>XML configuration with bean</title>
<programlisting language="xml"><![CDATA[<context:annotation-config/>
<bean id="graphDatabaseService" class="org.neo4j.kernel.EmbeddedGraphDatabase"
destroy-method="shutdown">
<constructor-arg index="0" value="target/config-test" />
</bean>
<bean id="graphDatabaseService" class="org.neo4j.kernel.EmbeddedGraphDatabase"
destroy-method="shutdown">
<constructor-arg index="0" value="target/config-test" />
</bean>
<datagraph:config graphDatabaseService="graphDatabaseService"/>
]]></programlisting>
<datagraph:config graphDatabaseService="graphDatabaseService"/>
]]></programlisting>
</example>
<example>
<title>XML configuration with cross-store</title>
<programlisting language="xml"><![CDATA[<context:annotation-config/>
<programlisting language="xml"><![CDATA[
<context:annotation-config/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>
</bean>
<datagraph:config storeDirectory="target/config-test"
entityManagerFactory="entityManagerFactory"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"
id="entityManagerFactory">
<property name="dataSource" ref="dataSource"/>
<property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>
</bean>
]]></programlisting>
<datagraph:config storeDirectory="target/config-test"
entityManagerFactory="entityManagerFactory"/>
]]></programlisting>
</example>
</section>
<section>
<title>Java based Configuration</title>
<title>Java-based bean configuration</title>
<para>
You can also configure Spring Data Graph using Java based bean metadata.<note>
<para>For those not familiar with how to configure the Spring
container using Java based bean metadata instead of XML based metadata
see the high level introduction in the reference docs <ulink
url="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/new-in-3.html#new-java-configuration"
userlevel="">here</ulink> as well as the detailed documentation <ulink
url="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java-instantiating-container">here</ulink>.</para>
</note>
To help configure Spring Data Graph using Java based bean metadata the class <code>Neo4jConfiguration</code> is registerd with the context either explicitly in the XML config or via classpath scanning for classes that have the @Configuration annotation. The only thing that must be provided in addition is the <code>GraphDatabaseService</code> configured with a datastore directory. The example below shows using XML to register the <code>Neo4jConfiguration</code> @Configuration class as well as Spring's <code>ConfigurationClassPostProcessor</code> that transforms the @Configuration class to bean definitions.
<programlisting language="xml"><![CDATA[
<beans>
...
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.data.graph.neo4j.config.Neo4jConfiguration"/>
<bean class="org.springframework.context.annotation.ConfigurationClassPostProcessor"/>
<bean id="graphDatabaseService" class="org.neo4j.kernel.EmbeddedGraphDatabase"
destroy-method="shutdown" scope="singleton">
<constructor-arg index="0" value="target/config-test"/>
</bean>
...
</beans>
]]></programlisting>
You can also configure Spring Data Graph using Java-based bean metadata.
</para>
<note>
<para>
For those not familiar with Java-based bean metadata in Spring, we recommend that you
read up on it first. The Spring documentation has a
<ulink url="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/new-in-3.html#new-java-configuration" userlevel="">high-level introduction</ulink>
as well as
<ulink url="http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/beans.html#beans-java-instantiating-container">detailed documentation</ulink>
on it.
</para>
</note>
<para>
In order to configure Spring Data Graph with Java-based bean metadata, the class
<code>Neo4jConfiguration</code> is registered with the context. This is either done
explicitly in the context configuration, or via classpath scanning for classes that
have the @Configuration annotation. The only thing that must be provided is the
<code>GraphDatabaseService</code>. The example below shows how to register the
<code>@Configuration Neo4jConfiguration</code> class, as well as Spring's
<code>ConfigurationClassPostProcessor</code> that transforms the
<code>@Configuration</code> class to bean definitions.
<example>
<title>Java-based bean configuration</title>
<programlisting language="xml"><![CDATA[<beans ...>
...
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.data.graph.neo4j.config.Neo4jConfiguration"/>
<bean class="org.springframework.context.annotation.ConfigurationClassPostProcessor"/>
<bean id="graphDatabaseService" class="org.neo4j.kernel.EmbeddedGraphDatabase"
destroy-method="shutdown" scope="singleton">
<constructor-arg index="0" value="target/config-test"/>
</bean>
...
</beans>
]]></programlisting>
</example>
</para>
</section>
</section>
</chapter>

View File

@@ -6,6 +6,6 @@
<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.
databases. Mark Pollack, the author of Spring.NET, is the project lead for the Spring Data project.
</para>
</chapter>

View File

@@ -1,24 +1,26 @@
<?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>
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>
<title>Neo4jTemplate</title>
<para>
The <code>Neo4jTemplate</code> offers the convenient API of Spring templates for the Neo4j graph
database.
</para>
<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.
For direct retrieval of nodes and relationships, the <code>getReferenceNode()</code>,
<code>getNode()</code> and <code>getRelationship()</code> methods can be used.
</para>
<para>
There are methods (<code>createNode</code> and <code>createRelationship</code>) for creating nodes and
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);
<example>
<title>Neo4j template</title>
<programlisting language="java"><![CDATA[import static org.springframework.data.graph.core.Property._;
Neo4jOperations neo = new Neo4jTemplate(graphDatabaseService);
Node michael = neo.createNode(_("name","Michael"));
Node mark = neo.createNode(_("name","Mark"));
@@ -30,60 +32,60 @@ neo.index("devs",thomas, "name","Thomas");
assert "Mark".equals(neo.query("devs","name","Mark",new NodeNamePathMapper()));
]]></programlisting>
</para>
</example>
</section>
<section>
<title>Indexing</title>
<para>
Adding nodes and relationships to an index is achieved using the <code>index</code> method.
Adding nodes and relationships to an index is done with the <code>index()</code> method.
</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.
The <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>
<title>Graph 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.
The 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 neighbors
of the start node, filtering the relationships according to the 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.
The <code>traverse()</code> method covers the full traversal operation that takes a
<code>TraversalDescription</code> (typically built with the <code>Traversal.description()</code>
DSL) and runs it from the start node. Each path that is returned by the traversal is passed to the
<code>PathMapper</code> to be converted into the desired type.
</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.
comes from Neo4j. Much like a result set, a path contains a chain of <code>nodes()</code> connected by
<code>relationships()</code>, starting at a <code>startNode()</code> and ending at 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.
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.
With <code>EntityPath</code> and <code>EntityMapper</code> there is also support for using
node entities within the <code>Path</code> and <code>PathMapper</code> constructs.
</para>
</section>
<section>
<title>Transaction handling/management</title>
<title>Transactions</title>
<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.
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 <code>@Transactional</code>
or the <code>TransactionTemplate</code>.
</para>
</section>
</chapter>

View File

@@ -29,8 +29,7 @@
<para>
<example>
<title>First test case</title>
<programlisting language="java" ><![CDATA[
@Autowired GraphDatabaseContext graphDatabaseContext;
<programlisting language="java" ><![CDATA[@Autowired GraphDatabaseContext graphDatabaseContext;
@Test public void persistedMovieShouldBeRetrievableFromGraphDb() {
Movie forrestGump = new Movie("Forrest Gump", 1994).persist();
@@ -52,8 +51,7 @@
Our domain model had now evolved.
<example>
<title>Movie class</title>
<programlisting language="java"><![CDATA[
@NodeEntity
<programlisting language="java"><![CDATA[@NodeEntity
class Movie {
int id;
String title;

View File

@@ -24,8 +24,7 @@
<para>
<example>
<title>Domain model</title>
<programlisting lang="java" language="java" role="java" ><![CDATA[
class Movie {
<programlisting lang="java" language="java" role="java" ><![CDATA[class Movie {
int id;
String title;
int year;

View File

@@ -12,8 +12,7 @@
<para>
<example>
<title>JSON movie response</title>
<programlisting language="javascript" ><![CDATA[
[{"popularity":3,
<programlisting language="javascript" ><![CDATA[[{"popularity":3,
"translated":true, "adult":false, "language":"en",
"original_name":"[Rec]", "name":"[Rec]", "alternative_name":"[REC]",
"movie_type":"movie",
@@ -60,8 +59,7 @@
</example>
<example>
<title>JSON actor response</title>
<programlisting language="javascript" ><![CDATA[
[{"popularity":3,
<programlisting language="javascript" ><![CDATA[[{"popularity":3,
"name":"Glenn Strange", "known_as":[{"name":"George Glenn Strange"}, {"name":"Glen Strange"},
{"name":"Glen 'Peewee' Strange"}, {"name":"Peewee Strange"}, {"name":"'Peewee' Strange"}],
"id":30112,
@@ -96,8 +94,7 @@
<para>
<example>
<title>Importing the data</title>
<programlisting language="java" ><![CDATA[
@Transactional
<programlisting language="java" ><![CDATA[@Transactional
public Movie importMovie(String movieId) {
Movie movie = repository.getMovie(movieId);
if (movie == null) { // Not found: Create fresh

View File

@@ -12,8 +12,7 @@
<para>
<example>
<title>Exact Indexing for Movie id</title>
<programlisting language="java" ><![CDATA[
@NodeEntity class Movie {
<programlisting language="java" ><![CDATA[@NodeEntity class Movie {
@Indexed int id;
String title;
int year;

View File

@@ -29,8 +29,7 @@
<para>
<example>
<title>Neo4j Maven dependency</title>
<programlisting language="xml" ><![CDATA[
<dependency>
<programlisting language="xml" ><![CDATA[<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
<version>1.3.M05</version>
@@ -41,8 +40,7 @@
<para>
<example>
<title>Neo4j core API (transaction code omitted)</title>
<programlisting language="java" ><![CDATA[
enum RelationshipTypes implements RelationshipType { ACTS_IN };
<programlisting language="java" ><![CDATA[enum RelationshipTypes implements RelationshipType { ACTS_IN };
GraphDatabaseService gds = new EmbeddedGraphDatabase("/path/to/store");
Node forrest=gds.createNode();

View File

@@ -20,8 +20,7 @@
<para>
<example>
<title>Recommendations</title>
<programlisting language="java"><![CDATA[
public Map<Movie,Integer> recommendMovies(User user, final int ratingDistance) {
<programlisting language="java"><![CDATA[public Map<Movie,Integer> recommendMovies(User user, final int ratingDistance) {
final DynamicRelationshipType RATED = withName(User.RATED);
final Map<Long,int[]> ratings=new HashMap<Long, int[]>();
TraversalDescription traversal= Traversal.description().breadthFirst()

View File

@@ -19,8 +19,7 @@
<para>
<example>
<title>Role class</title>
<programlisting language="java"><![CDATA[
@RelationshipEntity
<programlisting language="java"><![CDATA[@RelationshipEntity
class Role {
@StartNode Actor actor;
@EndNode Movie movie;
@@ -40,8 +39,7 @@ class Role {
<para>
<example>
<title>Relating actors to movies</title>
<programlisting language="java" ><![CDATA[
class Actor {
<programlisting language="java" ><![CDATA[class Actor {
...
public Role playedIn(Movie movie, String roleName) {
Role role = relateTo(movie, Role.class, "ACTS_IN");
@@ -65,8 +63,7 @@ class Actor {
<para>
<example>
<title>@RelatedTo usage</title>
<programlisting language="java" ><![CDATA[
@NodeEntity
<programlisting language="java" ><![CDATA[@NodeEntity
class Movie {
@Indexed int id;
String title;
@@ -80,7 +77,7 @@ class Actor {
@Indexed int id;
String name;
@RelatedTo(elementClass = Movie.class, type = "ACTS_IN")
Set<Movie> cast;
Set<Movie> movies;
public Role playedIn(Movie movie, String roleName) {
Role role = relateTo(movie, Role.class, "ACTS_IN");
@@ -115,8 +112,7 @@ class Actor {
<para>
<example>
<title>@RelatedToVia usage</title>
<programlisting language="java" ><![CDATA[
@NodeEntity
<programlisting language="java" ><![CDATA[@NodeEntity
class Movie {
@Indexed int id;
String title;

View File

@@ -9,16 +9,14 @@
work with a named interface rather than different versions of a generic one.
<example>
<title>Movie repository</title>
<programlisting language="java"><![CDATA[
package org.neo4j.cineasts.repository;
<programlisting language="java"><![CDATA[package org.neo4j.cineasts.repository;
public interface MovieRepository extends GraphRepository<Movie> {}
]]></programlisting>
</example>
Then we added it to the Spring context configuration by simply adding:
<example>
<title>Repository context configuration</title>
<programlisting language="xml"><![CDATA[
<datagraph:repositories base-package="org.neo4j.cineasts.repository"/>
<programlisting language="xml"><![CDATA[<datagraph:repositories base-package="org.neo4j.cineasts.repository"/>
]]></programlisting>
</example>
We then created the domain-specific repository class, annotating it with <code>@Repository</code> and
@@ -27,8 +25,7 @@ public interface MovieRepository extends GraphRepository<Movie> {}
<para>
<example>
<title>Domain-specific repository</title>
<programlisting language="java"><![CDATA[
@Repository @Transactional
<programlisting language="java"><![CDATA[@Repository @Transactional
public class CineastsRepostory {
@Autowired MovieRepository movieRepository;

View File

@@ -17,8 +17,7 @@
<para>
<example>
<title>Populating the database - Controller</title>
<programlisting language="java"><![CDATA[
@Service
<programlisting language="java"><![CDATA[@Service
public class DatabasePopulator {
@Autowired GraphDatabaseContext ctx;
@@ -54,8 +53,7 @@ public class MovieController {
</example>
<example>
<title>Populating the database - JSP</title>
<programlisting language="jsp"><![CDATA[
<%@ page session="false" %>
<programlisting language="jsp"><![CDATA[<%@ page session="false" %>
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
@@ -119,8 +117,7 @@ public class MovieController {
<para>
<example>
<title>Starting the Neo4j Shell</title>
<programlisting language="shell" ><![CDATA[
neo4j-shell -readonly -path data/graph.db
<programlisting language="shell" ><![CDATA[neo4j-shell -readonly -path data/graph.db
]]></programlisting>
</example>
</para>
@@ -132,8 +129,7 @@ neo4j-shell -readonly -path data/graph.db
<para>
<example>
<title>Neo4j Shell usage</title>
<programlisting language="shell" ><![CDATA[
neo4j-sh[readonly] (0)$ help
<programlisting language="shell" ><![CDATA[neo4j-sh[readonly] (0)$ help
Available commands: index dbinfo ls rm alias set eval mv gsh env rmrel mkrel
trav help pwd paths ... man cd
Use man <command> for info about each command.

View File

@@ -15,8 +15,7 @@
<para>
<example>
<title>Spring Security pom.xml</title>
<programlisting language="xml" ><![CDATA[
<dependency>
<programlisting language="xml" ><![CDATA[<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.version}</version>
@@ -32,8 +31,7 @@
<para>
<example>
<title>Spring Security web.xml</title>
<programlisting language="xml" ><![CDATA[
<context-param>
<programlisting language="xml" ><![CDATA[<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext-security.xml
@@ -60,8 +58,7 @@
<para>
<example>
<title>Spring Security applicationContext-security.xml</title>
<programlisting language="xml" ><![CDATA[
<security:global-method-security secured-annotations="enabled">
<programlisting language="xml" ><![CDATA[<security:global-method-security secured-annotations="enabled">
</security:global-method-security>
<security:http auto-config="true" access-denied-page="/auth/denied"> <!-- use-expressions="true" -->
@@ -89,8 +86,7 @@
</example>
<example>
<title>UserDetailsService and UserDetails implementation</title>
<programlisting language="java" ><![CDATA[
@Service
<programlisting language="java" ><![CDATA[@Service
public class CineastsUserDetailsService implements UserDetailsService, InitializingBean {
@Autowired private UserRepository userRepository;

View File

@@ -32,8 +32,7 @@
<para>
<example>
<title>Project pom.xml</title>
<programlisting language="xml"><![CDATA[
<properties>
<programlisting language="xml"><![CDATA[<properties>
<spring.version>3.0.5.RELEASE</spring.version>
</properties>
@@ -69,8 +68,7 @@
<example>
<title>Project web.xml</title>
<programlisting language="xml"><![CDATA[
<listener>
<programlisting language="xml"><![CDATA[<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
@@ -99,8 +97,7 @@
<para>
<example>
<title>Project applicationContext.xml</title>
<programlisting language="xml"><![CDATA[
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<programlisting language="xml"><![CDATA[<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
@@ -124,8 +121,7 @@
</example>
<example>
<title>Project dispatcherServlet-servlet.xml</title>
<programlisting language="xml"><![CDATA[
<mvc:annotation-driven/>
<programlisting language="xml"><![CDATA[<mvc:annotation-driven/>
<mvc:resources mapping="/images/**" location="/images/"/>
<mvc:resources mapping="/resources/**" location="/resources/"/>
<context:component-scan base-package="org.neo4j.cineasts.controller"/>

View File

@@ -18,8 +18,7 @@
<para>
<example>
<title>Social entities</title>
<programlisting language="java" ><![CDATA[
@NodeEntity
<programlisting language="java" ><![CDATA[@NodeEntity
class User {
@Indexed String login;
String name;
@@ -59,8 +58,7 @@ class Rating {
<para>
<example>
<title>Populate users and ratings</title>
<programlisting language="java" ><![CDATA[
@Transactional
<programlisting language="java" ><![CDATA[@Transactional
public List<Movie> populateDatabase() {
Actor tomHanks = new Actor("1", "Tom Hanks").persist();
Movie forestGump = new Movie("1", "Forrest Gump").persist();
@@ -88,8 +86,7 @@ public List<Movie> populateDatabase() {
<para>
<example>
<title>Getting the rating of a movie</title>
<programlisting language="java" ><![CDATA[
class Movie {
<programlisting language="java" ><![CDATA[class Movie {
...
@RelatedToVia(elementClass=Rating.class, type="RATED", direction = Direction.INCOMING)

View File

@@ -18,9 +18,7 @@
The first step was to configure Maven:
<example>
<title>Spring Data Graph Maven configuration</title>
<programlisting language="xml"><![CDATA[
<properties>
<programlisting language="xml"><![CDATA[<properties>
<aspectj.version>1.6.11.RELEASE</aspectj.version>
</properties>
@@ -85,8 +83,7 @@
<para>
<example>
<title>Spring Data Graph context configuration</title>
<programlisting language="xml"><![CDATA[
<beans xmlns="http://www.springframework.org/schema/beans" ...
<programlisting language="xml"><![CDATA[<beans xmlns="http://www.springframework.org/schema/beans" ...
xmlns:datagraph="http://www.springframework.org/schema/data/graph"
xsi:schemaLocation="... http://www.springframework.org/schema/data/graph
http://www.springframework.org/schema/data/graph/datagraph-1.0.xsd">

View File

@@ -12,8 +12,7 @@
<para>
<example>
<title>Controller for showing movies</title>
<programlisting language="java"><![CDATA[
@RequestMapping(value = "/movies/{movieId}", method = RequestMethod.GET, headers = "Accept=text/html")
<programlisting language="java"><![CDATA[@RequestMapping(value = "/movies/{movieId}", method = RequestMethod.GET, headers = "Accept=text/html")
public String singleMovieView(final Model model, @PathVariable String movieId) {
Movie movie = repository.getMovie(movieId);
model.addAttribute("id", movieId);
@@ -51,8 +50,7 @@ public String singleMovieView(final Model model, @PathVariable String movieId) {
<para>
<example>
<title>Searching for movies</title>
<programlisting language="java"><![CDATA[
public class CineastRepository {
<programlisting language="java"><![CDATA[public class CineastRepository {
....
public void List<Movie> findMovies(String query, int count) {
List<Movie> movies=new ArrayList<Movie>(count);
@@ -79,8 +77,7 @@ public class CineastRepository {
<para>
<example>
<title>Search controller</title>
<programlisting language="java"><![CDATA[
@RequestMapping(value = "/movies", method = RequestMethod.GET, headers = "Accept=text/html")
<programlisting language="java"><![CDATA[@RequestMapping(value = "/movies", method = RequestMethod.GET, headers = "Accept=text/html")
public String findMovies(Model model, @RequestParam("q") String query) {
List<Movie> movies = repository.findMovies(query, 20);
model.addAttribute("movies", movies);
@@ -93,8 +90,7 @@ public String findMovies(Model model, @RequestParam("q") String query) {
<para>
<example>
<title>Search Results JSP</title>
<programlisting language="jsp" ><![CDATA[
<h2>Movies</h2>
<programlisting language="jsp" ><![CDATA[<h2>Movies</h2>
<c:choose>
<c:when test="${not empty movies}">