├── .gitignore
├── README.md
├── pom.xml
└── v4.1.1
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── ambergarden
│ │ └── samples
│ │ └── neo4j
│ │ ├── GraphDBConfiguration.java
│ │ ├── entities
│ │ ├── Book.java
│ │ ├── Person.java
│ │ ├── base
│ │ │ ├── AbstractEntity.java
│ │ │ ├── DescriptiveEntity.java
│ │ │ └── NamedEntity.java
│ │ └── relationships
│ │ │ └── WriterOf.java
│ │ └── repositories
│ │ ├── BookRepository.java
│ │ └── PersonRepository.java
└── resources
│ └── META-INF
│ └── spring
│ └── db
│ └── dal-neo4j-context.xml
└── test
├── java
└── com
│ └── ambergarden
│ └── samples
│ └── neo4j
│ └── repositories
│ ├── BookRepositoryTest.java
│ └── PersonRepositoryTest.java
└── resources
└── spring
└── dal-test-context.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | .settings
3 | .project
4 | .classpath
5 | *.iml
6 | *~
7 | \#*#
8 | build
9 | target
10 | .springBeans
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Spring Data Neo4J Sample Project
2 | This is a small project which shows how to use Spring Data Neo4J.
3 |
4 | Neo4J is a well-known graph database. Spring Data Neo4J is a Spring project which allows users to use annotations and Spring Data conventions to operate Neo4J. It is always a good choice if you want to use Neo4J in a Spring-based project.
5 |
6 | They both grow rapidly. As a result, toturals and samples for Spring Neo4J quickly turns to be outdated.
7 |
8 | In this repository, we will try to demonstrate the usage, in a versionized style.
9 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 4.0.0
4 |
5 | com.ambergarden.samples.neo4j
6 | parent
7 | pom
8 | ${project.version}
9 |
10 |
11 | v4.1.1
12 |
13 |
14 |
15 | 0.1.0-BUILD-SNAPSHOT
16 | 1.7
17 | 4.2.5.RELEASE
18 | 4.1.1.RELEASE
19 | 2.0.1
20 | 4.9
21 |
22 |
23 |
--------------------------------------------------------------------------------
/v4.1.1/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 |
7 | com.ambergarden.samples.neo4j
8 | parent
9 | ${project.version}
10 | ../
11 |
12 |
13 | version-4.1.1
14 | jar
15 |
16 |
17 |
18 | org.neo4j
19 | neo4j-ogm-embedded-driver
20 | ${ogm.version}
21 |
22 |
23 | org.springframework
24 | spring-test
25 | ${spring.version}
26 |
27 |
28 | junit
29 | junit
30 | ${junit.version}
31 |
32 |
33 | org.springframework.data
34 | spring-data-neo4j
35 | ${spring.data.neo4j.version}
36 |
37 |
38 |
--------------------------------------------------------------------------------
/v4.1.1/src/main/java/com/ambergarden/samples/neo4j/GraphDBConfiguration.java:
--------------------------------------------------------------------------------
1 | package com.ambergarden.samples.neo4j;
2 |
3 | import org.neo4j.ogm.session.SessionFactory;
4 | import org.springframework.context.annotation.Bean;
5 | import org.springframework.context.annotation.Configuration;
6 | import org.springframework.data.neo4j.config.Neo4jConfiguration;
7 | import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
8 | import org.springframework.transaction.annotation.EnableTransactionManagement;
9 |
10 | /**
11 | * Spring JavaConfig configuration class to setup a Spring container and infrastructure components.
12 | */
13 | @Configuration
14 | @EnableNeo4jRepositories(basePackages = "com.ambergarden.samples.neo4j.repositories")
15 | @EnableTransactionManagement
16 | public class GraphDBConfiguration extends Neo4jConfiguration {
17 |
18 | @Bean
19 | public org.neo4j.ogm.config.Configuration getConfiguration() {
20 | org.neo4j.ogm.config.Configuration config =
21 | new org.neo4j.ogm.config.Configuration();
22 | // TODO: Temporary uses the embedded driver. We need to switch to http
23 | // driver. Then we can horizontally scale neo4j
24 | config.driverConfiguration()
25 | .setDriverClassName("org.neo4j.ogm.drivers.embedded.driver.EmbeddedDriver")
26 | .setURI("file:/D:/neo4j/graph.db/");
27 | return config;
28 | }
29 |
30 | @Override
31 | @Bean
32 | public SessionFactory getSessionFactory() {
33 | // Return the session factory which also includes the persistent entities
34 | return new SessionFactory(getConfiguration(), "com.ambergarden.samples.neo4j.entities");
35 | }
36 | }
--------------------------------------------------------------------------------
/v4.1.1/src/main/java/com/ambergarden/samples/neo4j/entities/Book.java:
--------------------------------------------------------------------------------
1 | package com.ambergarden.samples.neo4j.entities;
2 |
3 | import java.util.Set;
4 |
5 | import org.neo4j.ogm.annotation.NodeEntity;
6 | import org.neo4j.ogm.annotation.Relationship;
7 |
8 | import com.ambergarden.samples.neo4j.entities.base.DescriptiveEntity;
9 | import com.ambergarden.samples.neo4j.entities.relationships.WriterOf;
10 |
11 | /**
12 | * Entity which represents a book
13 | */
14 | @NodeEntity
15 | public class Book extends DescriptiveEntity {
16 | @Relationship(type="WRITER_OF", direction=Relationship.INCOMING)
17 | private Set writers;
18 |
19 | @Relationship(type="READER_OF", direction=Relationship.INCOMING)
20 | private Set readers;
21 |
22 | public Set getWriters() {
23 | return writers;
24 | }
25 |
26 | public void setWriters(Set writers) {
27 | this.writers = writers;
28 | }
29 |
30 | public Set getReaders() {
31 | return readers;
32 | }
33 |
34 | public void setReaders(Set readers) {
35 | this.readers = readers;
36 | }
37 | }
--------------------------------------------------------------------------------
/v4.1.1/src/main/java/com/ambergarden/samples/neo4j/entities/Person.java:
--------------------------------------------------------------------------------
1 | package com.ambergarden.samples.neo4j.entities;
2 |
3 | import java.util.Set;
4 |
5 | import org.neo4j.ogm.annotation.NodeEntity;
6 | import org.neo4j.ogm.annotation.Relationship;
7 |
8 | import com.ambergarden.samples.neo4j.entities.base.NamedEntity;
9 | import com.ambergarden.samples.neo4j.entities.relationships.WriterOf;
10 |
11 | /**
12 | * Entity which represents a person
13 | */
14 | @NodeEntity
15 | public class Person extends NamedEntity {
16 | @Relationship(type="WRITER_OF")
17 | private Set writings;
18 |
19 | @Relationship(type="READER_OF")
20 | private Set books;
21 |
22 | public Set getWritings() {
23 | return writings;
24 | }
25 |
26 | public void setWritings(Set writings) {
27 | this.writings = writings;
28 | }
29 |
30 | public Set getBooks() {
31 | return books;
32 | }
33 |
34 | public void setBooks(Set books) {
35 | this.books = books;
36 | }
37 | }
--------------------------------------------------------------------------------
/v4.1.1/src/main/java/com/ambergarden/samples/neo4j/entities/base/AbstractEntity.java:
--------------------------------------------------------------------------------
1 | package com.ambergarden.samples.neo4j.entities.base;
2 |
3 | import org.neo4j.ogm.annotation.GraphId;
4 |
5 | /**
6 | * The abstract entity which contains the basic fields such
7 | * as id, hashCode and equals function
8 | */
9 | public abstract class AbstractEntity {
10 |
11 | @GraphId
12 | private Long id;
13 |
14 | public Long getId() {
15 | return id;
16 | }
17 |
18 | public void setId(Long id) {
19 | this.id = id;
20 | }
21 |
22 | @Override
23 | public boolean equals(Object obj) {
24 | if (this == obj) {
25 | return true;
26 | }
27 |
28 | if (obj == null) {
29 | return false;
30 | }
31 |
32 | if (getClass() != obj.getClass()) {
33 | return false;
34 | }
35 |
36 | if (this.id == null) {
37 | // For newly created entity, id will be null
38 | return false;
39 | }
40 |
41 | AbstractEntity entity = (AbstractEntity) obj;
42 | return this.id.equals(entity.id);
43 | }
44 |
45 | @Override
46 | public int hashCode() {
47 | return id == null ? super.hashCode() : id.hashCode();
48 | }
49 | }
--------------------------------------------------------------------------------
/v4.1.1/src/main/java/com/ambergarden/samples/neo4j/entities/base/DescriptiveEntity.java:
--------------------------------------------------------------------------------
1 | package com.ambergarden.samples.neo4j.entities.base;
2 |
3 | import org.neo4j.ogm.annotation.NodeEntity;
4 |
5 | /**
6 | * The abstract entity which represents an entity with a description
7 | */
8 | @NodeEntity
9 | public abstract class DescriptiveEntity extends NamedEntity {
10 | private String description;
11 |
12 | public String getDescription() {
13 | return description;
14 | }
15 |
16 | public void setDescription(String description) {
17 | this.description = description;
18 | }
19 | }
--------------------------------------------------------------------------------
/v4.1.1/src/main/java/com/ambergarden/samples/neo4j/entities/base/NamedEntity.java:
--------------------------------------------------------------------------------
1 | package com.ambergarden.samples.neo4j.entities.base;
2 |
3 | import org.neo4j.ogm.annotation.NodeEntity;
4 |
5 | /**
6 | * The abstract entity which represents an entity with a name
7 | */
8 | @NodeEntity
9 | public abstract class NamedEntity extends AbstractEntity {
10 | private String name;
11 |
12 | public String getName() {
13 | return name;
14 | }
15 |
16 | public void setName(String name) {
17 | this.name = name;
18 | }
19 | }
--------------------------------------------------------------------------------
/v4.1.1/src/main/java/com/ambergarden/samples/neo4j/entities/relationships/WriterOf.java:
--------------------------------------------------------------------------------
1 | package com.ambergarden.samples.neo4j.entities.relationships;
2 |
3 | import java.util.Date;
4 |
5 | import org.neo4j.ogm.annotation.EndNode;
6 | import org.neo4j.ogm.annotation.RelationshipEntity;
7 | import org.neo4j.ogm.annotation.StartNode;
8 |
9 | import com.ambergarden.samples.neo4j.entities.Book;
10 | import com.ambergarden.samples.neo4j.entities.Person;
11 | import com.ambergarden.samples.neo4j.entities.base.AbstractEntity;
12 |
13 | @RelationshipEntity(type="WRITER_OF")
14 | public class WriterOf extends AbstractEntity {
15 | @StartNode
16 | private Person writer;
17 |
18 | @EndNode
19 | private Book book;
20 |
21 | private Date startDate;
22 |
23 | private Date endDate;
24 |
25 | public Person getWriter() {
26 | return writer;
27 | }
28 |
29 | public void setWriter(Person writer) {
30 | this.writer = writer;
31 | }
32 |
33 | public Book getBook() {
34 | return book;
35 | }
36 |
37 | public void setBook(Book book) {
38 | this.book = book;
39 | }
40 |
41 | public Date getStartDate() {
42 | return startDate;
43 | }
44 |
45 | public void setStartDate(Date startDate) {
46 | this.startDate = startDate;
47 | }
48 |
49 | public Date getEndDate() {
50 | return endDate;
51 | }
52 |
53 | public void setEndDate(Date endDate) {
54 | this.endDate = endDate;
55 | }
56 | }
--------------------------------------------------------------------------------
/v4.1.1/src/main/java/com/ambergarden/samples/neo4j/repositories/BookRepository.java:
--------------------------------------------------------------------------------
1 | package com.ambergarden.samples.neo4j.repositories;
2 |
3 | import org.springframework.data.neo4j.repository.GraphRepository;
4 |
5 | import com.ambergarden.samples.neo4j.entities.Book;
6 |
7 | /**
8 | * The repository to perform CRUD operations on book entities
9 | */
10 | public interface BookRepository extends GraphRepository {
11 | }
--------------------------------------------------------------------------------
/v4.1.1/src/main/java/com/ambergarden/samples/neo4j/repositories/PersonRepository.java:
--------------------------------------------------------------------------------
1 | package com.ambergarden.samples.neo4j.repositories;
2 |
3 | import org.springframework.data.neo4j.repository.GraphRepository;
4 |
5 | import com.ambergarden.samples.neo4j.entities.Person;
6 |
7 | /**
8 | * The repository to perform CRUD operations on person entities
9 | */
10 | public interface PersonRepository extends GraphRepository {
11 | }
--------------------------------------------------------------------------------
/v4.1.1/src/main/resources/META-INF/spring/db/dal-neo4j-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
10 |
12 |
13 |
--------------------------------------------------------------------------------
/v4.1.1/src/test/java/com/ambergarden/samples/neo4j/repositories/BookRepositoryTest.java:
--------------------------------------------------------------------------------
1 | package com.ambergarden.samples.neo4j.repositories;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNotNull;
5 | import static org.junit.Assert.assertNull;
6 |
7 | import java.util.Date;
8 | import java.util.HashSet;
9 | import java.util.Set;
10 |
11 | import org.junit.Test;
12 | import org.junit.runner.RunWith;
13 | import org.springframework.beans.factory.annotation.Autowired;
14 | import org.springframework.test.context.ContextConfiguration;
15 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
16 |
17 | import com.ambergarden.samples.neo4j.entities.Book;
18 | import com.ambergarden.samples.neo4j.entities.Person;
19 | import com.ambergarden.samples.neo4j.entities.relationships.WriterOf;
20 |
21 | @RunWith(SpringJUnit4ClassRunner.class)
22 | @ContextConfiguration({ "classpath*:/spring/dal-test-context.xml" })
23 | public class BookRepositoryTest {
24 | private static String TEST_PERSON_NAME_1 = "Person1";
25 |
26 | private static String TEST_BOOK_NAME_1 = "Book1";
27 | private static String TEST_BOOK_NAME_2 = "Book2";
28 |
29 | @Autowired
30 | private PersonRepository personRepository;
31 |
32 | @Autowired
33 | private BookRepository bookRepository;
34 |
35 | @Test
36 | public void testCRUDBook() {
37 | Book book = new Book();
38 | book.setName(TEST_BOOK_NAME_1);
39 | book = bookRepository.save(book);
40 | assertNotNull(book);
41 | assertNotNull(book.getId());
42 | assertEquals(TEST_BOOK_NAME_1, book.getName());
43 |
44 | Long originalId = book.getId();
45 | book.setName(TEST_BOOK_NAME_2);
46 | book = bookRepository.save(book);
47 | assertEquals(originalId, book.getId());
48 | assertEquals(TEST_BOOK_NAME_2, book.getName());
49 |
50 | bookRepository.delete(book);
51 | book = bookRepository.findOne(originalId);
52 | assertNull(book);
53 | }
54 |
55 | @Test
56 | public void testCRUDRelationships() {
57 | Person person1 = new Person();
58 | person1.setName(TEST_PERSON_NAME_1);
59 | person1 = personRepository.save(person1);
60 |
61 | // Test create with readers
62 | Set readers = new HashSet();
63 | readers.add(person1);
64 |
65 | Set books = new HashSet();
66 | Book book1 = new Book();
67 | books.add(book1);
68 | person1.setBooks(books);
69 |
70 | book1.setName(TEST_BOOK_NAME_1);
71 | book1.setReaders(readers);
72 | book1 = bookRepository.save(book1);
73 | assertNotNull(book1);
74 | assertNotNull(book1.getReaders());
75 | assertEquals(1, book1.getReaders().size());
76 |
77 | // Test add readers
78 | Book book2 = new Book();
79 | book2.setName(TEST_BOOK_NAME_2);
80 | book2 = bookRepository.save(book2);
81 | assertNotNull(book2);
82 | assertNull(book2.getReaders());
83 |
84 | readers = new HashSet();
85 | readers.add(person1);
86 | person1.getBooks().add(book2);
87 | book2.setReaders(readers);
88 | book2 = bookRepository.save(book2);
89 | assertNotNull(book2.getReaders());
90 | assertEquals(1, book2.getReaders().size());
91 |
92 | // Verify that the person entity is in sync
93 | person1 = personRepository.findOne(person1.getId());
94 | assertNotNull(person1.getBooks());
95 | assertEquals(2, person1.getBooks().size());
96 |
97 | // Test remove readers
98 | book2.setReaders(null);
99 | person1.getBooks().remove(book2);
100 | book2 = bookRepository.save(book2);
101 |
102 | person1 = personRepository.findOne(person1.getId());
103 | assertNotNull(person1.getBooks());
104 | assertEquals(1, person1.getBooks().size());
105 |
106 | // Test remove all readers
107 | book1.setReaders(null);
108 | person1.getBooks().remove(book1);
109 | book1 = bookRepository.save(book1);
110 |
111 | person1 = personRepository.findOne(person1.getId());
112 | assertNull(person1.getBooks());
113 | }
114 |
115 | @Test
116 | public void testRichRelationship() {
117 | Date timestamp = new Date();
118 | Person person1 = new Person();
119 | person1.setName(TEST_PERSON_NAME_1);
120 | person1 = personRepository.save(person1);
121 |
122 | // Test create with writers
123 | Book book1 = new Book();
124 | Set writings = new HashSet();
125 | person1.setWritings(writings);
126 |
127 | WriterOf writer = new WriterOf();
128 | writer.setBook(book1);
129 | writer.setWriter(person1);
130 | writer.setStartDate(timestamp);
131 | writer.setEndDate(timestamp);
132 | writings.add(writer);
133 |
134 | book1.setName(TEST_BOOK_NAME_1);
135 | book1.setWriters(writings);
136 | book1 = bookRepository.save(book1);
137 | assertNotNull(book1);
138 | assertNotNull(book1.getWriters());
139 | assertEquals(1, book1.getWriters().size());
140 |
141 | for (WriterOf writerOf : book1.getWriters()) {
142 | assertNotNull(writerOf.getStartDate());
143 | assertNotNull(writerOf.getEndDate());
144 | }
145 | }
146 |
147 | @Test
148 | public void testCRUDRelationshipEntities() {
149 | Person person1 = new Person();
150 | person1.setName(TEST_PERSON_NAME_1);
151 | person1 = personRepository.save(person1);
152 |
153 | // Test create with writers
154 | Book book1 = new Book();
155 | Set writings = new HashSet();
156 | person1.setWritings(writings);
157 |
158 | WriterOf writer = new WriterOf();
159 | writer.setBook(book1);
160 | writer.setWriter(person1);
161 | writings.add(writer);
162 |
163 | book1.setName(TEST_BOOK_NAME_1);
164 | book1.setWriters(writings);
165 | book1 = bookRepository.save(book1);
166 | assertNotNull(book1);
167 | assertNotNull(book1.getWriters());
168 | assertEquals(1, book1.getWriters().size());
169 |
170 | // Test add readers
171 | Book book2 = new Book();
172 | book2.setName(TEST_BOOK_NAME_2);
173 | book2 = bookRepository.save(book2);
174 | assertNotNull(book2);
175 | assertNull(book2.getReaders());
176 |
177 | writings = new HashSet();
178 | writer = new WriterOf();
179 | writer.setBook(book2);
180 | writer.setWriter(person1);
181 | writings.add(writer);
182 |
183 | book2.setWriters(writings);
184 | book2 = bookRepository.save(book2);
185 | assertNotNull(book2.getWriters());
186 | assertEquals(1, book2.getWriters().size());
187 |
188 | // Verify that the person entity is in sync
189 | person1 = personRepository.findOne(person1.getId());
190 | assertNotNull(person1.getWritings());
191 | assertEquals(2, person1.getWritings().size());
192 |
193 | // Test remove writers
194 | person1.getWritings().removeAll(book1.getWriters());
195 | person1.getWritings().removeAll(book2.getWriters());
196 | book2.setWriters(null);
197 | book2 = bookRepository.save(book2);
198 | book1.setWriters(null);
199 | book1 = bookRepository.save(book1);
200 |
201 | person1 = personRepository.findOne(person1.getId());
202 | assertNull(person1.getWritings());
203 | }
204 | }
--------------------------------------------------------------------------------
/v4.1.1/src/test/java/com/ambergarden/samples/neo4j/repositories/PersonRepositoryTest.java:
--------------------------------------------------------------------------------
1 | package com.ambergarden.samples.neo4j.repositories;
2 |
3 | import static org.junit.Assert.assertEquals;
4 | import static org.junit.Assert.assertNotNull;
5 | import static org.junit.Assert.assertNull;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 | import org.springframework.beans.factory.annotation.Autowired;
10 | import org.springframework.test.context.ContextConfiguration;
11 | import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
12 |
13 | import com.ambergarden.samples.neo4j.entities.Person;
14 |
15 | @RunWith(SpringJUnit4ClassRunner.class)
16 | @ContextConfiguration({ "classpath*:/spring/dal-test-context.xml" })
17 | public class PersonRepositoryTest {
18 | private static String TEST_PERSON_NAME_1 = "Person1";
19 | private static String TEST_PERSON_NAME_2 = "Person2";
20 |
21 | @Autowired
22 | private PersonRepository personRepository;
23 |
24 | @Test
25 | public void testCRUDPerson() {
26 | Person person = new Person();
27 | person.setName(TEST_PERSON_NAME_1);
28 | person = personRepository.save(person);
29 | assertNotNull(person);
30 | assertNotNull(person.getId());
31 | assertEquals(TEST_PERSON_NAME_1, person.getName());
32 |
33 | Long originalId = person.getId();
34 | person.setName(TEST_PERSON_NAME_2);
35 | person = personRepository.save(person);
36 | assertEquals(originalId, person.getId());
37 | assertEquals(TEST_PERSON_NAME_2, person.getName());
38 |
39 | personRepository.delete(person);
40 | person = personRepository.findOne(originalId);
41 | assertNull(person);
42 | }
43 | }
--------------------------------------------------------------------------------
/v4.1.1/src/test/resources/spring/dal-test-context.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
--------------------------------------------------------------------------------