making all the tests green again

merged pull requests from ractive
fixed handling in ManagedSet
fixed cypher query executer initialization
extracted EntityStateHandler to resolve cyclic dependency
introduced different modes for the initialization provided by the namespace
fixed illegal method override for inherited persist
This commit is contained in:
Michael Hunger
2011-10-02 19:20:25 +02:00
parent 8de85a0f6a
commit bdf51f21dd
17 changed files with 269 additions and 119 deletions

View File

@@ -25,6 +25,7 @@ import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.context.annotation.ConfigurationClassPostProcessor;
import org.springframework.util.ClassUtils;
import org.w3c.dom.Element;
import static org.springframework.util.StringUtils.hasText;
@@ -32,22 +33,40 @@ 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";
@Override
protected AbstractBeanDefinition parseInternal(Element element, ParserContext context) {
BeanDefinitionBuilder configBuilder = createConfigurationBeanDefinition();
BeanDefinitionBuilder configBuilder = createConfigurationBeanDefinition(element);
setupGraphDatabase(element, context, configBuilder);
setupEntityManagerFactory(element, configBuilder);
setupConfigurationClassPostProcessor(context);
return getSourcedBeanDefinition(configBuilder, element, context);
}
private BeanDefinitionBuilder createConfigurationBeanDefinition() {
BeanDefinitionBuilder configBuilder = BeanDefinitionBuilder.rootBeanDefinition(Neo4jConfiguration.class);
private BeanDefinitionBuilder createConfigurationBeanDefinition(Element element) {
BeanDefinitionBuilder configBuilder = createConfigBuilderByMode(element);
configBuilder.setAutowireMode(Autowire.BY_TYPE.value());
return configBuilder;
}
// todo cross-store
private BeanDefinitionBuilder createConfigBuilderByMode(Element element) {
if (isModeCrossStore(element)) return BeanDefinitionBuilder.rootBeanDefinition(CROSS_STORE_CONFIG);
if (isModeAspectJ()) return BeanDefinitionBuilder.rootBeanDefinition(ASPECTJ_CONFIG);
return BeanDefinitionBuilder.rootBeanDefinition(Neo4jConfiguration.class);
}
private boolean isModeCrossStore(Element element) {
return isModeAspectJ() && isEntityManagerFactoryConfigured(element);
}
private boolean isModeAspectJ() {
return ClassUtils.isPresent(ASPECTJ_CONFIG, getClass().getClassLoader());
}
private void setupConfigurationClassPostProcessor(final ParserContext parserContext) {
BeanDefinitionRegistry beanDefinitionRegistry = parserContext.getRegistry();
@@ -72,12 +91,17 @@ public class DataGraphBeanDefinitionParser extends AbstractBeanDefinitionParser
}
private void setupEntityManagerFactory(Element element, BeanDefinitionBuilder configBuilder) {
String entityManagerFactory = element.getAttribute("entityManagerFactory");
if (hasText(entityManagerFactory)) {
if (isEntityManagerFactoryConfigured(element)) {
String entityManagerFactory = element.getAttribute("entityManagerFactory");
configBuilder.addPropertyReference("entityManagerFactory", entityManagerFactory);
}
}
private boolean isEntityManagerFactoryConfigured(Element element) {
String entityManagerFactory = element.getAttribute("entityManagerFactory");
return hasText(entityManagerFactory);
}
private String handleStoreDir(Element element, ParserContext context, BeanDefinitionBuilder configBuilder) {
String storeDir = element.getAttribute("storeDirectory");
if (!hasText(storeDir)) return null;

View File

@@ -16,9 +16,6 @@
package org.springframework.data.neo4j.config;
import javax.annotation.PostConstruct;
import javax.validation.Validator;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
@@ -30,8 +27,6 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.ConversionService;
import org.springframework.dao.support.PersistenceExceptionTranslator;
import org.springframework.data.neo4j.fieldaccess.DelegatingFieldAccessorFactory;
import org.springframework.data.neo4j.fieldaccess.Neo4jConversionServiceFactoryBean;
import org.springframework.data.neo4j.fieldaccess.NodeDelegatingFieldAccessorFactory;
@@ -40,6 +35,7 @@ import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.mapping.Neo4jNodeConverterImpl;
import org.springframework.data.neo4j.repository.DirectGraphRepositoryFactory;
import org.springframework.data.neo4j.support.EntityInstantiator;
import org.springframework.data.neo4j.support.EntityStateHandler;
import org.springframework.data.neo4j.support.GraphDatabaseContext;
import org.springframework.data.neo4j.support.node.NodeEntityInstantiator;
import org.springframework.data.neo4j.support.node.NodeEntityStateFactory;
@@ -51,6 +47,9 @@ import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.jta.JtaTransactionManager;
import org.springframework.transaction.jta.UserTransactionAdapter;
import javax.annotation.PostConstruct;
import javax.validation.Validator;
/**
* Abstract base class for code based configuration of Spring managed Neo4j infrastructure.
* <p>Subclasses are required to provide an implementation of graphDbService ....
@@ -87,6 +86,7 @@ public abstract class Neo4jConfiguration {
gdc.setConversionService(conversionService());
gdc.setMappingContext(mappingContext());
gdc.setConverter(neo4jConverter());
gdc.setEntityStateHandler(entityStateHandler());
gdc.setNodeTypeRepresentationStrategy(typeRepresentationStrategyFactory.getNodeTypeRepresentationStrategy());
gdc.setRelationshipTypeRepresentationStrategy(typeRepresentationStrategyFactory.getRelationshipTypeRepresentationStrategy());
if (validator!=null) {
@@ -95,6 +95,11 @@ public abstract class Neo4jConfiguration {
return gdc;
}
@Bean
public EntityStateHandler entityStateHandler() {
return new EntityStateHandler(mappingContext(),graphDatabaseService);
}
@Bean
public Neo4jNodeConverterImpl neo4jConverter() throws Exception {
return new Neo4jNodeConverterImpl();
@@ -106,13 +111,13 @@ public abstract class Neo4jConfiguration {
}
@Bean
protected RelationshipEntityInstantiator graphRelationshipInstantiator() {
return new RelationshipEntityInstantiator(mappingContext());
protected RelationshipEntityInstantiator graphRelationshipInstantiator() throws Exception {
return new RelationshipEntityInstantiator(entityStateHandler());
}
@Bean
protected EntityInstantiator<Node> graphEntityInstantiator() {
return new NodeEntityInstantiator(mappingContext());
protected EntityInstantiator<Node> graphEntityInstantiator() throws Exception {
return new NodeEntityInstantiator(entityStateHandler());
}
@Bean

View File

@@ -0,0 +1,45 @@
/**
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.fieldaccess;
import org.neo4j.graphdb.PropertyContainer;
import org.neo4j.helpers.collection.IterableWrapper;
import org.springframework.data.neo4j.support.GraphDatabaseContext;
/**
* Simple wrapper to create an Iterable over @NodeEntities or @RelationshipEntities from an iterable over Nodes or Relationships.
* Creates NodeEntities on the fly while iterating the Iterator from original iterable.
*/
public class GraphBackedEntityIterableWrapper<STATE extends PropertyContainer, ENTITY> extends IterableWrapper<ENTITY, STATE> {
private final Class<ENTITY> targetType;
private final GraphDatabaseContext graphDatabaseContext;
public GraphBackedEntityIterableWrapper(Iterable<STATE> iterable, Class<ENTITY> targetType, final GraphDatabaseContext graphDatabaseContext) {
super(iterable);
this.targetType = targetType;
this.graphDatabaseContext = graphDatabaseContext;
}
@Override
protected ENTITY underlyingObjectToObject(STATE s) {
return graphDatabaseContext.createEntityFromState(s, targetType);
}
public static <S extends PropertyContainer, E> GraphBackedEntityIterableWrapper<S, E> create(
Iterable<S> iterable, Class<E> targetType, final GraphDatabaseContext graphDatabaseContext) {
return new GraphBackedEntityIterableWrapper<S, E>(iterable, targetType, graphDatabaseContext);
}
}

View File

@@ -16,10 +16,11 @@
package org.springframework.data.neo4j.fieldaccess;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
import org.springframework.data.neo4j.core.EntityState;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.support.DoReturn;
import org.springframework.data.neo4j.support.GraphDatabaseContext;
import org.springframework.data.neo4j.support.ManagedEntity;
import java.util.AbstractSet;
import java.util.Collection;
@@ -68,15 +69,20 @@ public class ManagedFieldAccessorSet<T> extends AbstractSet<T> {
}
private void update() {
final Neo4jPersistentEntity<?> persistentEntity = property.getOwner();
if (persistentEntity.isNodeEntity()) {
updateValue();
}
if (persistentEntity.isRelationshipEntity()) {
if (ctx.isManaged(entity)) {
updateValueWithState(((ManagedEntity)entity).getEntityState());
} else {
updateValue();
}
}
private Object updateValueWithState(EntityState entityState) {
final Object newValue = entityState.setValue(property, delegate);
if (newValue instanceof DoReturn) return DoReturn.unwrap(newValue);
property.setValue(entity, newValue);
return newValue;
}
private Object updateValue() {
final Object newValue = fieldAccessor.setValue(entity,delegate);
if (newValue instanceof DoReturn) return DoReturn.unwrap(newValue);

View File

@@ -15,18 +15,13 @@
*/
package org.springframework.data.neo4j.fieldaccess;
import java.lang.reflect.Field;
import java.util.Map;
import org.neo4j.graphdb.Node;
import org.springframework.data.neo4j.core.EntityState;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.support.DoReturn;
import org.springframework.data.neo4j.support.GraphDatabaseContext;
import scala.annotation.target.field;
import org.springframework.data.neo4j.support.ManagedEntity;
import java.util.Map;
/**
* Updates the entity containing such a ManagedPrefixedDynamicProperties when some property is added, changed or
@@ -82,10 +77,6 @@ public class ManagedPrefixedDynamicProperties extends PrefixedDynamicProperties
return d;
}
private void update() {
updateValue();
}
private Object updateValue() {
final Object newValue = fieldAccessor.setValue(entity, this);
if (newValue instanceof DoReturn)
@@ -93,4 +84,19 @@ public class ManagedPrefixedDynamicProperties extends PrefixedDynamicProperties
property.setValue(entity, newValue);
return newValue;
}
private void update() {
if (graphDatabaseContext.isManaged(entity)) {
updateValueWithState(((ManagedEntity)entity).getEntityState());
} else {
updateValue();
}
}
private Object updateValueWithState(EntityState entityState) {
final Object newValue = entityState.setValue(property, this);
if (newValue instanceof DoReturn) return DoReturn.unwrap(newValue);
property.setValue(entity, newValue);
return newValue;
}
}

View File

@@ -20,11 +20,8 @@ import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.support.GraphDatabaseContext;
import org.springframework.util.Assert;
import java.util.HashSet;
import java.util.Set;
@@ -59,7 +56,7 @@ public abstract class NodeToNodesRelationshipFieldAccessor extends AbstractNodeR
@Override
protected Node getState(final Object entity) {
return property.getOwner().getPersistentState(entity, graphDatabaseContext);
return graphDatabaseContext.getPersistentState(entity);
}
}

View File

@@ -16,17 +16,15 @@
package org.springframework.data.neo4j.fieldaccess;
import org.neo4j.graphdb.*;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.RelationshipType;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.mapping.RelationshipInfo;
import org.springframework.data.neo4j.support.GraphDatabaseContext;
import java.util.HashSet;
import java.util.Set;
import static org.springframework.data.neo4j.support.DoReturn.doReturn;
public class OneToNRelationshipEntityFieldAccessorFactory implements FieldAccessorFactory {
@@ -68,22 +66,16 @@ public class OneToNRelationshipEntityFieldAccessorFactory implements FieldAccess
@Override
public Object getValue(final Object entity) {
checkUnderlyingNode(entity);
final Set<?> result = createEntitySetFromRelationships(entity);
return doReturn(new ManagedFieldAccessorSet(entity, result, property,graphDatabaseContext, this));
}
return doReturn(iterableFrom(entity));
}
private Set<?> createEntitySetFromRelationships(final Object entity) {
final Set<Object> result = new HashSet<Object>();
for (final Relationship rel : getStatesFromEntity(entity)) {
final Object relationshipEntity = graphDatabaseContext.createEntityFromState(rel, relatedType);
result.add(relationshipEntity);
}
return result;
}
private GraphBackedEntityIterableWrapper<Relationship, ?> iterableFrom(final Object entity) {
return GraphBackedEntityIterableWrapper.create(getStatesFromEntity(entity), relatedType, graphDatabaseContext);
}
@Override
protected Iterable<Relationship> getStatesFromEntity(final Object entity) {
final Node persistentState = property.getOwner().getPersistentState(entity, graphDatabaseContext);
final Node persistentState = getState(entity);
return persistentState.getRelationships(type, direction);
}
@@ -94,7 +86,7 @@ public class OneToNRelationshipEntityFieldAccessorFactory implements FieldAccess
@Override
protected Node getState(final Object entity) {
return property.getOwner().getPersistentState(entity, graphDatabaseContext);
return graphDatabaseContext.getPersistentState(entity);
}
}

View File

@@ -24,6 +24,7 @@ import org.springframework.data.neo4j.mapping.RelationshipInfo;
import org.springframework.data.neo4j.support.GraphDatabaseContext;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import static org.springframework.data.neo4j.support.DoReturn.doReturn;
@@ -73,5 +74,9 @@ public class OneToNRelationshipFieldAccessorFactory extends NodeRelationshipFiel
return doReturn(createManagedSet(entity, result));
}
}
@Override
public Object getDefaultImplementation() {
return new HashSet();
}
}
}

View File

@@ -35,5 +35,5 @@ public interface Neo4jPersistentEntity<T> extends PersistentEntity<T, Neo4jPersi
void setPersistentState(Object entity, PropertyContainer pc);
<T extends PropertyContainer> T getPersistentState(Object entity, GraphDatabaseContext service);
Object getPersistentId(Object entity);
}

View File

@@ -23,7 +23,6 @@ import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.neo4j.annotation.NodeEntity;
import org.springframework.data.neo4j.annotation.RelationshipEntity;
import org.springframework.data.neo4j.support.GraphDatabaseContext;
import org.springframework.data.util.TypeInformation;
import java.lang.annotation.Annotation;
@@ -97,19 +96,10 @@ public class Neo4jPersistentEntityImpl<T> extends BasicPersistentEntity<T, Neo4j
@SuppressWarnings("unchecked")
@Override
public <T extends PropertyContainer> T getPersistentState(Object entity, GraphDatabaseContext service) {
public Object getPersistentId(Object entity) {
final Neo4jPersistentProperty idProperty = getIdProperty();
if (idProperty==null) throw new MappingException("No field annotated with @GraphId found in "+ getEntityName());
if (!Number.class.isAssignableFrom(idProperty.getType())) throw new IllegalArgumentException("The id of "+getEntityName()+" "+idProperty+" is not a number");
final Number id = (Number) idProperty.getValue(entity);
if (id==null) return null; // todo create new node?
if (isNodeEntity()) {
return (T) service.getNodeById(id.longValue());
}
if (isRelationshipEntity()) {
return (T) service.getRelationshipById(id.longValue());
}
throw new IllegalArgumentException("The entity "+getEntityName()+" has to be either annotated with @NodeEntity or @RelationshipEntity");
return idProperty.getValue(entity);
}
public String getEntityName() {

View File

@@ -0,0 +1,85 @@
/**
* Copyright 2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.support;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.PropertyContainer;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntityImpl;
/**
* @author mh
* @since 02.10.11
*/
public class EntityStateHandler {
private Neo4jMappingContext mappingContext;
private final GraphDatabaseService service;
public EntityStateHandler(Neo4jMappingContext mappingContext, GraphDatabaseService service) {
this.mappingContext = mappingContext;
this.service = service;
}
public <S extends PropertyContainer> void setPersistentState(Object entity, S state) {
if (entity instanceof PropertyContainer) {
return;
}
if (isManaged(entity)) {
((ManagedEntity<S,Object>) entity).setPersistentState(state);
return;
}
final Class<?> type = entity.getClass();
final Neo4jPersistentEntityImpl<?> persistentEntity = mappingContext.getPersistentEntity(type);
persistentEntity.setPersistentState(entity, state);
}
public boolean isManaged(Object entity) {
return entity instanceof ManagedEntity;
}
@SuppressWarnings("unchecked")
public <S extends PropertyContainer> S getPersistentState(Object entity) {
if (entity instanceof PropertyContainer) {
return (S) entity;
}
if (isManaged(entity)) {
return ((ManagedEntity<S,Object>) entity).getPersistentState();
}
final Class<?> type = entity.getClass();
final Neo4jPersistentEntityImpl<?> persistentEntity = mappingContext.getPersistentEntity(type);
final Object id = persistentEntity.getPersistentId(entity);
if (id == null) return null; // todo create new node?
if (!(id instanceof Number))
throw new IllegalArgumentException("The id of " + persistentEntity.getEntityName() + " " + persistentEntity.getIdProperty() + " is not a number");
long graphId = ((Number) id).longValue();
if (isNodeEntity(type)) {
return (S) service.getNodeById(graphId);
}
if (isRelationshipEntity(type)) {
return (S) service.getRelationshipById(graphId);
}
throw new IllegalArgumentException("The entity " + persistentEntity.getEntityName() + " has to be either annotated with @NodeEntity or @RelationshipEntity");
}
public boolean isNodeEntity(Class<?> targetType) {
return mappingContext.isNodeEntity(targetType);
}
public boolean isRelationshipEntity(Class targetType) {
return mappingContext.isRelationshipEntity(targetType);
}
}

View File

@@ -32,7 +32,6 @@ import org.springframework.data.neo4j.annotation.Indexed;
import org.springframework.data.neo4j.core.*;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.mapping.Neo4jNodeConverter;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntityImpl;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.support.query.CypherQueryExecutor;
import org.springframework.data.util.TypeInformation;
@@ -67,7 +66,8 @@ public class GraphDatabaseContext {
private RelationshipTypeRepresentationStrategy relationshipTypeRepresentationStrategy;
private Neo4jMappingContext mappingContext;
private final CypherQueryExecutor executor = new CypherQueryExecutor(this);
private CypherQueryExecutor cypherQueryExecutor;
private EntityStateHandler entityStateHandler;
public <S extends PropertyContainer, T> Index<S> getIndex(Class<T> type) {
@@ -128,33 +128,16 @@ public class GraphDatabaseContext {
S state = getPersistentState(entity);
return getTypeRepresentationStrategy(state, targetType).projectEntity(state, targetType);
}
@SuppressWarnings("unchecked")
public <S extends PropertyContainer> S getPersistentState(Object entity) {
if (entity instanceof PropertyContainer) {
return (S) entity;
}
if (isManaged(entity)) {
return ((ManagedEntity<S>)entity).getPersistentState();
}
final Class<?> type = entity.getClass();
final Neo4jPersistentEntityImpl<?> persistentEntity = mappingContext.getPersistentEntity(type);
return (S)persistentEntity.getPersistentState(entity,this);
return entityStateHandler.getPersistentState(entity);
}
// todo depending on type of mapping
@SuppressWarnings("unchecked")
public <S extends PropertyContainer> void setPersistentState(Object entity, S state) {
if (entity instanceof PropertyContainer) {
return;
}
if (isManaged(entity)) {
((ManagedEntity<S>)entity).setPersistentState(state);
return;
}
final Class<?> type = entity.getClass();
final Neo4jPersistentEntityImpl<?> persistentEntity = mappingContext.getPersistentEntity(type);
persistentEntity.setPersistentState(entity,state);
entityStateHandler.setPersistentState(entity, state);
}
public <S extends PropertyContainer, T> void postEntityCreation(S node, Class<T> entityClass) {
@@ -163,8 +146,7 @@ public class GraphDatabaseContext {
@SuppressWarnings("unchecked")
public <T> Iterable<T> findAllByTraversal(Object entity, Class<?> targetType, TraversalDescription traversalDescription) {
final Neo4jPersistentEntityImpl<?> persistentEntity = mappingContext.getPersistentEntity(entity.getClass());
final PropertyContainer state = persistentEntity.getPersistentState(entity, this);
final PropertyContainer state = entityStateHandler.getPersistentState(entity);
if (state == null) throw new IllegalStateException("No node attached to " + this);
final Traverser traverser = traversalDescription.traverse((Node) state);
if (Node.class.isAssignableFrom(targetType)) return (Iterable<T>) traverser.nodes();
@@ -317,6 +299,7 @@ public class GraphDatabaseContext {
public void setGraphDatabaseService(GraphDatabaseService graphDatabaseService) {
this.graphDatabaseService = graphDatabaseService;
this.cypherQueryExecutor = new CypherQueryExecutor(this);
}
public NodeTypeRepresentationStrategy getNodeTypeRepresentationStrategy() {
@@ -373,8 +356,8 @@ public class GraphDatabaseContext {
}
}
private boolean isManaged(Object entity) {
return entity instanceof ManagedEntity;
public boolean isManaged(Object entity) {
return entityStateHandler.isManaged(entity);
}
public void setConverter(Neo4jNodeConverter converter) {
@@ -383,14 +366,19 @@ public class GraphDatabaseContext {
public Object executeQuery(Object entity, String queryString, Map<String, Object> params, Neo4jPersistentProperty property) {
final TypeInformation<?> typeInformation = property.getTypeInformation();
final Class<?> targetType = typeInformation.getActualType().getType();
final TypeInformation<?> actualType = typeInformation.getActualType();
final Class<?> targetType = actualType.getType();
if (actualType.isMap()) {
return cypherQueryExecutor.queryForList(queryString, params);
}
if (typeInformation.isCollectionLike()) {
return executor.query(queryString, targetType, params);
return cypherQueryExecutor.query(queryString, targetType, params);
}
if (typeInformation.isMap()) {
return executor.queryForList(queryString, params);
}
return executor.queryForObject(queryString, targetType, params);
return cypherQueryExecutor.queryForObject(queryString, targetType, params);
}
public void setEntityStateHandler(EntityStateHandler entityStateHandler) {
this.entityStateHandler = entityStateHandler;
}
}

View File

@@ -15,16 +15,18 @@
*/
package org.springframework.data.neo4j.support;
import org.neo4j.graphdb.PropertyContainer;
import org.springframework.data.neo4j.core.EntityState;
/**
* @author mh
* @since 02.10.11
*/
public interface ManagedEntity<S> {
<T extends S> T persist();
public interface ManagedEntity<S,T> {
<U extends T> U persist();
S getPersistentState();
EntityState<S> getEntityState();
void setPersistentState(S state);
}

View File

@@ -17,9 +17,8 @@
package org.springframework.data.neo4j.support.node;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.support.AbstractConstructorEntityInstantiator;
import org.springframework.data.neo4j.support.EntityStateHandler;
/**
@@ -31,10 +30,10 @@ import org.springframework.data.neo4j.support.AbstractConstructorEntityInstantia
*/
public class NodeEntityInstantiator extends AbstractConstructorEntityInstantiator<Node> {
private final Neo4jMappingContext mappingContext;
private final EntityStateHandler entityStateHandler;
public NodeEntityInstantiator(Neo4jMappingContext mappingContext) {
this.mappingContext = mappingContext;
public NodeEntityInstantiator(EntityStateHandler entityStateHandler) {
this.entityStateHandler = entityStateHandler;
}
@@ -44,7 +43,7 @@ public class NodeEntityInstantiator extends AbstractConstructorEntityInstantiato
}
protected void setPersistentState(Object entity, Node node) {
this.mappingContext.setPersistentState(entity,node);
this.entityStateHandler.setPersistentState(entity,node);
}

View File

@@ -24,6 +24,7 @@ import org.springframework.data.neo4j.fieldaccess.DefaultEntityState;
import org.springframework.data.neo4j.fieldaccess.DelegatingFieldAccessorFactory;
import org.springframework.data.neo4j.mapping.Neo4jPersistentEntity;
import org.springframework.data.neo4j.support.GraphDatabaseContext;
import org.springframework.data.neo4j.support.ManagedEntity;
/**
* @author Michael Hunger
@@ -65,7 +66,9 @@ public class NodeEntityState extends DefaultEntityState<Node> {
@Override
public void setPersistentState(Node node) {
graphDatabaseContext.setPersistentState(entity,node);
if (!(entity instanceof ManagedEntity)) {
graphDatabaseContext.setPersistentState(entity, node);
}
super.setPersistentState(node);
}

View File

@@ -17,9 +17,8 @@
package org.springframework.data.neo4j.support.relationship;
import org.neo4j.graphdb.Relationship;
import org.springframework.data.neo4j.mapping.Neo4jMappingContext;
import org.springframework.data.neo4j.support.AbstractConstructorEntityInstantiator;
import org.springframework.data.neo4j.support.EntityStateHandler;
import sun.reflect.ReflectionFactory;
/**
@@ -30,15 +29,15 @@ import sun.reflect.ReflectionFactory;
public class RelationshipEntityInstantiator extends AbstractConstructorEntityInstantiator<Relationship> {
private final Neo4jMappingContext mappingContext;
private final EntityStateHandler entityStateHandler;
public RelationshipEntityInstantiator(Neo4jMappingContext mappingContext) {
this.mappingContext = mappingContext;
public RelationshipEntityInstantiator(EntityStateHandler entityStateHandler) {
this.entityStateHandler = entityStateHandler;
}
@Override
protected void setState(Object entity, Relationship relationship) {
this.mappingContext.setPersistentState(entity,relationship);
this.entityStateHandler.setPersistentState(entity,relationship);
}
@Override

View File

@@ -28,6 +28,7 @@ import org.springframework.data.neo4j.Person;
import org.springframework.data.neo4j.Personality;
import org.springframework.data.neo4j.fieldaccess.Neo4jConversionServiceFactoryBean;
import org.springframework.data.neo4j.fieldaccess.NodeDelegatingFieldAccessorFactory;
import org.springframework.data.neo4j.support.EntityStateHandler;
import org.springframework.data.neo4j.support.GraphDatabaseContext;
import org.springframework.data.neo4j.support.node.NodeEntityInstantiator;
import org.springframework.data.neo4j.support.node.NodeEntityStateFactory;
@@ -63,10 +64,13 @@ public class Neo4jNodeConverterTest {
private GraphDatabaseContext createContext(Neo4jMappingContext mappingContext) throws Exception {
GraphDatabaseContext gdc = new GraphDatabaseContext();
gdc.setGraphDatabaseService(new ImpermanentGraphDatabase());
final ImpermanentGraphDatabase gdb = new ImpermanentGraphDatabase();
gdc.setGraphDatabaseService(gdb);
gdc.setMappingContext(mappingContext);
gdc.setNodeTypeRepresentationStrategy(new NoopNodeTypeRepresentationStrategy(new NodeEntityInstantiator(mappingContext)));
final EntityStateHandler entityStateHandler = new EntityStateHandler(mappingContext, gdb);
gdc.setNodeTypeRepresentationStrategy(new NoopNodeTypeRepresentationStrategy(new NodeEntityInstantiator(entityStateHandler)));
gdc.setConversionService(new Neo4jConversionServiceFactoryBean().getObject());
gdc.setEntityStateHandler(entityStateHandler);
return gdc;
}