merge documentation updates
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
I’m excited about Spring Data Graph for several reasons.
|
||||
</para>
|
||||
<para>
|
||||
<para>
|
||||
I’m 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. It’s 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 today’s Java
|
||||
technologies.
|
||||
</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
|
||||
</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. I’m
|
||||
sure the vast majority of my code has long since been replaced (probably for the better) by coders who aren’t
|
||||
early in 2010. This led to a prototype of what became Spring Data Graph — at times written paired with Emil. I’m
|
||||
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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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<T></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<T></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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"/>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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}">
|
||||
|
||||
Reference in New Issue
Block a user