updated to neo4j-1.3.M04

This commit is contained in:
Michael Hunger
2011-03-12 22:36:58 +00:00
parent c7b3276bd2
commit b462c88284
9 changed files with 111 additions and 93 deletions

View File

@@ -26,7 +26,7 @@ For more detailed questions, use the [forum](http://forum.springsource.org/forum
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>1.0.0.M3</version>
<version>1.0.0.M4</version>
</dependency>
<repository>
@@ -103,14 +103,18 @@ For more detailed questions, use the [forum](http://forum.springsource.org/forum
@Transactional
public Collection<World> makeSomeWorlds() {
World earth = new World( "Earth", 1 );
World mars = new World( "Mars", 2 );
World earth = world( "Earth", 1 );
World mars = world( "Mars", 2 );
mars.addRocketRouteTo( earth );
return Arrays.asList(
new World( "Mercury", 0 ), new World( "Venus", 0 ), earth, mars,
new World( "Jupiter", 63 ), new World( "Saturn", 62 ),
new World( "Uranus", 27 ), new World( "Neptune", 13 ));
world( "Mercury", 0 ), world( "Venus", 0 ), earth, mars,
world( "Jupiter", 63 ), world( "Saturn", 62 ),
world( "Uranus", 27 ), world( "Neptune", 13 ));
}
private World world(String name, int moons) {
return new World(name,moons).persist();
}
private NodeFinder<World> finder() {

View File

@@ -16,7 +16,7 @@
<org.slf4j.version>1.5.10</org.slf4j.version>
<org.springframework.version>3.0.5.RELEASE</org.springframework.version>
<data.commons.version>1.0.0.BUILD-SNAPSHOT</data.commons.version>
<neo4j.version>1.3.M03</neo4j.version>
<neo4j.version>1.3.M04</neo4j.version>
<aspectj.version>1.6.11.M2</aspectj.version>
</properties>
<profiles>

View File

@@ -107,6 +107,12 @@
<groupId>org.neo4j</groupId>
<artifactId>neo4j</artifactId>
</dependency>
<dependency>
<groupId>org.neo4j</groupId>
<artifactId>neo4j-kernel</artifactId>
<classifier>tests</classifier>
<scope>test</scope>
</dependency>
<!-- JPA -->
<dependency>

View File

@@ -36,14 +36,14 @@ import static org.springframework.data.graph.neo4j.fieldaccess.DoReturn.unwrap;
*/
public class DetachedEntityState<ENTITY extends GraphBacked<STATE>, STATE> implements EntityState<ENTITY,STATE> {
private final Map<Field, Object> dirty = new HashMap<Field, Object>();
private final Set<NodeBacked> backrefs = new HashSet<NodeBacked>();
protected final EntityState<ENTITY,STATE> delegate;
private final static Log log = LogFactory.getLog(DetachedEntityState.class);
private GraphDatabaseContext graphDatabaseContext;
private final BackReferences backReferences = null;
public DetachedEntityState(final EntityState<ENTITY, STATE> delegate, GraphDatabaseContext graphDatabaseContext) {
this.delegate = delegate;
this.graphDatabaseContext = graphDatabaseContext;
//this.backReferences = new BackReferences(this);
}
@Override
@@ -183,10 +183,34 @@ public class DetachedEntityState<ENTITY extends GraphBacked<STATE>, STATE> imple
this.dirty.put(f, previousValue);
}
public void addBackReferences(Collection<NodeBacked> backReference) {
this.backrefs.addAll(backReference);
public GraphDatabaseContext getGraphDatabaseContext() {
return graphDatabaseContext;
}
// todo always create an transaction for persist, atomic operation when no outside tx exists
@Override
public ENTITY persist() {
if (!isDetached()) return getEntity();
Transaction tx = graphDatabaseContext.beginTx();
try {
ENTITY result = delegate.persist();
//persistNeighbours();
flushDirty();
tx.success();
return result;
} finally {
tx.finish();
}
}
private void persistNeighbours() {
backReferences.persistNeighbours();
for (NodeBacked nodeBacked : getOutboundDirtyNodeEntities()) {
nodeBacked.persist();
}
}
private Set<NodeBacked> getOutboundDirtyNodeEntities() {
HashSet<NodeBacked> result = new HashSet<NodeBacked>();
@@ -216,50 +240,9 @@ public class DetachedEntityState<ENTITY extends GraphBacked<STATE>, STATE> imple
}
return false;
}
private void pruneInvalidBackRefs() {
for (Iterator<NodeBacked> it = backrefs.iterator(); it.hasNext();) {
NodeBacked backRef = it.next();
GraphBacked entity = getEntity();
if (backRef.refersTo(entity)) continue;
it.remove();
}
}
public boolean refersTo(GraphBacked target) {
return getOutboundDirtyNodeEntities().contains(target);
}
public GraphDatabaseContext getGraphDatabaseContext() {
return graphDatabaseContext;
}
// todo always create an transaction for persist, atomic operation when no outside tx exists
@Override
public ENTITY persist() {
if (!isDetached()) return getEntity();
Transaction tx = graphDatabaseContext.beginTx();
try {
ENTITY result = delegate.persist();
persistNeighbours();
flushDirty();
tx.success();
return result;
} finally {
tx.finish();
}
}
private void persistNeighbours() {
pruneInvalidBackRefs();
for (NodeBacked backref : backrefs) {
backref.persist();
}
for (NodeBacked nodeBacked : getOutboundDirtyNodeEntities()) {
nodeBacked.persist();
}
}
}

View File

@@ -3,6 +3,7 @@ package org.springframework.data.graph.neo4j.support;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -49,6 +50,14 @@ public class IndexTest {
@Autowired
private FinderFactory finderFactory;
protected NodeFinder<Group> groupFinder;
protected NodeFinder<Person> personFinder;
@Before
public void setUp() throws Exception {
groupFinder = finderFactory.createNodeEntityFinder(Group.class);
personFinder = finderFactory.createNodeEntityFinder(Person.class);
}
@BeforeTransaction
public void cleanDb() {
@@ -72,32 +81,41 @@ public class IndexTest {
Person me = persistedPerson(NAME_VALUE, 35);
Person spouse = persistedPerson(NAME_VALUE3, 36);
me.setSpouse(spouse);
final NodeFinder<Person> personFinder = finderFactory.createNodeEntityFinder(Person.class);
final Person foundMe = personFinder.findByPropertyValue(Person.NAME_INDEX, "Person.name", NAME_VALUE);
final Person foundMe = this.personFinder.findByPropertyValue(Person.NAME_INDEX, "Person.name", NAME_VALUE);
assertEquals(spouse, foundMe.getSpouse());
}
@Test
@Transactional
@Ignore("remove property from index not workin")
//@Transactional
//@Ignore("remove property from index not workin")
public void testRemovePropertyFromIndex() {
Group group = new Group().persist();
group.setName(NAME_VALUE);
final NodeFinder<Group> finder = finderFactory.createNodeEntityFinder(Group.class);
getGroupIndex().remove(group.getPersistentState(), NAME);
final Group found = finder.findByPropertyValue(null, NAME, NAME_VALUE);
Transaction tx = graphDatabaseContext.beginTx();
try {
Group group = new Group().persist();
group.setName(NAME_VALUE);
getGroupIndex().remove(group.getPersistentState(), NAME);
tx.success();
} finally {
tx.finish();
}
final Group found = groupFinder.findByPropertyValue(null, NAME, NAME_VALUE);
assertNull("Group.name removed from index", found);
}
@Test
@Transactional
@Ignore("remove property from index not workin")
//@Transactional
//@Ignore("remove property from index not workin")
public void testRemoveNodeFromIndex() {
Group group = new Group().persist();
group.setName(NAME_VALUE);
final NodeFinder<Group> finder = finderFactory.createNodeEntityFinder(Group.class);
getGroupIndex().remove(group.getPersistentState());
final Group found = finder.findByPropertyValue(null, NAME, NAME_VALUE);
Transaction tx = graphDatabaseContext.beginTx();
try {
Group group = new Group().persist();
group.setName(NAME_VALUE);
getGroupIndex().remove(group.getPersistentState());
tx.success();
} finally {
tx.finish();
}
final Group found = groupFinder.findByPropertyValue(null, NAME, NAME_VALUE);
assertNull("Group.name removed from index", found);
}
@@ -110,8 +128,7 @@ public class IndexTest {
public void testFindGroupByIndex() {
Group group = new Group().persist();
group.setName(NAME_VALUE);
final NodeFinder<Group> finder = finderFactory.createNodeEntityFinder(Group.class);
final Group found = finder.findByPropertyValue(null, NAME, NAME_VALUE);
final Group found = groupFinder.findByPropertyValue(null, NAME, NAME_VALUE);
assertEquals(group, found);
}
@@ -120,8 +137,7 @@ public class IndexTest {
public void testFindGroupByAlternativeFieldNameIndex() {
Group group = new Group().persist();
group.setOtherName(NAME_VALUE);
final NodeFinder<Group> finder = finderFactory.createNodeEntityFinder(Group.class);
final Group found = finder.findByPropertyValue(null, Group.OTHER_NAME_INDEX, NAME_VALUE);
final Group found = groupFinder.findByPropertyValue(null, Group.OTHER_NAME_INDEX, NAME_VALUE);
assertEquals(group, found);
}
@@ -172,8 +188,7 @@ public class IndexTest {
public void testDontFindGroupByNonIndexedFieldWithAnnotation() {
Group group = new Group().persist();
group.setUnindexedName("value-unindexedName");
final NodeFinder<Group> finder = finderFactory.createNodeEntityFinder(Group.class);
final Group found = finder.findByPropertyValue(null, "unindexedName", "value-unindexedName");
final Group found = groupFinder.findByPropertyValue(null, "unindexedName", "value-unindexedName");
assertNull(found);
}
@@ -182,8 +197,7 @@ public class IndexTest {
public void testDontFindGroupByNonIndexedField() {
Group group = new Group().persist();
group.setUnindexedName2("value-unindexedName2");
final NodeFinder<Group> finder = finderFactory.createNodeEntityFinder(Group.class);
final Group found = finder.findByPropertyValue(null, "unindexedName2", "value-unindexedName2");
final Group found = groupFinder.findByPropertyValue(null, "unindexedName2", "value-unindexedName2");
assertNull(found);
}
@@ -194,8 +208,7 @@ public class IndexTest {
group.setName(NAME_VALUE);
Group group2 = new Group().persist();
group2.setName(NAME_VALUE);
final NodeFinder<Group> finder = finderFactory.createNodeEntityFinder(Group.class);
final Iterable<Group> found = finder.findAllByPropertyValue(null, NAME, NAME_VALUE);
final Iterable<Group> found = groupFinder.findAllByPropertyValue(null, NAME, NAME_VALUE);
final Collection<Group> result = IteratorUtil.addToCollection(found.iterator(), new HashSet<Group>());
assertEquals(new HashSet<Group>(Arrays.asList(group, group2)), result);
}
@@ -205,8 +218,7 @@ public class IndexTest {
public void shouldFindGroupyByQueryString() {
Group group = new Group().persist();
group.setFullTextName("queryableName");
final NodeFinder<Group> finder = finderFactory.createNodeEntityFinder(Group.class);
final Iterable<Group> found = finder.findAllByQuery(Group.SEARCH_GROUPS_INDEX, "fullTextName", "queryable*");
final Iterable<Group> found = groupFinder.findAllByQuery(Group.SEARCH_GROUPS_INDEX, "fullTextName", "queryable*");
final Collection<Group> result = IteratorUtil.addToCollection(found.iterator(), new HashSet<Group>());
assertEquals(new HashSet<Group>(Arrays.asList(group)), result);
}
@@ -215,16 +227,14 @@ public class IndexTest {
@Transactional
public void testFindAllPersonByIndexOnAnnotatedField() {
Person person = persistedPerson(NAME_VALUE, 35);
final NodeFinder<Person> finder = finderFactory.createNodeEntityFinder(Person.class);
final Person found = finder.findByPropertyValue(Person.NAME_INDEX, "Person.name", NAME_VALUE);
final Person found = personFinder.findByPropertyValue(Person.NAME_INDEX, "Person.name", NAME_VALUE);
assertEquals(person, found);
}
@Test
public void findsPersonByIndexOnAnnotatedIntFieldInSeparateTransactions() {
Person person = persistedPerson(NAME_VALUE, 35);
final NodeFinder<Person> finder = finderFactory.createNodeEntityFinder(Person.class);
final Person found = finder.findByPropertyValue(null, "Person.age", 35);
final Person found = personFinder.findByPropertyValue(null, "Person.age", 35);
assertEquals("person found inside range", person, found);
}
@@ -232,8 +242,7 @@ public class IndexTest {
@Transactional
public void testRangeQueryPersonByIndexOnAnnotatedField() {
Person person = persistedPerson(NAME_VALUE, 35);
final NodeFinder<Person> finder = finderFactory.createNodeEntityFinder(Person.class);
final Person found = finder.findAllByRange(null, "Person.age", 10, 40).iterator().next();
final Person found = personFinder.findAllByRange(null, "Person.age", 10, 40).iterator().next();
assertEquals("person found inside range", person, found);
}
@@ -241,18 +250,17 @@ public class IndexTest {
@Transactional
public void testOutsideRangeQueryPersonByIndexOnAnnotatedField() {
Person person = persistedPerson(NAME_VALUE, 35);
final NodeFinder<Person> finder = finderFactory.createNodeEntityFinder(Person.class);
Iterable<Person> emptyResult = finder.findAllByRange(null, "Person.age", 0, 34);
Iterable<Person> emptyResult = personFinder.findAllByRange(null, "Person.age", 0, 34);
assertFalse("nothing found outside range", emptyResult.iterator().hasNext());
}
@Test
@Transactional
public void testFindAllPersonByIndexOnAnnotatedFieldWithAtIndexed() {
Person person = persistedPerson(NAME_VALUE, 35);
person.setNickname("Mike");
final NodeFinder<Person> finder = finderFactory.createNodeEntityFinder(Person.class);
final Person found = finder.findByPropertyValue(null, "Person.nickname", "Mike");
final Person found = personFinder.findByPropertyValue(null, "Person.nickname", "Mike");
assertEquals(person, found);
}

View File

@@ -55,6 +55,7 @@ public class ModificationOutsideOfTransactionTest
}
@Test
@Ignore("ignored until subgraph persisting is added")
public void testCreateSubgraphOutsideOfTransactionPersistInDirectionOfRel() {
Person michael = new Person("Michael", 35);
Person emil = new Person("Emil", 31);
@@ -70,7 +71,7 @@ public class ModificationOutsideOfTransactionTest
}
@Ignore
@Ignore("ignored until subgraph persisting is added")
@Test
public void testCreateSubgraphOutsideOfTransactionPersistInReverseDirectionOfRel() {
Person michael = new Person("Michael", 35);

View File

@@ -20,7 +20,7 @@ log4j.appender.R.layout.ConversionPattern=%p %t %c - %m%n
log4j.category.org.springframework=WARN
#log4j.category.org.springframework.data.graph.neo4j.support.SubReferenceNodeTypeStrategy=DEBUG
#log4j.category.org.springframework.data.graph.neo4j.fieldaccess=DEBUG
log4j.category.org.springframework.data=TRACE
#log4j.category.org.springframework.data=TRACE
#log4j.category.org.springframework.data.support=TRACE
#log4j.category.org.springframework.persistence=TRACE
#log4j.category.org.springframework.data.graph.neo4j.support=DEBUG

View File

@@ -36,7 +36,7 @@
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-neo4j</artifactId>
<version>1.0.0.M3</version>
<version>1.0.0.M4</version>
</dependency>
<dependency>

View File

@@ -1,6 +1,22 @@
Spring Data Graph Changelog
=============================================
Changes in version 1.0.0.M4 (2011-03-14)
----------------------------------------
* update to Neo4j-1.3.M04
* simplification of detached/attached state
* all node entities are detached at creation, must call persist()
* attach() renamed to persist()
* separate indices per domain class
* support for fulltext indices
* fixed direct lookup of numerically indexed values
* relationships via relateTo are now also restricted to one per type,direction and target
* added EntityPath/EntityPathMapper for entity based Neo4jTemplate callbacks
* added EntityEvaluator for entity based path evaluation
* error handling for node type strategy called on non type nodes
* FieldTraversalDescriptionBuilder build method parametrization
Changes in version 1.0.0.M3 (2011-02-25)
----------------------------------------