Merge branch 'master' of github.com:SpringSource/spring-data-neo4j
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
*.hprof*
|
||||
ajcore*
|
||||
.project
|
||||
.classpath
|
||||
|
||||
@@ -62,8 +62,14 @@ public interface NodeBacked extends GraphBacked<Node,NodeBacked> {
|
||||
* @param target other entity
|
||||
* @param relationshipClass relationship entity class
|
||||
* @param relationshipType type of relationship to be created
|
||||
* @param allowDuplicates duplication relationships of the same type are allowed between two entities
|
||||
* @return relationship entity of specified relationshipClass
|
||||
*/
|
||||
<R extends RelationshipBacked, N extends NodeBacked> R relateTo(N target, Class<R> relationshipClass, String relationshipType,boolean allowDuplicates);
|
||||
|
||||
/**
|
||||
* delegates to relateTo with allowDuplicates set to false
|
||||
*/
|
||||
<R extends RelationshipBacked, N extends NodeBacked> R relateTo(N target, Class<R> relationshipClass, String relationshipType);
|
||||
|
||||
|
||||
@@ -151,7 +157,12 @@ public interface NodeBacked extends GraphBacked<Node,NodeBacked> {
|
||||
*
|
||||
* @param target entity
|
||||
* @param type neo4j relationship type for the underlying relationship
|
||||
* @param allowDuplicates duplication relationships of the same type are allowed between two entities
|
||||
* @return the newly created relationship to the target node
|
||||
*/
|
||||
Relationship relateTo(NodeBacked target, String type, boolean allowDuplicates);
|
||||
/**
|
||||
* delegates to relateTo with allowDuplicates set to false
|
||||
*/
|
||||
Relationship relateTo(NodeBacked target, String type);
|
||||
}
|
||||
|
||||
@@ -162,11 +162,16 @@ public privileged aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMix
|
||||
}
|
||||
|
||||
public Relationship NodeBacked.relateTo(NodeBacked target, String type) {
|
||||
return this.relateTo(target,type,false);
|
||||
}
|
||||
public Relationship NodeBacked.relateTo(NodeBacked target, String type, boolean allowDuplicates) {
|
||||
if (target==null) throw new IllegalArgumentException("Target entity is null");
|
||||
if (type==null) throw new IllegalArgumentException("Relationshiptype is null");
|
||||
|
||||
Relationship relationship=getRelationshipTo(target,type);
|
||||
if (relationship!=null) return relationship;
|
||||
if (!allowDuplicates) {
|
||||
Relationship relationship=getRelationshipTo(target,type);
|
||||
if (relationship!=null) return relationship;
|
||||
}
|
||||
return this.getPersistentState().createRelationshipTo(target.getPersistentState(), DynamicRelationshipType.withName(type));
|
||||
}
|
||||
|
||||
@@ -229,11 +234,14 @@ public privileged aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMix
|
||||
}
|
||||
|
||||
public <R extends RelationshipBacked, N extends NodeBacked> R NodeBacked.relateTo(N target, Class<R> relationshipClass, String relationshipType) {
|
||||
return this.relateTo(target,relationshipClass,relationshipType,false);
|
||||
}
|
||||
public <R extends RelationshipBacked, N extends NodeBacked> R NodeBacked.relateTo(N target, Class<R> relationshipClass, String relationshipType, boolean allowDuplicates) {
|
||||
if (target==null) throw new IllegalArgumentException("Target entity is null");
|
||||
if (relationshipClass==null) throw new IllegalArgumentException("Relationship class is null");
|
||||
if (relationshipType==null) throw new IllegalArgumentException("Relationshiptype is null");
|
||||
|
||||
Relationship rel = this.relateTo(target,relationshipType);
|
||||
Relationship rel = this.relateTo(target,relationshipType,allowDuplicates);
|
||||
|
||||
GraphDatabaseContext gdc = Neo4jNodeBacking.aspectOf().graphDatabaseContext;
|
||||
gdc.postEntityCreation(rel, relationshipClass);
|
||||
|
||||
@@ -18,13 +18,13 @@ package org.springframework.data.neo4j.aspects;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.DynamicRelationshipType;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.neo4j.kernel.Traversal;
|
||||
import org.neo4j.kernel.impl.traversal.TraversalDescriptionImpl;
|
||||
import org.springframework.data.neo4j.aspects.Person;
|
||||
import org.springframework.data.neo4j.annotation.*;
|
||||
import org.springframework.data.neo4j.core.FieldTraversalDescriptionBuilder;
|
||||
|
||||
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -44,6 +44,12 @@ public class Group {
|
||||
@GraphTraversal(traversalBuilder = PeopleTraversalBuilder.class, elementClass = Person.class, params = "persons")
|
||||
private Iterable<Person> people;
|
||||
|
||||
@GraphTraversal(traversalBuilder = PeopleTraversalBuilder.class, params = "persons")
|
||||
private Iterable<Node> peopleNodes;
|
||||
|
||||
@GraphTraversal(traversalBuilder = PeopleTraversalBuilder.class, params = "persons")
|
||||
private Iterable<Relationship> peopleRelationships;
|
||||
|
||||
@GraphProperty
|
||||
@Indexed
|
||||
private String name;
|
||||
@@ -162,4 +168,12 @@ public class Group {
|
||||
public void setAdmin(Boolean admin) {
|
||||
this.admin = admin;
|
||||
}
|
||||
|
||||
public Iterable<Node> getPeopleNodes() {
|
||||
return peopleNodes;
|
||||
}
|
||||
|
||||
public Iterable<Relationship> getPeopleRelationships() {
|
||||
return peopleRelationships;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,16 +76,16 @@ public class Person {
|
||||
@RelatedToVia(type = "knows", elementClass = Friendship.class)
|
||||
private Iterable<Friendship> friendships;
|
||||
|
||||
@Query(value = "start person=(%start) match (person)<-[:boss]-(boss) return boss")
|
||||
@Query(value = "start person=node({self}) match (person)<-[:boss]-(boss) return boss")
|
||||
private Person bossByQuery;
|
||||
|
||||
@Query(value = "start person=(%start) match (person)<-[:boss]-(boss) return boss.%property",params = {"property","name"})
|
||||
@Query(value = "start person=node({self}) match (person)<-[:boss]-(boss) return boss.name")
|
||||
private String bossName;
|
||||
|
||||
@Query(value = "start person=(%start) match (person)<-[:persons]-(team)-[:persons]->(member) return member",elementClass = Person.class)
|
||||
@Query(value = "start person=node({self}) match (person)<-[:persons]-(team)-[:persons]->(member) return member",elementClass = Person.class)
|
||||
private Iterable<Person> otherTeamMembers;
|
||||
|
||||
@Query(value = "start person=(%start) match (person)<-[:persons]-(team)-[:persons]->(member) return member.name, member.age")
|
||||
@Query(value = "start person=node({self}) match (person)<-[:persons]-(team)-[:persons]->(member) return member.name, member.age")
|
||||
private Iterable<Map<String,Object>> otherTeamMemberData;
|
||||
|
||||
public Person(Node n) {
|
||||
|
||||
@@ -19,8 +19,6 @@ package org.springframework.data.neo4j.aspects;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.neo4j.aspects.Group;
|
||||
import org.springframework.data.neo4j.aspects.Person;
|
||||
import org.springframework.data.neo4j.annotation.Query;
|
||||
import org.springframework.data.neo4j.annotation.QueryType;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
@@ -35,22 +33,22 @@ import java.util.Map;
|
||||
*/
|
||||
public interface PersonRepository extends GraphRepository<Person>, NamedIndexRepository<Person> {
|
||||
|
||||
@Query("start team=(%team) match (team)-[:persons]->(member) return member")
|
||||
Iterable<Person> findAllTeamMembers(@Param("team") Group team);
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member")
|
||||
Iterable<Person> findAllTeamMembers(@Param("p_team") Group team);
|
||||
|
||||
@Query(value = "g.v(team).out('persons')", type = QueryType.Gremlin)
|
||||
Iterable<Person> findAllTeamMembersGremlin(@Param("team") Group team);
|
||||
|
||||
@Query("start team=(%team) match (team)-[:persons]->(member) return member.name,member.age")
|
||||
Iterable<Map<String,Object>> findAllTeamMemberData(@Param("team") Group team);
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member.name,member.age")
|
||||
Iterable<Map<String,Object>> findAllTeamMemberData(@Param("p_team") Group team);
|
||||
|
||||
@Query("start person=(%person) match (boss)-[:boss]->(person) return boss")
|
||||
Person findBoss(@Param("person") Person person);
|
||||
@Query("start person=node({p_person}) match (person)<-[:boss]-(boss) return boss")
|
||||
Person findBoss(@Param("p_person") Person person);
|
||||
|
||||
Group findTeam(@Param("person") Person person);
|
||||
Group findTeam(@Param("p_person") Person person);
|
||||
|
||||
@Query("start team=(%team) match (team)-[:persons]->(member) return member")
|
||||
Page<Person> findAllTeamMembersPaged(@Param("team") Group team, Pageable page);
|
||||
@Query("start team=(%team) match (team)-[:persons]->(member) return member")
|
||||
Iterable<Person> findAllTeamMembersSorted(@Param("team") Group team, Sort sort);
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member")
|
||||
Page<Person> findAllTeamMembersPaged(@Param("p_team") Group team, Pageable page);
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member")
|
||||
Iterable<Person> findAllTeamMembersSorted(@Param("p_team") Group team, Sort sort);
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.helpers.collection.ClosableIterable;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
|
||||
@@ -25,7 +25,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.PageRequest;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.neo4j.aspects.*;
|
||||
import org.springframework.data.neo4j.aspects.Group;
|
||||
import org.springframework.data.neo4j.aspects.Person;
|
||||
import org.springframework.data.neo4j.aspects.PersonRepository;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.data.neo4j.support.node.Neo4jHelper;
|
||||
import org.springframework.test.context.CleanContextCacheTestExecutionListener;
|
||||
@@ -37,6 +39,7 @@ import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.test.context.transaction.TransactionalTestExecutionListener;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
@@ -45,6 +48,7 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.internal.matchers.IsCollectionContaining.hasItem;
|
||||
import static org.junit.internal.matchers.IsCollectionContaining.hasItems;
|
||||
import static org.neo4j.helpers.collection.IteratorUtil.addToCollection;
|
||||
import static org.neo4j.helpers.collection.IteratorUtil.asCollection;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@@ -61,17 +65,16 @@ public class GraphRepositoryTest {
|
||||
private PersonRepository personRepository;
|
||||
private TestTeam testTeam;
|
||||
|
||||
@BeforeTransaction
|
||||
public void cleanDb() {
|
||||
Neo4jHelper.cleanDb(graphDatabaseContext);
|
||||
}
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
testTeam = new TestTeam();
|
||||
testTeam.createSDGTeam();
|
||||
}
|
||||
|
||||
@BeforeTransaction
|
||||
public void cleanDb() {
|
||||
Neo4jHelper.cleanDb(graphDatabaseContext);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testFindIterableOfPersonWithQueryAnnotation() {
|
||||
@@ -117,7 +120,7 @@ public class GraphRepositoryTest {
|
||||
@Transactional
|
||||
public void testFindPagedNull() {
|
||||
Page<Person> teamMemberPage1 = personRepository.findAllTeamMembersPaged(testTeam.sdg,null);
|
||||
assertEquals(asList(testTeam.michael, testTeam.emil,testTeam.david), asCollection(teamMemberPage1));
|
||||
assertEquals(new HashSet(asList(testTeam.david, testTeam.emil, testTeam.michael)), addToCollection(teamMemberPage1, new HashSet()));
|
||||
assertThat(teamMemberPage1.isFirstPage(), is(true));
|
||||
assertThat(teamMemberPage1.isLastPage(), is(false));
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.springframework.data.neo4j.aspects.Person.persistedPerson;
|
||||
|
||||
import org.springframework.data.neo4j.aspects.*;
|
||||
@@ -146,7 +147,7 @@ public class NodeEntityRelationshipTest {
|
||||
group.setPersons(persons);
|
||||
Collection<Person> personsFromGet = group.getPersons();
|
||||
assertEquals(persons, personsFromGet);
|
||||
Assert.assertTrue(Set.class.isAssignableFrom(personsFromGet.getClass()));
|
||||
assertTrue(Set.class.isAssignableFrom(personsFromGet.getClass()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -160,7 +161,7 @@ public class NodeEntityRelationshipTest {
|
||||
group.getPersons().add(david);
|
||||
Collection<Person> personsFromGet = group.getPersons();
|
||||
assertEquals(new HashSet<Person>(Arrays.asList(david,michael)), personsFromGet);
|
||||
Assert.assertTrue(Set.class.isAssignableFrom(personsFromGet.getClass()));
|
||||
assertTrue(Set.class.isAssignableFrom(personsFromGet.getClass()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -244,6 +245,26 @@ public class NodeEntityRelationshipTest {
|
||||
assertEquals(persons, IteratorUtil.addToCollection(group.getReadOnlyPersons().iterator(), new HashSet<Person>()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void multipleRelationshipsOfSameTypeBetweenTwoEntities() {
|
||||
Person michael = persistedPerson("Michael", 35);
|
||||
Person david = persistedPerson("David", 25);
|
||||
Friendship friendship1 = michael.relateTo(david, Friendship.class, "knows", true);
|
||||
friendship1.setYears(1);
|
||||
Friendship friendship2 = michael.relateTo(david, Friendship.class, "knows",true);
|
||||
friendship2.setYears(2);
|
||||
assertTrue("two different relationships", friendship1 != friendship2);
|
||||
assertTrue("two different relationships", friendship1.getPersistentState() != friendship2.getPersistentState());
|
||||
assertEquals(1, friendship1.getYears());
|
||||
assertEquals(2,friendship2.getYears());
|
||||
final Collection<Relationship> friends = IteratorUtil.asCollection(michael.getPersistentState().getRelationships(Direction.OUTGOING, DynamicRelationshipType.withName("knows")));
|
||||
assertEquals(2,friends.size());
|
||||
assertTrue(friends.contains(friendship1.getPersistentState()));
|
||||
assertTrue(friends.contains(friendship2.getPersistentState()));
|
||||
}
|
||||
|
||||
|
||||
@Test(expected = InvalidDataAccessApiUsageException.class)
|
||||
@Transactional
|
||||
public void testOneToManyReadOnlyShouldThrowExceptionOnSet() {
|
||||
|
||||
@@ -46,7 +46,12 @@ public class TestTeam {
|
||||
sdg.addPerson(michael);
|
||||
sdg.addPerson(emil);
|
||||
sdg.addPerson(david);
|
||||
// todo those should be attached and automatically written through to the db
|
||||
david.persist();
|
||||
emil.persist();
|
||||
michael.persist();
|
||||
sdg.persist();
|
||||
|
||||
}
|
||||
|
||||
public Map<String, Object> simpleRowFor(final Person person, String prefix) {
|
||||
|
||||
@@ -22,22 +22,20 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.DynamicRelationshipType;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.traversal.Evaluators;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.neo4j.helpers.collection.IteratorUtil;
|
||||
import org.neo4j.kernel.Traversal;
|
||||
import org.neo4j.kernel.impl.traversal.TraversalDescriptionImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.neo4j.aspects.Group;
|
||||
import org.springframework.data.neo4j.aspects.Person;
|
||||
import org.springframework.data.neo4j.core.EntityPath;
|
||||
|
||||
import static org.springframework.data.neo4j.aspects.Person.persistedPerson;
|
||||
|
||||
import org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory;
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.data.neo4j.support.node.Neo4jHelper;
|
||||
|
||||
import org.springframework.test.annotation.Rollback;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
@@ -48,6 +46,7 @@ import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.springframework.data.neo4j.aspects.Person.persistedPerson;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = {"classpath:org/springframework/data/neo4j/aspects/support/Neo4jGraphPersistenceTest-context.xml"})
|
||||
@@ -100,18 +99,29 @@ public class TraversalTest {
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
@Rollback(false)
|
||||
public void testTraverseFieldFromGroupToPeople() {
|
||||
Person p = persistedPerson("Michael", 35);
|
||||
Group group = new Group().persist();
|
||||
group.setName("dev");
|
||||
group.addPerson(p);
|
||||
Iterable<Person> people = group.getPeople();
|
||||
final HashSet<Person> found = new HashSet<Person>();
|
||||
for (Person person : people) {
|
||||
found.add(person);
|
||||
}
|
||||
assertEquals(Collections.singleton(p),found);
|
||||
assertEquals(Collections.singletonList(p),IteratorUtil.asCollection(group.getPeople()));
|
||||
}
|
||||
@Test
|
||||
@Transactional
|
||||
public void testTraverseFieldFromGroupToPeopleNodes() {
|
||||
Person p = persistedPerson("Michael", 35);
|
||||
Group group = new Group().persist();
|
||||
group.addPerson(p);
|
||||
assertEquals(Collections.singletonList(p.getPersistentState()), IteratorUtil.asCollection(group.getPeopleNodes()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testTraverseFieldFromGroupToPeopleRelationships() {
|
||||
Person p = persistedPerson("Michael", 35);
|
||||
Group group = new Group().persist();
|
||||
group.addPerson(p);
|
||||
Relationship personRelationship = group.getPersistentState().getSingleRelationship(DynamicRelationshipType.withName("persons"),Direction.OUTGOING);
|
||||
assertEquals(Collections.singletonList(personRelationship), IteratorUtil.asCollection(group.getPeopleRelationships()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -94,14 +94,14 @@ public class GremlinQueryEngineTest {
|
||||
/*
|
||||
@Test
|
||||
public void testQueryListOfTypeNode() throws Exception {
|
||||
final String queryString = "start person=(name_index,name,\"%name\") match (person) <-[:boss]- (boss) return boss";
|
||||
final String queryString = "start person=(name_index,name,\"{name}\") match (person) <-[:boss]- (boss) return boss";
|
||||
final Collection<Node> result = IteratorUtil.asCollection(queryEngine.query(queryString, michaelsName()).to(Node.class));
|
||||
|
||||
assertEquals(asList(nodeFor(testTeam.emil)),result);
|
||||
}
|
||||
@Test
|
||||
public void testQueryListOfTypePerson() throws Exception {
|
||||
final String queryString = "start person=(name_index,name,\"%name\") match (person) <-[:boss]- (boss) return boss";
|
||||
final String queryString = "start person=(name_index,name,\"{name}\") match (person) <-[:boss]- (boss) return boss";
|
||||
final Collection<Person> result = IteratorUtil.asCollection(queryEngine.query(queryString, michaelsName()).to(Person.class, new EntityResultConverter(graphDatabaseContext)));
|
||||
|
||||
assertEquals(asList(testTeam.emil),result);
|
||||
@@ -110,7 +110,7 @@ public class GremlinQueryEngineTest {
|
||||
|
||||
@Test
|
||||
public void testQuerySingleOfTypePerson() throws Exception {
|
||||
final String queryString = "start person=(name_index,name,\"%name\") match (person) <-[:boss]- (boss) return boss";
|
||||
final String queryString = "start person=(name_index,name,\"{name}\") match (person) <-[:boss]- (boss) return boss";
|
||||
final Person result = queryEngine.query(queryString, michaelsName()).to(Person.class, new EntityResultConverter<Map<String,Object>,Person>(graphDatabaseContext)).single();
|
||||
|
||||
assertEquals(testTeam.emil,result);
|
||||
@@ -132,14 +132,14 @@ public class GremlinQueryEngineTest {
|
||||
|
||||
@Test
|
||||
public void testQueryForObjectAsString() throws Exception {
|
||||
final String queryString = "start person=(name_index,name,\"%name\") match (person) <-[:persons]- (team) return team.name";
|
||||
final String queryString = "start person=(name_index,name,\"{name}\") match (person) <-[:persons]- (team) return team.name";
|
||||
final String result = queryEngine.query(queryString, michaelsName()).to(String.class).single();
|
||||
|
||||
assertEquals(testTeam.sdg.getName(),result);
|
||||
}
|
||||
@Test
|
||||
public void testQueryForObjectAsEnum() throws Exception {
|
||||
final String queryString = "start person=(name_index,name,\"%name\") return person.personality";
|
||||
final String queryString = "start person=(name_index,name,\"{name}\") return person.personality";
|
||||
final Personality result = queryEngine.query(queryString, michaelsName()).to(Personality.class).single();
|
||||
|
||||
assertEquals(michael.getPersonality(),result);
|
||||
|
||||
@@ -87,17 +87,16 @@ public class QueryEngineTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
public void testQueryList() throws Exception {
|
||||
final String queryString = "start person=(%michael,%david) return person.name, person.age";
|
||||
final Collection<Map<String,Object>> result = IteratorUtil.asCollection(queryEngine.query(queryString, MapUtil.map("michael",idFor(michael), "david",idFor(testTeam.david))));
|
||||
final String queryString = "start person=node({people}) return person.name, person.age";
|
||||
final Collection<Map<String,Object>> result = IteratorUtil.asCollection(queryEngine.query(queryString, MapUtil.map("people",asList(idFor(michael),idFor(testTeam.david)))));
|
||||
|
||||
assertEquals(asList(testTeam.simpleRowFor(michael,"person"),testTeam.simpleRowFor(testTeam.david,"person")),result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryListOfTypeNode() throws Exception {
|
||||
final String queryString = "start person=(name_index,name,\"%name\") match (person) <-[:boss]- (boss) return boss";
|
||||
final String queryString = "start person=node:name_index(name={name}) match (person) <-[:boss]- (boss) return boss";
|
||||
final QueryResult<Map<String,Object>> queryResult = queryEngine.query(queryString, michaelsName());
|
||||
final Collection<Node> result = IteratorUtil.asCollection(queryResult.to(Node.class));
|
||||
|
||||
@@ -105,7 +104,7 @@ public class QueryEngineTest {
|
||||
}
|
||||
@Test
|
||||
public void testQueryListOfTypePerson() throws Exception {
|
||||
final String queryString = "start person=(name_index,name,\"%name\") match (person) <-[:boss]- (boss) return boss";
|
||||
final String queryString = "start person=node:name_index(name={name}) match (person) <-[:boss]- (boss) return boss";
|
||||
final Collection<Person> result = IteratorUtil.asCollection(queryEngine.query(queryString, michaelsName()).to(Person.class, new EntityResultConverter(graphDatabaseContext)));
|
||||
|
||||
assertEquals(asList(testTeam.emil),result);
|
||||
@@ -117,7 +116,7 @@ public class QueryEngineTest {
|
||||
|
||||
@Test
|
||||
public void testQuerySingleOfTypePerson() throws Exception {
|
||||
final String queryString = "start person=(name_index,name,\"%name\") match (person) <-[:boss]- (boss) return boss";
|
||||
final String queryString = "start person=node:name_index(name={name}) match (person) <-[:boss]- (boss) return boss";
|
||||
final Person result = queryEngine.query(queryString, michaelsName()).to(Person.class, new EntityResultConverter<Map<String,Object>,Person>(graphDatabaseContext)).single();
|
||||
|
||||
assertEquals(testTeam.emil,result);
|
||||
@@ -125,7 +124,7 @@ public class QueryEngineTest {
|
||||
|
||||
@Test
|
||||
public void testQueryListWithCustomConverter() throws Exception {
|
||||
final String queryString = String.format("start person=(name_index,name,\"%s\") match (person) <-[:boss]- (boss) return boss", michael.getName());
|
||||
final String queryString = "start person=node:name_index(name={name}) match (person) <-[:boss]- (boss) return boss";
|
||||
final Collection<String> result = IteratorUtil.asCollection(queryEngine.query(queryString, michaelsName()).to(String.class, new ResultConverter<Map<String, Object>, String>() {
|
||||
@Override
|
||||
public String convert(Map<String, Object> row, Class<String> target) {
|
||||
@@ -145,14 +144,14 @@ public class QueryEngineTest {
|
||||
|
||||
@Test
|
||||
public void testQueryForObjectAsString() throws Exception {
|
||||
final String queryString = "start person=(name_index,name,\"%name\") match (person) <-[:persons]- (team) return team.name";
|
||||
final String queryString = "start person=node:name_index(name={name}) match (person) <-[:persons]- (team) return team.name";
|
||||
final String result = queryEngine.query(queryString, michaelsName()).to(String.class).single();
|
||||
|
||||
assertEquals(testTeam.sdg.getName(),result);
|
||||
}
|
||||
@Test
|
||||
public void testQueryForObjectAsEnum() throws Exception {
|
||||
final String queryString = "start person=(name_index,name,\"%name\") return person.personality";
|
||||
final String queryString = "start person=node:name_index(name={name}) return person.personality";
|
||||
final Personality result = queryEngine.query(queryString, michaelsName()).to(Personality.class).single();
|
||||
|
||||
assertEquals(michael.getPersonality(),result);
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
<property name="namedQueries">
|
||||
<bean class="org.springframework.data.repository.core.support.PropertiesBasedNamedQueries">
|
||||
<constructor-arg>
|
||||
<props><prop key="Person.findTeam">start p=(%person) match (p)<-[:persons]-(group) return group</prop></props>
|
||||
<props><prop key="Person.findTeam">start p=node({p_person}) match (p)<-[:persons]-(group) return group</prop></props>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
</property>
|
||||
|
||||
@@ -11,6 +11,6 @@
|
||||
<context:annotation-config/>
|
||||
<neo4j:config graphDatabaseService="graphDatabaseService"/>
|
||||
<neo4j:repositories base-package="org.springframework.data.neo4j.aspects"/>
|
||||
<bean id="graphDatabaseService" class="org.neo4j.test.ImpermanentGraphDatabase"/>
|
||||
<bean id="graphDatabaseService" class="org.neo4j.test.ImpermanentGraphDatabase" destroy-method="shutdown"/>
|
||||
|
||||
</beans>
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.config;
|
||||
package org.springframework.data.neo4j.cross_store.config;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -21,11 +21,11 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.neo4j.aspects.config.Neo4jAspectConfiguration;
|
||||
import org.springframework.data.neo4j.cross_store.support.node.CrossStoreNodeEntityInstantiator;
|
||||
import org.springframework.data.neo4j.cross_store.support.node.CrossStoreNodeEntityStateFactory;
|
||||
import org.springframework.data.neo4j.support.EntityInstantiator;
|
||||
import org.springframework.data.neo4j.support.node.CrossStoreNodeEntityStateFactory;
|
||||
import org.springframework.data.neo4j.support.node.NodeEntityInstantiator;
|
||||
import org.springframework.data.neo4j.support.node.NodeEntityStateFactory;
|
||||
import org.springframework.data.neo4j.support.node.CrossStoreNodeEntityInstantiator;
|
||||
import org.springframework.data.neo4j.transaction.ChainedTransactionManager;
|
||||
import org.springframework.orm.jpa.JpaTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
@@ -14,11 +14,12 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j.support.node;
|
||||
package org.springframework.data.neo4j.cross_store.support.node;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.springframework.data.neo4j.aspects.core.NodeBacked;
|
||||
import org.springframework.data.neo4j.support.EntityInstantiator;
|
||||
import org.springframework.data.neo4j.support.node.NodeEntityInstantiator;
|
||||
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j.support.node;
|
||||
package org.springframework.data.neo4j.cross_store.support.node;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.NotInTransactionException;
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.neo4j.support.node;
|
||||
package org.springframework.data.neo4j.cross_store.support.node;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
@@ -21,6 +21,8 @@ import org.springframework.data.neo4j.aspects.core.NodeBacked;
|
||||
import org.springframework.data.neo4j.core.EntityState;
|
||||
import org.springframework.data.neo4j.fieldaccess.DetachedEntityState;
|
||||
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
|
||||
import org.springframework.data.neo4j.support.node.NodeEntityState;
|
||||
import org.springframework.data.neo4j.support.node.NodeEntityStateFactory;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
@@ -96,7 +96,7 @@
|
||||
<property name="entityStateHandler" ref="entityStateHandler"/>
|
||||
<property name="mappingContext" ref="mappingContext"/>
|
||||
</bean>
|
||||
<bean id="graphEntityInstantiator" class="org.springframework.data.neo4j.support.node.CrossStoreNodeEntityInstantiator">
|
||||
<bean id="graphEntityInstantiator" class="org.springframework.data.neo4j.cross_store.support.node.CrossStoreNodeEntityInstantiator">
|
||||
<constructor-arg ref="nodeEntityInstantiator"/>
|
||||
<constructor-arg ref="entityManagerFactory"/>
|
||||
</bean>
|
||||
@@ -121,7 +121,7 @@
|
||||
<bean id="nodeTypeRepresentationStrategy" factory-bean="typeRepresentationStrategyFactory" factory-method="getNodeTypeRepresentationStrategy" />
|
||||
<bean id="relationshipTypeRepresentationStrategy" factory-bean="typeRepresentationStrategyFactory" factory-method="getRelationshipTypeRepresentationStrategy"/>
|
||||
|
||||
<bean id="nodeEntityStateFactory" class="org.springframework.data.neo4j.support.node.CrossStoreNodeEntityStateFactory">
|
||||
<bean id="nodeEntityStateFactory" class="org.springframework.data.neo4j.cross_store.support.node.CrossStoreNodeEntityStateFactory">
|
||||
<property name="nodeDelegatingFieldAccessorFactory">
|
||||
<bean class="org.springframework.data.neo4j.fieldaccess.NodeDelegatingFieldAccessorFactory">
|
||||
<constructor-arg ref="graphDatabaseContext"/>
|
||||
|
||||
42
spring-data-neo4j-cross-store/template.mf
Normal file
42
spring-data-neo4j-cross-store/template.mf
Normal file
@@ -0,0 +1,42 @@
|
||||
Bundle-SymbolicName: org.springframework.data.neo4j
|
||||
Bundle-Name: Spring Data Neo4J
|
||||
Bundle-Vendor: SpringSource
|
||||
Bundle-ManifestVersion: 2
|
||||
Import-Package:
|
||||
sun.reflect;version="0";resolution:=optional
|
||||
Import-Template:
|
||||
org.springframework.beans.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.context.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.core.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.dao.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.jdbc.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.stereotype.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.orm.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.transaction.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.util.*;version="[3.0.0, 4.0.0)",
|
||||
org.springframework.data.*;version="[1.0.0, 2.0.0)",
|
||||
org.springframework.persistence.*;version="[1.0.0, 2.0.0)",
|
||||
org.springframework.data.neo4j.*;version="0",
|
||||
org.neo4j.*;version="0",
|
||||
org.neo4j.cypher.*;version="0";resolution:=optional,
|
||||
org.w3c.dom.*;version="0",
|
||||
org.aspectj.*;version="[1.6.5, 2.0.0)",
|
||||
org.apache.commons.logging.*;version="[1.1.1, 2.0.0)",
|
||||
org.apache.commons.configuration.*;version="0",
|
||||
org.objectweb.jotm.*;version="0",
|
||||
org.apache.lucene.*;version="0",
|
||||
javax.validation.*;version="0";resolution:=optional,
|
||||
javax.annotation.*;version="0";resolution:=optional,
|
||||
javax.naming.*;version="0";resolution:=optional,
|
||||
javax.script.*;version="0";resolution:=optional,
|
||||
javax.persistence.*;version="[1.0.0, 3.0.0)";resolution:=optional,
|
||||
javax.persistence.spi.*;version="[1.0.0, 3.0.0)";resolution:=optional,
|
||||
javax.transaction.*;version="[1.0.1, 2.0.0)";resolution:=optional,
|
||||
com.tinkerpop.blueprints.*;version="[0.8,1.0)";resolution:=optional,
|
||||
com.tinkerpop.gremlin.*;version="[1.1,2.0)";resolution:=optional,
|
||||
com.tinkerpop.pipes.util.*;version="[0.8,1.0)";resolution:=optional
|
||||
Import-Package:
|
||||
net.sf.cglib.proxy;version="[2.2.0,3.0.0)",
|
||||
net.sf.cglib.core;version="[2.2.0,3.0.0)",
|
||||
net.sf.cglib.reflect;version="[2.2.0,3.0.0)"
|
||||
DynamicImport-Package: *
|
||||
@@ -16,6 +16,7 @@ import java.util.Set;
|
||||
public class Person {
|
||||
@Indexed
|
||||
String id;
|
||||
@Indexed(fulltext = true, indexName = "people")
|
||||
String name;
|
||||
private Date birthday;
|
||||
private String birthplace;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.neo4j.cineasts.movieimport;
|
||||
|
||||
import org.springframework.context.support.FileSystemXmlApplicationContext;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
* @since 04.10.11
|
||||
*/
|
||||
public class MovieImporter {
|
||||
|
||||
private final MovieDbImportService importer;
|
||||
|
||||
public static void main(String[] args) {
|
||||
final FileSystemXmlApplicationContext ctx = new FileSystemXmlApplicationContext("src/main/webapp/WEB-INF/applicationContext.xml");
|
||||
try {
|
||||
final MovieDbImportService importer = ctx.getBean(MovieDbImportService.class);
|
||||
final MovieImporter movieImporter = new MovieImporter(importer);
|
||||
movieImporter.runImport(getMovieIdsToImport(args));
|
||||
} finally {
|
||||
ctx.close();
|
||||
}
|
||||
}
|
||||
|
||||
public MovieImporter(MovieDbImportService importer) {
|
||||
this.importer = importer;
|
||||
}
|
||||
|
||||
private void runImport(Map<Integer, Integer> movieIdsToImport) {
|
||||
final long start = System.currentTimeMillis();
|
||||
final Map<Integer, String> result = importer.importMovies(movieIdsToImport);
|
||||
final long time = System.currentTimeMillis() - start;
|
||||
for (Map.Entry<Integer, String> movie : result.entrySet()) {
|
||||
System.out.println(movie.getKey() + "\t" + movie.getValue());
|
||||
}
|
||||
System.out.println("Imported movies took "+ time+" ms.");
|
||||
}
|
||||
|
||||
private static Map<Integer, Integer> getMovieIdsToImport(String[] args) {
|
||||
if (args.length == 0) {
|
||||
throw new IllegalArgumentException("Usage: MovieImporter 1 10000\nWorking Directory should be the cineasts directory with the json files in data/json.");
|
||||
}
|
||||
if (args.length == 1) {
|
||||
return Collections.singletonMap(Integer.valueOf(args[0]), Integer.valueOf(args[0]));
|
||||
}
|
||||
return Collections.singletonMap(Integer.valueOf(args[0]), Integer.valueOf(args[1]));
|
||||
}
|
||||
}
|
||||
@@ -45,9 +45,10 @@ public class RestCypherQueryEngine implements QueryEngine<Map<String,Object>> {
|
||||
|
||||
@Override
|
||||
public QueryResult<Map<String, Object>> query(String statement, Map<String, Object> params) {
|
||||
final String parametrizedStatement = QueryResultBuilder.replaceParams(statement, params);
|
||||
final RequestResult requestResult = restRequest.get("ext/CypherPlugin/graphdb/execute_query", JsonHelper.createJsonFrom(MapUtil.map("query", parametrizedStatement)));
|
||||
return new RestQueryResult(restRequest.toMap(requestResult),restGraphDatabase,resultConverter);
|
||||
final RequestResult requestResult = restRequest.get("ext/CypherPlugin/graphdb/execute_query", JsonHelper.createJsonFrom(MapUtil.map("query", statement, "params", params)));
|
||||
final Map<?, ?> resultMap = restRequest.toMap(requestResult);
|
||||
if (RestResultException.isExceptionResult(resultMap)) throw new RestResultException(resultMap);
|
||||
return new RestQueryResult(resultMap,restGraphDatabase,resultConverter);
|
||||
}
|
||||
|
||||
static class RestQueryResult implements QueryResult<Map<String,Object>> {
|
||||
|
||||
@@ -116,6 +116,12 @@ public class LocalTestServer {
|
||||
|
||||
startupListener.await();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stop() {
|
||||
getJetty().setStopAtShutdown(false);
|
||||
super.stop();
|
||||
}
|
||||
};
|
||||
neoServer = new NeoServerWithEmbeddedWebServer(bootstrapper
|
||||
, addressResolver, new StartupHealthCheck(), new PropertyFileConfigurator(new File(url.getPath())), jettyWebServer, serverModules) {
|
||||
|
||||
@@ -30,11 +30,12 @@ public class RestTestHelper
|
||||
protected RestGraphDatabase graphDb;
|
||||
private static final String HOSTNAME = "localhost";
|
||||
private static final int PORT = 7473;
|
||||
private static LocalTestServer neoServer = new LocalTestServer(HOSTNAME,PORT).withPropertiesFile("test-db.properties");
|
||||
private static LocalTestServer neoServer;
|
||||
private static final String SERVER_ROOT_URI = "http://" + HOSTNAME + ":" + PORT + "/db/data/";
|
||||
|
||||
public void startServer() throws Exception {
|
||||
BasicConfigurator.configure();
|
||||
neoServer = new LocalTestServer(HOSTNAME,PORT).withPropertiesFile("test-db.properties");
|
||||
neoServer.start();
|
||||
}
|
||||
|
||||
@@ -48,5 +49,6 @@ public class RestTestHelper
|
||||
|
||||
public static void shutdownServer() {
|
||||
neoServer.stop();
|
||||
neoServer = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ import java.lang.annotation.Target;
|
||||
@Target({ElementType.FIELD,ElementType.METHOD})
|
||||
public @interface Query {
|
||||
/**
|
||||
* @return Query to be executed %start will be replaced by the node-id of the current entity other placeholders (%name) by the given named params
|
||||
* @return Query to be executed {self} will be provided by the node-id of the current entity other parameters (e.g. {name}) by the given named params
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
|
||||
@@ -33,8 +33,8 @@ import static org.springframework.util.StringUtils.hasText;
|
||||
public class DataGraphBeanDefinitionParser extends AbstractBeanDefinitionParser {
|
||||
|
||||
private static final String GRAPH_DATABASE_SERVICE = "graphDatabaseService";
|
||||
public static final String ASPECTJ_CONFIG = "org.springframework.data.neo4j.config.Neo4jAspectConfiguration";
|
||||
public static final String CROSS_STORE_CONFIG = "org.springframework.data.neo4j.config.CrossStoreNeo4jConfiguration";
|
||||
public static final String ASPECTJ_CONFIG = "org.springframework.data.neo4j.aspects.config.Neo4jAspectConfiguration";
|
||||
public static final String CROSS_STORE_CONFIG = "org.springframework.data.neo4j.cross_store.config.CrossStoreNeo4jConfiguration";
|
||||
|
||||
@Override
|
||||
protected AbstractBeanDefinition parseInternal(Element element, ParserContext context) {
|
||||
|
||||
@@ -21,7 +21,6 @@ import org.neo4j.helpers.collection.ClosableIterable;
|
||||
import org.neo4j.helpers.collection.IteratorWrapper;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
@@ -33,6 +32,7 @@ public class QueryResultBuilder<T> implements QueryResult<T> {
|
||||
private final boolean isClosableIterable;
|
||||
private boolean isClosed;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public QueryResultBuilder(Iterable<T> result) {
|
||||
this(result, new DefaultConverter());
|
||||
}
|
||||
@@ -43,14 +43,7 @@ public class QueryResultBuilder<T> implements QueryResult<T> {
|
||||
this.defaultConverter = defaultConverter;
|
||||
}
|
||||
|
||||
public static String replaceParams(String statement, Map<String, Object> params) {
|
||||
if (params==null || params.isEmpty()) return statement;
|
||||
for (Map.Entry<String, Object> param : params.entrySet()) {
|
||||
statement = statement.replaceAll("%"+param.getKey()+"\\b",""+param.getValue());
|
||||
}
|
||||
return statement;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <R> ConvertedResult<R> to(Class<R> type) {
|
||||
return this.to(type, defaultConverter);
|
||||
|
||||
@@ -143,13 +143,10 @@ public class DetachedEntityState<STATE> implements EntityState<STATE> {
|
||||
if (isDetached()) {
|
||||
final Field field = property.getField();
|
||||
if (!isDirty(field) && isWritable(field)) {
|
||||
Object existingValue;
|
||||
if (hasPersistentState()) {
|
||||
addDirty(field, unwrap(delegate.getValue(field)), true);
|
||||
}
|
||||
else {
|
||||
// existingValue = getValueFromEntity(field);
|
||||
// if (existingValue == null) existingValue = getDefaultValue(field.getType());
|
||||
addDirty(field, newVal, false);
|
||||
}
|
||||
}
|
||||
@@ -170,6 +167,7 @@ public class DetachedEntityState<STATE> implements EntityState<STATE> {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public void createAndAssignState() {
|
||||
if (graphDatabaseContext.transactionIsRunning()) {
|
||||
|
||||
@@ -86,6 +86,7 @@ public class Neo4jConversionServiceFactoryBean implements FactoryBean<Conversion
|
||||
|
||||
public static class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
|
||||
return new StringToEnum(targetType);
|
||||
}
|
||||
@@ -97,6 +98,7 @@ public class Neo4jConversionServiceFactoryBean implements FactoryBean<Conversion
|
||||
public StringToEnum(Class<T> enumType) {
|
||||
this.enumType = enumType;
|
||||
}
|
||||
@SuppressWarnings("RedundantCast")
|
||||
public T convert(String source) {
|
||||
if (source == null) return null;
|
||||
final String trimmed=source.trim();
|
||||
|
||||
@@ -45,7 +45,7 @@ public class OneToNRelationshipFieldAccessorFactory extends NodeRelationshipFiel
|
||||
@Override
|
||||
public FieldAccessor forField(final Neo4jPersistentProperty property) {
|
||||
final RelationshipInfo relationshipInfo = property.getRelationshipInfo();
|
||||
final Class<?> targetType = (Class<?>) relationshipInfo.getTargetType().getType();
|
||||
final Class<?> targetType = relationshipInfo.getTargetType().getType();
|
||||
return new OneToNRelationshipFieldAccessor(relationshipInfo.getRelationshipType(), relationshipInfo.getDirection(), targetType, graphDatabaseContext,property);
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ public class QueryFieldAccessorFactory implements FieldAccessorFactory {
|
||||
private Map<String, Object> createPlaceholderParams(Object entity) {
|
||||
Map<String,Object> params=new HashMap<String, Object>();
|
||||
final Node startNode = graphDatabaseContext.<Node>getPersistentState(entity);
|
||||
params.put("start", startNode.getId());
|
||||
params.put("self", startNode.getId());
|
||||
if (annotationParams.length==0) return params;
|
||||
for (int i = 0; i < annotationParams.length; i+=2) {
|
||||
params.put(annotationParams[i],annotationParams[i+1]);
|
||||
|
||||
@@ -69,6 +69,7 @@ class Neo4jPersistentPropertyImpl extends AbstractPersistentProperty<Neo4jPersis
|
||||
return annotation!=null ? new IndexInfo(annotation) : null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
|
||||
return (T) annotations.get(annotationType);
|
||||
}
|
||||
|
||||
@@ -68,6 +68,7 @@ public class Neo4jPersistentEntityImpl<T> extends BasicPersistentEntity<T, Neo4j
|
||||
return hasAnnotation(RelationshipEntity.class);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T extends Annotation> T getAnnotation(Class<T> annotationType) {
|
||||
return (T) annotations.get(annotationType);
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ public class GraphMetamodelEntityInformation<S extends PropertyContainer, T> ext
|
||||
private final RelationshipEntity relationshipEntity;
|
||||
private final NodeEntity nodeEntity;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public GraphMetamodelEntityInformation(Class domainClass, GraphDatabaseContext graphDatabaseContext) {
|
||||
super(domainClass);
|
||||
this.graphDatabaseContext = graphDatabaseContext;
|
||||
|
||||
@@ -43,6 +43,7 @@ public class RelationshipGraphRepository<T> extends AbstractGraphRepository<Rela
|
||||
return entity;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Iterable<T> save(Iterable<? extends T> entities) {
|
||||
return (Iterable<T>) entities;
|
||||
|
||||
@@ -67,7 +67,8 @@ public abstract class SpringPluginInitializer implements PluginLifecycle {
|
||||
ProvidedClassPathXmlApplicationContext appCtx = SpringPluginInitializer.this.ctx;
|
||||
for ( final Pair<String, Class> exposedBean : exposedBeans ) {
|
||||
// Class<?> concreteType = ctx.getType( exposedBean );
|
||||
result.add( new SpringBeanInjectable( appCtx, exposedBean.first(), exposedBean.other() ) );
|
||||
@SuppressWarnings("unchecked") final SpringBeanInjectable injectable = new SpringBeanInjectable(appCtx, exposedBean.first(), exposedBean.other());
|
||||
result.add(injectable);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -86,7 +87,7 @@ public abstract class SpringPluginInitializer implements PluginLifecycle {
|
||||
*
|
||||
* @param <T> optional type of the bean
|
||||
*/
|
||||
private static class SpringBeanInjectable<T extends Object> implements Injectable<T> {
|
||||
private static class SpringBeanInjectable<T> implements Injectable<T> {
|
||||
private final String exposedBean;
|
||||
protected ApplicationContext ctx;
|
||||
private final Class<T> clazz;
|
||||
@@ -97,6 +98,7 @@ public abstract class SpringPluginInitializer implements PluginLifecycle {
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public T getValue() {
|
||||
return (T)ctx.getBean( exposedBean );
|
||||
|
||||
|
||||
@@ -34,6 +34,7 @@ public class EntityStateHandler {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <S extends PropertyContainer> void setPersistentState(Object entity, S state) {
|
||||
if (entity instanceof PropertyContainer) {
|
||||
return;
|
||||
|
||||
@@ -37,6 +37,7 @@ public class EntityResultConverter<T,R> extends DefaultConverter<T,R> {
|
||||
conversionService = this.ctx.getConversionService();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected Object doConvert(Object value, Class<?> sourceType, Class targetType) {
|
||||
if (ctx.isNodeEntity(targetType)) {
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.springframework.data.neo4j.conversion.QueryResult;
|
||||
import org.springframework.data.neo4j.conversion.QueryResultBuilder;
|
||||
import org.springframework.data.neo4j.conversion.ResultConverter;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
public class CypherQueryEngine implements QueryEngine<Map<String,Object>> {
|
||||
@@ -48,19 +49,18 @@ public class CypherQueryEngine implements QueryEngine<Map<String,Object>> {
|
||||
@Override
|
||||
public QueryResult<Map<String, Object>> query(String statement, Map<String, Object> params) {
|
||||
try {
|
||||
String parametrizedQuery = QueryResultBuilder.replaceParams(statement,params);
|
||||
ExecutionResult result = parseAndExecuteQuery(parametrizedQuery);
|
||||
ExecutionResult result = parseAndExecuteQuery(statement,params);
|
||||
return new QueryResultBuilder<Map<String,Object>>(result,resultConverter);
|
||||
} catch (Exception e) {
|
||||
throw new InvalidDataAccessResourceUsageException("Error executing statement " + statement, e);
|
||||
}
|
||||
}
|
||||
|
||||
private ExecutionResult parseAndExecuteQuery(String statement) {
|
||||
private ExecutionResult parseAndExecuteQuery(String statement, Map<String, Object> params) {
|
||||
try {
|
||||
CypherParser parser = new CypherParser();
|
||||
Query query = parser.parse(statement);
|
||||
return executionEngine.execute(query);
|
||||
return executionEngine.execute(query,params==null ? Collections.<String,Object>emptyMap() : params);
|
||||
} catch(Exception e) {
|
||||
throw new InvalidDataAccessResourceUsageException("Error executing statement " + statement, e);
|
||||
}
|
||||
|
||||
@@ -31,11 +31,10 @@ import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
@SuppressWarnings("ALL")
|
||||
public class GremlinExecutor {
|
||||
|
||||
public static final int REFRESH_ENGINE_COUNT = 10000;
|
||||
private final String g = "g";
|
||||
private static final String GRAPH_VARIABLE = "g";
|
||||
private volatile ScriptEngine engine;
|
||||
|
||||
private ScriptEngine createScriptEngine() {
|
||||
@@ -49,6 +48,7 @@ public class GremlinExecutor {
|
||||
this.graphDatabaseService = graphDatabaseService;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Iterable<Object> query(String statement, Map<String,Object> params) {
|
||||
try {
|
||||
final Bindings bindings = createBindings(params);
|
||||
@@ -62,7 +62,7 @@ public class GremlinExecutor {
|
||||
|
||||
private Bindings createBindings(Map<String, Object> params) {
|
||||
final Bindings bindings = new SimpleBindings();
|
||||
bindings.put(g, new Neo4jGraph(graphDatabaseService));
|
||||
bindings.put(GRAPH_VARIABLE, new Neo4jGraph(graphDatabaseService));
|
||||
if (params==null) return bindings;
|
||||
for (Map.Entry<String, Object> entry : params.entrySet()) {
|
||||
bindings.put(entry.getKey(),entry.getValue());
|
||||
@@ -73,12 +73,13 @@ public class GremlinExecutor {
|
||||
private ScriptEngine engine() {
|
||||
if (engine == null || executionCount.incrementAndGet() > REFRESH_ENGINE_COUNT) {
|
||||
executionCount.set(0);
|
||||
this.engine = new ScriptEngineManager().getEngineByName("gremlin");
|
||||
this.engine = createScriptEngine();
|
||||
}
|
||||
return this.engine;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static Iterable getRepresentation(final Object result) {
|
||||
if (result instanceof Iterable) {
|
||||
if (result instanceof Table) {
|
||||
|
||||
@@ -16,7 +16,9 @@
|
||||
|
||||
package org.springframework.data.neo4j.support.typerepresentation;
|
||||
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Relationship;
|
||||
import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.graphdb.index.IndexHits;
|
||||
import org.neo4j.helpers.Predicate;
|
||||
@@ -24,14 +26,9 @@ import org.neo4j.helpers.collection.ClosableIterable;
|
||||
import org.neo4j.helpers.collection.FilteringIterable;
|
||||
import org.neo4j.helpers.collection.IterableWrapper;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
|
||||
import org.springframework.data.neo4j.core.NodeTypeRepresentationStrategy;
|
||||
import org.springframework.data.neo4j.support.EntityInstantiator;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.WeakHashMap;
|
||||
|
||||
public class IndexingNodeTypeRepresentationStrategy implements NodeTypeRepresentationStrategy {
|
||||
|
||||
public static final String INDEX_NAME = "__types__";
|
||||
@@ -89,6 +86,7 @@ public class IndexingNodeTypeRepresentationStrategy implements NodeTypeRepresent
|
||||
return count;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Class<?> getJavaType(Node node) {
|
||||
if (node == null) throw new IllegalArgumentException("Node is null");
|
||||
|
||||
@@ -57,10 +57,10 @@ public class IndexingRelationshipTypeRepresentationStrategy implements Relations
|
||||
}
|
||||
|
||||
private void addToTypesIndex(Relationship node, Class<?> entityClass) {
|
||||
Class<?> klass = entityClass;
|
||||
while (klass.getAnnotation(RelationshipEntity.class) != null) {
|
||||
getRelTypesIndex().add(node, INDEX_KEY, klass.getName());
|
||||
klass = klass.getSuperclass();
|
||||
Class<?> type = entityClass;
|
||||
while (type.getAnnotation(RelationshipEntity.class) != null) {
|
||||
getRelTypesIndex().add(node, INDEX_KEY, type.getName());
|
||||
type = type.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -136,6 +136,7 @@ public class SubReferenceNodeTypeRepresentationStrategy implements NodeTypeRepre
|
||||
return clazz;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> Class<T> resolveType(Node node, String typeName) {
|
||||
final Class<?> type = typeCache.getClassForName(typeName);
|
||||
if (type == null) {
|
||||
@@ -180,7 +181,7 @@ public class SubReferenceNodeTypeRepresentationStrategy implements NodeTypeRepre
|
||||
@Override
|
||||
protected T underlyingObjectToObject(final Relationship rel) {
|
||||
final Node node = rel.getStartNode();
|
||||
T entity = (T) entityInstantiator.createEntityFromState(node, getJavaType(node));
|
||||
@SuppressWarnings("unchecked") T entity = (T) entityInstantiator.createEntityFromState(node, getJavaType(node));
|
||||
if (log.isDebugEnabled()) log.debug("Converting node: " + node + " to entity: " + entity);
|
||||
return entity;
|
||||
}
|
||||
|
||||
@@ -53,7 +53,6 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
/**
|
||||
* @param graphDatabase the neo4j graph database
|
||||
* @param transactionManager if passed in, will be used to create implicit transactions whenever needed
|
||||
* @return a Neo4jTemplate instance
|
||||
*/
|
||||
public Neo4jTemplate(final GraphDatabase graphDatabase, PlatformTransactionManager transactionManager) {
|
||||
notNull(graphDatabase, "graphDatabase");
|
||||
@@ -61,10 +60,6 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
this.graphDatabase = graphDatabase;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param graphDatabase the neo4j graph database
|
||||
* @return a Neo4jTemplate instance
|
||||
*/
|
||||
public Neo4jTemplate(final GraphDatabase graphDatabase) {
|
||||
notNull(graphDatabase, "graphDatabase");
|
||||
transactionManager = null;
|
||||
@@ -178,11 +173,13 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public QueryResult<Map<String, Object>> query(String statement, Map<String, Object> params) {
|
||||
notNull(statement, "statement");
|
||||
return queryEngineFor(QueryType.Cypher).query(statement, params);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public QueryResult<Object> execute(String statement, Map<String, Object> params) {
|
||||
notNull(statement, "statement");
|
||||
|
||||
@@ -22,7 +22,7 @@ import org.neo4j.graphdb.GraphDatabaseService;
|
||||
import org.neo4j.kernel.EmbeddedGraphDatabase;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.data.neo4j.PersonRepository;
|
||||
import org.springframework.data.neo4j.model.PersonRepository;
|
||||
import org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseContext;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
|
||||
@@ -17,7 +17,7 @@ package org.springframework.data.neo4j.mapping;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.neo4j.Person;
|
||||
import org.springframework.data.neo4j.model.Person;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
|
||||
@@ -24,8 +24,8 @@ import org.neo4j.graphdb.Node;
|
||||
import org.neo4j.graphdb.Transaction;
|
||||
import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.test.ImpermanentGraphDatabase;
|
||||
import org.springframework.data.neo4j.Person;
|
||||
import org.springframework.data.neo4j.Personality;
|
||||
import org.springframework.data.neo4j.model.Person;
|
||||
import org.springframework.data.neo4j.model.Personality;
|
||||
import org.springframework.data.neo4j.fieldaccess.Neo4jConversionServiceFactoryBean;
|
||||
import org.springframework.data.neo4j.fieldaccess.NodeDelegatingFieldAccessorFactory;
|
||||
import org.springframework.data.neo4j.support.EntityStateHandler;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.Indexed;
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.springframework.data.neo4j.annotation.GraphId;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
|
||||
import org.springframework.data.neo4j.annotation.*;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.DynamicRelationshipType;
|
||||
@@ -116,6 +116,7 @@ public class Group {
|
||||
}
|
||||
|
||||
private static class PeopleTraversalBuilder implements FieldTraversalDescriptionBuilder {
|
||||
@SuppressWarnings("deprecation")
|
||||
@Override
|
||||
public TraversalDescription build(Object start, Neo4jPersistentProperty property, String...params) {
|
||||
return new TraversalDescriptionImpl()
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.springframework.data.neo4j.repository.GraphRepository;
|
||||
import org.springframework.data.neo4j.repository.NamedIndexRepository;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.annotation.RelatedTo;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
import org.springframework.data.neo4j.annotation.RelatedTo;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.neo4j.graphdb.Direction;
|
||||
import org.neo4j.graphdb.Node;
|
||||
@@ -70,16 +70,16 @@ public class Person {
|
||||
@RelatedToVia(type = "knows", elementClass = Friendship.class)
|
||||
private Iterable<Friendship> friendships;
|
||||
|
||||
@Query(value = "start person=(%start) match (person)<-[:boss]-(boss) return boss")
|
||||
@Query(value = "start person=node({self}) match (person)<-[:boss]-(boss) return boss")
|
||||
private Person bossByQuery;
|
||||
|
||||
@Query(value = "start person=(%start) match (person)<-[:boss]-(boss) return boss.%property",params = {"property","name"})
|
||||
@Query(value = "start person=node({self}) match (person)<-[:boss]-(boss) return boss.%property",params = {"property","name"})
|
||||
private String bossName;
|
||||
|
||||
@Query(value = "start person=(%start) match (person)<-[:persons]-(team)-[:persons]->(member) return member",elementClass = Person.class)
|
||||
@Query(value = "start person=node({self}) match (person)<-[:persons]-(team)-[:persons]->(member) return member",elementClass = Person.class)
|
||||
private Iterable<Person> otherTeamMembers;
|
||||
|
||||
@Query(value = "start person=(%start) match (person)<-[:persons]-(team)-[:persons]->(member) return member.name, member.age")
|
||||
@Query(value = "start person=node({self}) match (person)<-[:persons]-(team)-[:persons]->(member) return member.name, member.age")
|
||||
private Iterable<Map<String,Object>> otherTeamMemberData;
|
||||
|
||||
public Person(Node n) {
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.neo4j.graphdb.Node;
|
||||
import org.springframework.data.persistence.StateBackedCreator;
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -33,22 +33,22 @@ import java.util.Map;
|
||||
*/
|
||||
public interface PersonRepository extends GraphRepository<Person>, NamedIndexRepository<Person> {
|
||||
|
||||
@Query("start team=(%team) match (team)-[:persons]->(member) return member")
|
||||
Iterable<Person> findAllTeamMembers(@Param("team") Group team);
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member")
|
||||
Iterable<Person> findAllTeamMembers(@Param("p_team") Group team);
|
||||
|
||||
@Query(value = "g.v(team).out('persons')", type = QueryType.Gremlin)
|
||||
Iterable<Person> findAllTeamMembersGremlin(@Param("team") Group team);
|
||||
|
||||
@Query("start team=(%team) match (team)-[:persons]->(member) return member.name,member.age")
|
||||
Iterable<Map<String,Object>> findAllTeamMemberData(@Param("team") Group team);
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member.name,member.age")
|
||||
Iterable<Map<String,Object>> findAllTeamMemberData(@Param("p_team") Group team);
|
||||
|
||||
@Query("start person=(%person) match (boss)-[:boss]->(person) return boss")
|
||||
Person findBoss(@Param("person") Person person);
|
||||
@Query("start person=node({p_person}) match (boss)-[:boss]->(person) return boss")
|
||||
Person findBoss(@Param("p_person") Person person);
|
||||
|
||||
Group findTeam(@Param("person") Person person);
|
||||
Group findTeam(@Param("p_person") Person person);
|
||||
|
||||
@Query("start team=(%team) match (team)-[:persons]->(member) return member")
|
||||
Page<Person> findAllTeamMembersPaged(@Param("team") Group team, Pageable page);
|
||||
@Query("start team=(%team) match (team)-[:persons]->(member) return member")
|
||||
Iterable<Person> findAllTeamMembersSorted(@Param("team") Group team, Sort sort);
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member")
|
||||
Page<Person> findAllTeamMembersPaged(@Param("p_team") Group team, Pageable page);
|
||||
@Query("start team=node({p_team}) match (team)-[:persons]->(member) return member")
|
||||
Iterable<Person> findAllTeamMembersSorted(@Param("p_team") Group team, Sort sort);
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
public enum Personality {
|
||||
EXTROVERT, INTROVERT
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
import org.springframework.data.neo4j.annotation.NodeEntity;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
public class Toyota extends Car {
|
||||
public Toyota() {
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j;
|
||||
package org.springframework.data.neo4j.model;
|
||||
|
||||
public class Volvo extends Car {
|
||||
public Volvo() {
|
||||
@@ -14,19 +14,16 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.data.neo4j.aspects.support;
|
||||
package org.springframework.data.neo4j.support;
|
||||
|
||||
import org.hamcrest.core.Is;
|
||||
import org.hamcrest.core.IsInstanceOf;
|
||||
import org.hamcrest.core.IsNot;
|
||||
import org.hamcrest.core.IsNull;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.data.neo4j.core.GraphDatabase;
|
||||
import org.springframework.data.neo4j.support.DelegatingGraphDatabase;
|
||||
import org.springframework.data.neo4j.support.GraphDatabaseFactory;
|
||||
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.hamcrest.core.IsInstanceOf.instanceOf;
|
||||
import static org.hamcrest.core.IsNot.not;
|
||||
import static org.hamcrest.core.IsNull.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
/**
|
||||
* @author mh
|
||||
@@ -39,8 +36,8 @@ public class GraphDatabaseFactoryTest {
|
||||
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("GraphDatabaseFactory-context.xml");
|
||||
try {
|
||||
GraphDatabase graphDatabase = ctx.getBean("graphDatabase", GraphDatabase.class);
|
||||
assertThat(graphDatabase, is(not(nullValue())));
|
||||
assertThat(graphDatabase, is(instanceOf(DelegatingGraphDatabase.class)));
|
||||
Assert.assertThat(graphDatabase, Is.is(IsNot.not(IsNull.nullValue())));
|
||||
Assert.assertThat(graphDatabase, Is.is(IsInstanceOf.instanceOf(DelegatingGraphDatabase.class)));
|
||||
} finally {
|
||||
ctx.close();
|
||||
}
|
||||
@@ -52,8 +49,8 @@ public class GraphDatabaseFactoryTest {
|
||||
try {
|
||||
factory.setStoreLocation("target/test-db");
|
||||
GraphDatabase graphDatabase = factory.getObject();
|
||||
assertThat(graphDatabase, is(not(nullValue())));
|
||||
assertThat(graphDatabase,is(instanceOf(DelegatingGraphDatabase.class)));
|
||||
Assert.assertThat(graphDatabase, Is.is(IsNot.not(IsNull.nullValue())));
|
||||
Assert.assertThat(graphDatabase, Is.is(IsInstanceOf.instanceOf(DelegatingGraphDatabase.class)));
|
||||
} finally {
|
||||
factory.shutdown();
|
||||
}
|
||||
@@ -18,10 +18,7 @@ package org.springframework.data.neo4j.template;
|
||||
|
||||
import org.apache.lucene.index.Term;
|
||||
import org.apache.lucene.search.TermQuery;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.*;
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.neo4j.graphdb.index.Index;
|
||||
import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
@@ -51,12 +48,12 @@ public class Neo4jTemplateApiTest {
|
||||
private static final DynamicRelationshipType KNOWS = DynamicRelationshipType.withName("knows");
|
||||
private static final DynamicRelationshipType HAS = DynamicRelationshipType.withName("has");
|
||||
protected Neo4jTemplate template;
|
||||
protected static GraphDatabase graphDatabase;
|
||||
protected GraphDatabase graphDatabase;
|
||||
protected Node referenceNode;
|
||||
protected Relationship relationship1;
|
||||
protected Node node1;
|
||||
protected static PlatformTransactionManager transactionManager;
|
||||
protected static GraphDatabaseService graphDatabaseService;
|
||||
protected PlatformTransactionManager transactionManager;
|
||||
protected GraphDatabaseService graphDatabaseService;
|
||||
|
||||
|
||||
|
||||
@@ -85,7 +82,7 @@ public class Neo4jTemplateApiTest {
|
||||
|
||||
private void createData() {
|
||||
|
||||
new TransactionTemplate(Neo4jTemplateApiTest.transactionManager).execute(new TransactionCallbackWithoutResult() {
|
||||
new TransactionTemplate(transactionManager).execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(TransactionStatus status) {
|
||||
referenceNode.setProperty("name", "node0");
|
||||
@@ -98,8 +95,8 @@ public class Neo4jTemplateApiTest {
|
||||
});
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() throws Exception {
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
if (graphDatabaseService!=null) {
|
||||
graphDatabaseService.shutdown();
|
||||
}
|
||||
@@ -137,7 +134,7 @@ public class Neo4jTemplateApiTest {
|
||||
|
||||
@Test
|
||||
public void shouldRollbackViaStatus() throws Exception {
|
||||
new TransactionTemplate(Neo4jTemplateApiTest.transactionManager).execute(new TransactionCallbackWithoutResult() {
|
||||
new TransactionTemplate(transactionManager).execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(final TransactionStatus status) {
|
||||
template.exec(new GraphCallback.WithoutResult() {
|
||||
@@ -174,7 +171,7 @@ public class Neo4jTemplateApiTest {
|
||||
}
|
||||
@Test(expected = DataAccessException.class)
|
||||
public void shouldConvertNotFoundExceptionToDataAccessException() {
|
||||
Neo4jTemplate template = new Neo4jTemplate(graphDatabase, Neo4jTemplateApiTest.transactionManager);
|
||||
Neo4jTemplate template = new Neo4jTemplate(graphDatabase, transactionManager);
|
||||
template.exec(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabase graph) throws Exception {
|
||||
@@ -267,6 +264,7 @@ public class Neo4jTemplateApiTest {
|
||||
assertSingleResult("rel1",template.lookup("relationship", "name", "rel1").to(String.class, new PropertyContainerNameConverter()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
@Test
|
||||
public void testTraverse() throws Exception {
|
||||
final TraversalDescription description = Traversal.description().relationships(KNOWS).prune(Traversal.pruneAfterDepth(1)).filter(Traversal.returnAllButStartNode());
|
||||
@@ -275,7 +273,7 @@ public class Neo4jTemplateApiTest {
|
||||
|
||||
@Test
|
||||
public void shouldFindNextNodeViaCypher() throws Exception {
|
||||
assertSingleResult(node1, template.query("start n=(0) match n-->m return m", null).to(Node.class));
|
||||
assertSingleResult(node1, template.query("start n=node(0) match n-->m return m", null).to(Node.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -51,7 +51,7 @@ public class NeoTraversalTest extends NeoApiTest {
|
||||
});
|
||||
|
||||
final Set<String> resultSet = new HashSet<String>();
|
||||
final TraversalDescription description = Traversal.description().relationships(HAS).filter(returnAllButStartNode()).prune(Traversal.pruneAfterDepth(2));
|
||||
@SuppressWarnings("deprecation") final TraversalDescription description = Traversal.description().relationships(HAS).filter(returnAllButStartNode()).prune(Traversal.pruneAfterDepth(2));
|
||||
final QueryResult<Path> queryResult = template.traverse(template.getReferenceNode(), description);
|
||||
queryResult.handle(new Handler<Path>() {
|
||||
@Override
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package org.springframework.test.context;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.test.context.support.AbstractTestExecutionListener;
|
||||
|
||||
import java.applet.AppletContext;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -31,7 +31,7 @@ public class CleanContextCacheTestExecutionListener extends AbstractTestExecutio
|
||||
ContextCache cache = (ContextCache) cacheField.get(testContext);
|
||||
Field cacheMapField = ContextCache.class.getDeclaredField("contextKeyToContextMap");
|
||||
cacheMapField.setAccessible(true);
|
||||
Map<String, AppletContext> cacheMap = (Map<String, AppletContext>) cacheMapField.get(cache);
|
||||
@SuppressWarnings("unchecked") Map<String, ApplicationContext> cacheMap = (Map<String, ApplicationContext>) cacheMapField.get(cache);
|
||||
String[] keys = new String[cacheMap.size()];
|
||||
cacheMap.keySet().toArray(keys);
|
||||
for (String key : keys) {
|
||||
|
||||
@@ -1 +1 @@
|
||||
Person.findTeam=start p=(%person) match (p)<-[:persons]-(group) return group
|
||||
Person.findTeam=start p=node({p_person}) match (p)<-[:persons]-(group) return group
|
||||
@@ -114,19 +114,19 @@
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Executes the given query, replacing <code>%start</code> with the node-id and returning the results converted to the target type.</term>
|
||||
<term>Executes the given query, providing the <code>{self}</code> variable with the node-id and returning the results converted to the target type.</term>
|
||||
<listitem>
|
||||
<para><code><T> Iterable<T> NodeBacked.findAllByQuery(final String query, final Class<T> targetType)</code></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Executes the given query, replacing <code>%start</code> with the node-id and returning the original result, but with nodes and relationships replaced by their appropriate entities.</term>
|
||||
<term>Executes the given query, providing <code>{self}</code> variable with the node-id and returning the original result, but with nodes and relationships replaced by their appropriate entities.</term>
|
||||
<listitem>
|
||||
<para><code>Iterable<Map<String,Object>> NodeBacked.findAllByQuery(final String query)</code></para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term>Executes the given query, replacing <code>%start</code> with the node-id and returns a single result converted to the target type.</term>
|
||||
<term>Executes the given query, providing <code>{self}</code> variable with the node-id and returns a single result converted to the target type.</term>
|
||||
<listitem>
|
||||
<para><code><T> T NodeBacked.findByQuery(final String query, final Class<T> targetType)</code></para>
|
||||
</listitem>
|
||||
|
||||
@@ -76,8 +76,8 @@ public class Movie {
|
||||
<para>
|
||||
The <code>@Query</code> annotation leverages the delegation infrastructure used by the
|
||||
Spring Data Neo4j aspects. It provides dynamic fields which, when accessed, return the values
|
||||
selected by the provided query language expression. The provided query must contain a placeholder named <code>%start</code>
|
||||
for the id of the current entity. For instance <code>start n=(%start) match n-[:FRIEND]->friend return friend</code>.
|
||||
selected by the provided query language expression. The provided query must contain a placeholder named <code>{self}</code>
|
||||
for the id of the current entity. For instance <code>start n=({self}) match n-[:FRIEND]->friend return friend</code>.
|
||||
Graph queries can return variable number of entities. That's why annotation can be put onto fields
|
||||
with a single value, an Iterable of a concrete type or an Iterable of <code>Map<String,Object></code>.
|
||||
Additional parameters are taken from the params attribute of the <code>@Query</code> annotation.
|
||||
@@ -87,7 +87,7 @@ public class Movie {
|
||||
<title>@Graph on a node entity field</title>
|
||||
<programlisting language="java"><![CDATA[@NodeEntity
|
||||
public class Group {
|
||||
@Query(value = "start n=(%start) match (n)-[:%relType]->(friend) return friend",
|
||||
@Query(value = "start n=({self}) match (n)-[:%relType]->(friend) return friend",
|
||||
params = {"relType", "FRIEND"})
|
||||
private Iterable<Person> friends;
|
||||
}
|
||||
|
||||
@@ -149,9 +149,9 @@
|
||||
<title>Named Queries</title>
|
||||
<para>Spring Data Neo4j also supports the notion of named queries which are externalized in property-config-files
|
||||
(<code>META-INF/neo4j-named-queries.properties</code>). Those files have the format:
|
||||
<code>Entity.finderName=query</code> (e.g. <code>Person.findBoss=start p=(%person) match (p)<-[:BOSS]-(boss) return boss</code>).
|
||||
<code>Entity.finderName=query</code> (e.g. <code>Person.findBoss=start p=({p_person}) match (p)<-[:BOSS]-(boss) return boss</code>).
|
||||
Otherwise named queries support the same parameters as annotated queries. For using the named parameters you have to either
|
||||
annotate the parameters of the method with the <code>@Param("person")</code> annotation or enable debug symbols.
|
||||
annotate the parameters of the method with the <code>@Param("p_person")</code> annotation or enable debug symbols.
|
||||
</para>
|
||||
</section>
|
||||
<section>
|
||||
|
||||
@@ -31,7 +31,7 @@ neo.createRelationship(mark,thomas, WORKS_WITH, map("project","spring-data"));
|
||||
neo.index("devs",thomas, "name","Thomas");
|
||||
|
||||
// Cypher
|
||||
assert "Mark".equals(neo.query("start p=(%person) match p<-[:WORKS_WITH]-other return other.name",
|
||||
assert "Mark".equals(neo.query("start p=({p_person}) match p<-[:WORKS_WITH]-other return other.name",
|
||||
map("person",thomas)).to(String.class).single());
|
||||
|
||||
// Gremlin
|
||||
|
||||
Reference in New Issue
Block a user