updated to neo4j-1.3.M04
This commit is contained in:
16
README.md
16
README.md
@@ -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() {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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)
|
||||
----------------------------------------
|
||||
|
||||
|
||||
Reference in New Issue
Block a user