From 8d69cda2a9a2faeb0ce0563d73d07536905fb73f Mon Sep 17 00:00:00 2001 From: Michael Hunger Date: Tue, 7 Sep 2010 00:45:02 +0200 Subject: [PATCH] indexing, short property-names as default --- .../datastore/graph/api/GraphEntity.java | 4 +- .../datastore/graph/neo4j/finder/Finder.java | 49 +++++++++++++++---- .../graph/neo4j/finder/FinderFactory.java | 7 ++- .../graph/neo4j/jpa/Neo4jEntityManager.java | 15 +++--- .../neo4j/jpa/Neo4jEntityManagerFactory.java | 10 ++-- .../neo4j/jpa/Neo4jPersistenceProvider.java | 12 +++-- .../graph/neo4j/spi/node/Neo4jNodeBacking.aj | 31 ++++++++---- .../datastore/graph/neo4j/Group.java | 2 +- .../datastore/graph/neo4j/Person.java | 2 +- .../neo4j/spi/Neo4jGraphPersistenceTest.java | 36 +++++++++++--- .../spi/Neo4jGraphPersistenceTest-context.xml | 6 +++ 11 files changed, 128 insertions(+), 46 deletions(-) diff --git a/src/main/java/org/springframework/datastore/graph/api/GraphEntity.java b/src/main/java/org/springframework/datastore/graph/api/GraphEntity.java index 9700e2144..fe0e3d4e4 100644 --- a/src/main/java/org/springframework/datastore/graph/api/GraphEntity.java +++ b/src/main/java/org/springframework/datastore/graph/api/GraphEntity.java @@ -12,5 +12,7 @@ import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface GraphEntity { - boolean useShortNames() default false; + boolean useShortNames() default true; + + boolean fullIndex() default false; } diff --git a/src/main/java/org/springframework/datastore/graph/neo4j/finder/Finder.java b/src/main/java/org/springframework/datastore/graph/neo4j/finder/Finder.java index b94344b84..c68c08ce4 100644 --- a/src/main/java/org/springframework/datastore/graph/neo4j/finder/Finder.java +++ b/src/main/java/org/springframework/datastore/graph/neo4j/finder/Finder.java @@ -9,6 +9,9 @@ import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; import org.neo4j.graphdb.NotFoundException; import org.neo4j.graphdb.Relationship; +import org.neo4j.helpers.collection.IterableWrapper; +import org.neo4j.index.IndexHits; +import org.neo4j.index.IndexService; import org.springframework.datastore.graph.neo4j.spi.node.Neo4jHelper; import org.springframework.datastore.graph.api.NodeBacked; import org.springframework.persistence.support.EntityInstantiator; @@ -17,13 +20,15 @@ public class Finder { private final Class clazz; private final GraphDatabaseService graphDatabaseService; + private final IndexService indexService; private final EntityInstantiator graphEntityInstantiator; - public Finder(Class clazz, GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator) { + public Finder(Class clazz, GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator, IndexService indexService) { this.clazz = clazz; this.graphDatabaseService = graphDatabaseService; this.graphEntityInstantiator = graphEntityInstantiator; - } + this.indexService = indexService; + } public long count() { return Neo4jHelper.count(clazz, graphDatabaseService); @@ -32,13 +37,13 @@ public class Finder { public Iterable findAll() { Node subrefNode = Neo4jHelper.findSubreferenceNode(clazz, graphDatabaseService); if (subrefNode==null) return Collections.emptyList(); - // TODO add lazy list on top of graph - List result = new ArrayList((int) count()); - for (Relationship rel : subrefNode.getRelationships(Neo4jHelper.INSTANCE_OF_RELATIONSHIP_TYPE, Direction.INCOMING)) { - Node node = rel.getStartNode(); - result.add(graphEntityInstantiator.createEntityFromState(node, clazz)); - } - return result; + return new IterableWrapper(subrefNode.getRelationships(Neo4jHelper.INSTANCE_OF_RELATIONSHIP_TYPE, Direction.INCOMING)) { + @Override + protected T underlyingObjectToObject(Relationship rel) { + Node node = rel.getStartNode(); + return graphEntityInstantiator.createEntityFromState(node, clazz); + } + }; } public T findById(long id) { @@ -48,4 +53,30 @@ public class Finder { return null; } } + public T getByIndex(String property, Object value) { + try { + final Node node = indexService.getSingleNode(property, value); + if (node==null) return null; + return graphEntityInstantiator.createEntityFromState(node, clazz); + } catch(NotFoundException e) { + return null; + } + + } + public Iterable getAllByIndex(String property, Object value) { + try { + final IndexHits nodes = indexService.getNodes(property, value); + if (nodes==null) return Collections.emptyList(); + return new IterableWrapper(nodes) { + @Override + protected T underlyingObjectToObject(Node node) { + return graphEntityInstantiator.createEntityFromState(node, clazz); + } + }; + } catch(NotFoundException e) { + return null; + } + + } } + diff --git a/src/main/java/org/springframework/datastore/graph/neo4j/finder/FinderFactory.java b/src/main/java/org/springframework/datastore/graph/neo4j/finder/FinderFactory.java index 2d1fa1888..9e67db864 100644 --- a/src/main/java/org/springframework/datastore/graph/neo4j/finder/FinderFactory.java +++ b/src/main/java/org/springframework/datastore/graph/neo4j/finder/FinderFactory.java @@ -2,6 +2,7 @@ package org.springframework.datastore.graph.neo4j.finder; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; +import org.neo4j.index.IndexService; import org.springframework.datastore.graph.api.NodeBacked; import org.springframework.datastore.graph.neo4j.spi.node.Neo4jHelper; import org.springframework.persistence.support.EntityInstantiator; @@ -10,14 +11,16 @@ public class FinderFactory { private final GraphDatabaseService graphDatabaseService; private final EntityInstantiator graphEntityInstantiator; + private final IndexService indexService; - public FinderFactory(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator) { + public FinderFactory(GraphDatabaseService graphDatabaseService, EntityInstantiator graphEntityInstantiator, IndexService indexService) { this.graphDatabaseService = graphDatabaseService; this.graphEntityInstantiator = graphEntityInstantiator; + this.indexService = indexService; } public Finder getFinderForClass(Class clazz) { - return new Finder(clazz, graphDatabaseService, graphEntityInstantiator); + return new Finder(clazz, graphDatabaseService, graphEntityInstantiator, indexService); } public Class getEntityClass(String shortName) { diff --git a/src/main/java/org/springframework/datastore/graph/neo4j/jpa/Neo4jEntityManager.java b/src/main/java/org/springframework/datastore/graph/neo4j/jpa/Neo4jEntityManager.java index 556dd3ac0..33a9d9020 100644 --- a/src/main/java/org/springframework/datastore/graph/neo4j/jpa/Neo4jEntityManager.java +++ b/src/main/java/org/springframework/datastore/graph/neo4j/jpa/Neo4jEntityManager.java @@ -2,15 +2,14 @@ package org.springframework.datastore.graph.neo4j.jpa; import org.neo4j.graphdb.*; import org.neo4j.graphdb.Transaction; +import org.neo4j.index.IndexService; import org.neo4j.kernel.EmbeddedGraphDatabase; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.datastore.graph.api.NodeBacked; import org.springframework.datastore.graph.neo4j.finder.FinderFactory; import org.springframework.persistence.support.EntityInstantiator; -import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.Transactional; -import javax.annotation.Resource; import javax.persistence.*; import javax.persistence.spi.PersistenceUnitInfo; import javax.transaction.*; @@ -25,24 +24,26 @@ import java.util.Map; @Transactional @Configurable public class Neo4jEntityManager implements EntityManager { - GraphDatabaseService graphDatabaseService; - EntityInstantiator nodeInstantiator; + private GraphDatabaseService graphDatabaseService; + private EntityInstantiator nodeInstantiator; private PersistenceUnitInfo info; private Map params; + private IndexService indexService; private volatile boolean closed; private final FinderFactory finderFactory; - public Neo4jEntityManager(final GraphDatabaseService graphDatabaseService, final EntityInstantiator nodeInstantiator, PersistenceUnitInfo info, Map params) { + public Neo4jEntityManager(final GraphDatabaseService graphDatabaseService, final EntityInstantiator nodeInstantiator, PersistenceUnitInfo info, Map params, IndexService indexService) { this.graphDatabaseService = graphDatabaseService; this.nodeInstantiator = nodeInstantiator; this.info = info; this.params = params; - finderFactory = new FinderFactory(graphDatabaseService, nodeInstantiator); + this.indexService = indexService; + finderFactory = new FinderFactory(graphDatabaseService, nodeInstantiator, indexService); } public Neo4jEntityManager() { - finderFactory = new FinderFactory(graphDatabaseService, nodeInstantiator); + finderFactory = new FinderFactory(graphDatabaseService, nodeInstantiator, indexService); } private Node nodeFor(final Object entity) { diff --git a/src/main/java/org/springframework/datastore/graph/neo4j/jpa/Neo4jEntityManagerFactory.java b/src/main/java/org/springframework/datastore/graph/neo4j/jpa/Neo4jEntityManagerFactory.java index 1fe47147f..9ec48aae2 100644 --- a/src/main/java/org/springframework/datastore/graph/neo4j/jpa/Neo4jEntityManagerFactory.java +++ b/src/main/java/org/springframework/datastore/graph/neo4j/jpa/Neo4jEntityManagerFactory.java @@ -2,10 +2,10 @@ package org.springframework.datastore.graph.neo4j.jpa; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; +import org.neo4j.index.IndexService; import org.springframework.datastore.graph.api.NodeBacked; import org.springframework.persistence.support.EntityInstantiator; -import javax.annotation.Resource; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.spi.PersistenceUnitInfo; @@ -20,23 +20,25 @@ public class Neo4jEntityManagerFactory implements EntityManagerFactory { EntityInstantiator nodeInstantiator; private PersistenceUnitInfo info; private Map params; + private IndexService indexService; - public Neo4jEntityManagerFactory(GraphDatabaseService graphDatabaseService, EntityInstantiator nodeInstantiator, PersistenceUnitInfo info, Map params) { + public Neo4jEntityManagerFactory(GraphDatabaseService graphDatabaseService, EntityInstantiator nodeInstantiator, IndexService indexService, PersistenceUnitInfo info, Map params) { this.graphDatabaseService = graphDatabaseService; this.nodeInstantiator = nodeInstantiator; + this.indexService = indexService; this.info = info; this.params = params; } @Override public EntityManager createEntityManager() { - return new Neo4jEntityManager(graphDatabaseService,nodeInstantiator,info,params); + return new Neo4jEntityManager(graphDatabaseService,nodeInstantiator,info,params, indexService); } /* TODO handle different directories for target datastore */ @Override public EntityManager createEntityManager(Map map) { - return new Neo4jEntityManager(graphDatabaseService,nodeInstantiator,info,params); + return new Neo4jEntityManager(graphDatabaseService,nodeInstantiator,info,params, indexService); } @Override diff --git a/src/main/java/org/springframework/datastore/graph/neo4j/jpa/Neo4jPersistenceProvider.java b/src/main/java/org/springframework/datastore/graph/neo4j/jpa/Neo4jPersistenceProvider.java index c916ab872..14367f5e7 100644 --- a/src/main/java/org/springframework/datastore/graph/neo4j/jpa/Neo4jPersistenceProvider.java +++ b/src/main/java/org/springframework/datastore/graph/neo4j/jpa/Neo4jPersistenceProvider.java @@ -2,9 +2,9 @@ package org.springframework.datastore.graph.neo4j.jpa; import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.Node; +import org.neo4j.index.IndexService; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.datastore.graph.api.NodeBacked; -import org.springframework.datastore.graph.neo4j.spi.node.Neo4jHelper; import org.springframework.persistence.support.EntityInstantiator; import javax.annotation.Resource; @@ -21,16 +21,18 @@ import java.util.Map; @Configurable public class Neo4jPersistenceProvider implements PersistenceProvider { @Resource - GraphDatabaseService graphDatabaseService; + private GraphDatabaseService graphDatabaseService; @Resource - EntityInstantiator graphEntityInstantiator; + private EntityInstantiator graphEntityInstantiator; + @Resource + private IndexService indexService; @Override public EntityManagerFactory createEntityManagerFactory(String emName, Map params) { System.out.println("emName = " + emName); System.out.println("params = " + params); - return new Neo4jEntityManagerFactory(graphDatabaseService,graphEntityInstantiator,null,params); + return new Neo4jEntityManagerFactory(graphDatabaseService,graphEntityInstantiator, indexService, null,params); } @Override @@ -42,6 +44,6 @@ public class Neo4jPersistenceProvider implements PersistenceProvider { System.out.println("info.getProperties() = " + info.getProperties()); System.out.println("info.getPersistenceUnitName() = " + info.getPersistenceUnitName()); System.out.println("params = " + params); - return new Neo4jEntityManagerFactory(graphDatabaseService,graphEntityInstantiator,info,params); + return new Neo4jEntityManagerFactory(graphDatabaseService,graphEntityInstantiator, indexService, info,params); } } diff --git a/src/main/java/org/springframework/datastore/graph/neo4j/spi/node/Neo4jNodeBacking.aj b/src/main/java/org/springframework/datastore/graph/neo4j/spi/node/Neo4jNodeBacking.aj index 81ea66846..01cf160ae 100644 --- a/src/main/java/org/springframework/datastore/graph/neo4j/spi/node/Neo4jNodeBacking.aj +++ b/src/main/java/org/springframework/datastore/graph/neo4j/spi/node/Neo4jNodeBacking.aj @@ -8,6 +8,7 @@ import java.util.*; import org.aspectj.lang.reflect.FieldSignature; import org.neo4j.graphdb.*; +import org.neo4j.index.IndexService; import org.neo4j.kernel.EmbeddedGraphDatabase; import org.neo4j.util.GraphDatabaseUtil; import org.springframework.beans.factory.annotation.Autowired; @@ -47,13 +48,15 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields relationshipEntityInstantiator; - - @Autowired - public void init(GraphDatabaseService gds, EntityInstantiator graphEntityInstantiator, EntityInstantiator relationshipEntityInstantiator) { + private IndexService indexService; + + @Autowired + public void init(GraphDatabaseService gds, EntityInstantiator graphEntityInstantiator, EntityInstantiator relationshipEntityInstantiator, IndexService indexService) { this.graphDatabaseService = gds; this.graphEntityInstantiator = graphEntityInstantiator; this.relationshipEntityInstantiator = relationshipEntityInstantiator; - this.fieldAccessorFactory = new FieldAccessorFactory(graphEntityInstantiator, relationshipEntityInstantiator); + this.indexService = indexService; + this.fieldAccessorFactory = new FieldAccessorFactory(graphEntityInstantiator, relationshipEntityInstantiator); } @@ -151,14 +154,14 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields R NodeBacked.relateTo(N node, Class relationshipType, String type) { Relationship rel = this.getUnderlyingNode().createRelationshipTo(node.getUnderlyingNode(), DynamicRelationshipType.withName(type)); - return relationshipEntityInstantiator.createEntityFromState(rel, relationshipType); + return (R)createRelationshipEntity(relationshipType,rel); + // relationshipEntityInstantiator.createEntityFromState(rel, relationshipType); } */ public RelationshipBacked NodeBacked.relateTo(NodeBacked node, Class relationshipType, String type) { Relationship rel = this.getUnderlyingNode().createRelationshipTo(node.getUnderlyingNode(), DynamicRelationshipType.withName(type)); return createRelationshipEntity(relationshipType,rel); } - private static RelationshipBacked createRelationshipEntity(Class relationshipType, Relationship rel) { try { final Constructor constructor = relationshipType.getDeclaredConstructor(); @@ -298,10 +301,13 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields Neo4J simple node property [" + propName + "] with value=[" + newVal + "]"); return new ShouldProceedOrReturn(true,newVal); @@ -379,5 +385,12 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields finder = factory.getFinderForClass(Person.class); Assert.assertEquals(false,finder.findAll().iterator().hasNext()); } @@ -399,4 +400,25 @@ public class Neo4jGraphPersistenceTest { Group group = new Group(); group.setReadOnlyPersons(new HashSet()); } + @Test(expected = InvalidDataAccessApiUsageException.class) + @Transactional + public void testFindGroupByIndex() { + Group group = new Group(); + group.setName("test"); + final Finder finder = finderFactory.getFinderForClass(Group.class); + final Group found = finder.getByIndex("name", "test"); + Assert.assertEquals(group,found); + } + @Test(expected = InvalidDataAccessApiUsageException.class) + @Transactional + public void testFindAllGroupsByIndex() { + Group group = new Group(); + group.setName("test"); + Group group2 = new Group(); + group.setName("test"); + final Finder finder = finderFactory.getFinderForClass(Group.class); + final Iterable found = finder.getAllByIndex("name", "test"); + final Collection result = IteratorUtil.addToCollection(found.iterator(), new HashSet()); + Assert.assertEquals(new HashSet(Arrays.asList(group,group2)), result); + } } diff --git a/src/test/resources/org/springframework/datastore/graph/neo4j/spi/Neo4jGraphPersistenceTest-context.xml b/src/test/resources/org/springframework/datastore/graph/neo4j/spi/Neo4jGraphPersistenceTest-context.xml index efc91107c..dc96d102e 100644 --- a/src/test/resources/org/springframework/datastore/graph/neo4j/spi/Neo4jGraphPersistenceTest-context.xml +++ b/src/test/resources/org/springframework/datastore/graph/neo4j/spi/Neo4jGraphPersistenceTest-context.xml @@ -83,10 +83,16 @@ destroy-method="shutdown" scope="singleton"> + + + + + +