re-enabled cross-store persistence

This commit is contained in:
Michael Hunger
2011-03-14 23:20:00 +01:00
parent 93c415f9f6
commit 3345079ffb
13 changed files with 32 additions and 18 deletions

View File

@@ -16,6 +16,8 @@ Changes in version 1.0.0.M4 (2011-03-14)
* added EntityEvaluator for entity based path evaluation
* error handling for node type strategy called on non type nodes
* FieldTraversalDescriptionBuilder build method parametrization
* re-enabled cross-store persistence
* removed the need to mark graph managed fields with @Transient for a cross store entity
Changes in version 1.0.0.M3 (2011-02-25)
----------------------------------------

View File

@@ -327,6 +327,7 @@
<artifactId>maven-surefire-plugin</artifactId>
<version>2.6</version>
<configuration>
<forkMode>always</forkMode>
<useFile>true</useFile>
<includes>
<include>**/*Tests.java</include>

View File

@@ -1,10 +1,8 @@
package org.springframework.data.graph.neo4j.fieldaccess;
import org.springframework.data.graph.annotation.RelatedTo;
import org.springframework.data.graph.core.GraphBacked;
import org.springframework.data.graph.core.NodeBacked;
import java.lang.reflect.Field;
import java.util.*;
/**

View File

@@ -91,7 +91,7 @@ public abstract class DefaultEntityState<ENTITY extends GraphBacked<STATE>, STAT
return result;
}
private FieldAccessor<ENTITY> accessorFor(final Field field) {
protected FieldAccessor<ENTITY> accessorFor(final Field field) {
return fieldAccessors.get(field);
}

View File

@@ -79,7 +79,7 @@ public class DetachedEntityState<ENTITY extends GraphBacked<STATE>, STATE> imple
return delegate.getValue(field);
}
private boolean isDetached() {
protected boolean isDetached() {
return !transactionIsRunning() || !hasPersistentState() || isDirty();
}

View File

@@ -22,6 +22,8 @@ import org.springframework.data.graph.core.NodeBacked;
import org.springframework.data.graph.neo4j.finder.FinderFactory;
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
import java.lang.reflect.Field;
import static org.springframework.data.graph.neo4j.fieldaccess.PartialNodeEntityState.getId;
public class NodeEntityStateFactory {
@@ -38,8 +40,8 @@ public class NodeEntityStateFactory {
PartialNodeEntityState<NodeBacked> partialNodeEntityState = new PartialNodeEntityState<NodeBacked>(null, entity, entity.getClass(), graphDatabaseContext, finderFactory);
return new DetachedEntityState<NodeBacked, Node>(partialNodeEntityState, graphDatabaseContext) {
@Override
protected boolean transactionIsRunning() {
return super.transactionIsRunning() && getId(entity, entity.getClass()) != null;
protected boolean isDetached() {
return super.isDetached() || getId(entity, entity.getClass()) == null;
}
};
} else {

View File

@@ -18,7 +18,6 @@ package org.springframework.data.graph.neo4j.fieldaccess;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.NotInTransactionException;
import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.graphdb.index.Index;
import org.neo4j.graphdb.index.IndexHits;
import org.springframework.dao.InvalidDataAccessResourceUsageException;
@@ -141,6 +140,13 @@ public class PartialNodeEntityState<ENTITY extends NodeBacked> extends DefaultEn
return entity;
}
@Override
public boolean isWritable(Field field) {
final FieldAccessor<ENTITY> accessor = accessorFor(field);
if (accessor == null) return false; // difference to default behaviour, we don't care for non-managed fields here
return accessor.isWriteable(entity);
}
private void persistForeignId(Node node, Object id) {
if (!node.hasProperty(FOREIGN_ID) && id != null) {
final String foreignId = createForeignId(id);

View File

@@ -17,7 +17,6 @@
package org.springframework.data.graph.neo4j.finder;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.index.Index;
import org.neo4j.graphdb.traversal.TraversalDescription;
import org.springframework.data.graph.core.GraphBacked;
import org.springframework.data.graph.core.NodeBacked;

View File

@@ -30,6 +30,9 @@ import org.springframework.data.graph.core.RelationshipBacked;
import org.springframework.data.graph.neo4j.fieldaccess.*;
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
import org.springframework.data.graph.annotation.*;
import javax.persistence.Transient;
import javax.persistence.Entity;
import java.lang.reflect.Field;
import static org.springframework.data.graph.neo4j.fieldaccess.DoReturn.unwrap;
@@ -48,6 +51,13 @@ public aspect Neo4jNodeBacking { // extends AbstractTypeAnnotatingMixinFields<No
declare parents : (@NodeEntity *) implements NodeBacked;
declare @type: NodeBacked+: @Configurable;
declare @field: @GraphProperty * (@Entity @NodeEntity(partial=true) *).*:@Transient;
declare @field: @RelatedTo * (@Entity @NodeEntity(partial=true) *).*:@Transient;
declare @field: @RelatedToVia * (@Entity @NodeEntity(partial=true) *).*:@Transient;
declare @field: @GraphId * (@Entity @NodeEntity(partial=true) *).*:@Transient;
declare @field: @GraphTraversal * (@Entity @NodeEntity(partial=true) *).*:@Transient;
protected pointcut entityFieldGet(NodeBacked entity) :
get(* NodeBacked+.*) &&

View File

@@ -22,7 +22,6 @@ import org.springframework.data.graph.neo4j.fieldaccess.PartialNodeEntityState;
import org.springframework.persistence.support.EntityInstantiator;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
/**
* Entity instantiator for Node entities that takes into account that the entity is persisted in a JPA store as well.

View File

@@ -11,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.graph.neo4j.support.GraphDatabaseContext;
import org.springframework.data.graph.neo4j.support.node.Neo4jHelper;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.Rollback;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -24,8 +25,8 @@ import javax.sql.DataSource;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:org/springframework/data/graph/neo4j/partial/Neo4jGraphRecommendationTest-context.xml"})
@Ignore("seems to break things in the graph store")
//@Ignore("seems to break things in the graph store")
@DirtiesContext
public class RecommendationTest {
protected final Log log = LogFactory.getLog(getClass());
@@ -70,8 +71,7 @@ public class RecommendationTest {
user.setNickname(name);
em.persist(user);
em.flush();
user.getId();
return user;
return user.persist();
}
@Test

View File

@@ -28,15 +28,12 @@ public class User {
@GraphProperty
@Indexed
@Transient
String nickname;
@RelatedToVia(type = "recommends", elementClass = Recommendation.class)
@Transient
Iterable<Recommendation> recommendations;
@RelatedTo(type = "friends", elementClass = User.class)
@Transient
Set<User> friends;
public Recommendation rate(Restaurant restaurant, int stars, String comment) {

View File

@@ -37,7 +37,7 @@
method). Roo applications use this useful feature in a number of
areas, such as @PersistenceContext injection into entities.
-->
<context:spring-configured/>
<!--context:spring-configured/-->
<!--
This declaration will cause Spring to locate every @Component,
@@ -62,7 +62,7 @@
-->
<context:component-scan base-package="org.springframework.data.graph.neo4j">
<context:exclude-filter expression=".*_Roo_.*" type="regex"/>
<context:exclude-filter expression="org.springframework.data.graph.neo4j.config.Neo4jConfiguration" type="regex"/>
<context:exclude-filter expression="org.springframework.context.annotation.Configuration" type="annotation"/>
<context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
</context:component-scan>