Skip to content

Commit

Permalink
DATAGRAPH-433 Handle Uniqueness for Label based Entities
Browse files Browse the repository at this point in the history
* added merge to Neo4jTemplate, Database
* lazy determination of the index-label-name
* initialize storedEntityType early on, update with hierarchy information later
* label handling (correctly add additional labels to the node entity on create)
* uniqueness handling (choose merge in case of unique properties for creation)
* collecting of labels of a Neo4jPersistentEntity as getAllLabels()
  • Loading branch information
jexp committed Mar 13, 2014
1 parent 36c951e commit 2f724d6
Show file tree
Hide file tree
Showing 30 changed files with 290 additions and 313 deletions.
2 changes: 1 addition & 1 deletion pom.xml
Expand Up @@ -32,7 +32,7 @@
<properties>
<project.type>multi</project.type>
<dist.id>spring-data-neo4j</dist.id>
<springdata.commons>1.8.0.BUILD-SNAPSHOT</springdata.commons>
<springdata.commons>1.7.0.RELEASE</springdata.commons>

<!-- Neo4j 2.0 now requires JDK 7 as a min -->
<source.level>1.7</source.level>
Expand Down
Expand Up @@ -34,19 +34,27 @@
import org.springframework.data.neo4j.support.index.NoSuchIndexException;
import org.springframework.data.neo4j.support.query.ConversionServiceQueryResultConverter;
import org.springframework.data.neo4j.support.query.QueryEngine;
import org.springframework.data.neo4j.support.schema.SchemaIndexProvider;

import javax.transaction.TransactionManager;
import java.util.Collection;
import java.util.Map;

import static org.neo4j.helpers.collection.MapUtil.map;

public class SpringRestGraphDatabase extends org.neo4j.rest.graphdb.RestGraphDatabase implements GraphDatabase {
static {
System.setProperty(Config.CONFIG_BATCH_TRANSACTION,"false");
}

private static final String[] NO_LABELS = new String[0];
private ConversionService conversionService;
private ResultConverter resultConverter;
private SchemaIndexProvider schemaIndexProvider;

public SpringRestGraphDatabase( RestAPI api){
super(api);
schemaIndexProvider = new SchemaIndexProvider(this);
}

public SpringRestGraphDatabase( String uri ) {
Expand All @@ -58,8 +66,18 @@ public SpringRestGraphDatabase( String uri, String user, String password ) {
}

@Override
public Node createNode(Map<String, Object> props) {
return super.getRestAPI().createNode(props);
public Node createNode(Map<String, Object> props, Collection<String> labels) {
RestAPI restAPI = super.getRestAPI();
RestNode node = restAPI.createNode(props);
if (labels!=null && !labels.isEmpty()) {
restAPI.addLabels(node, toLabels(labels));
}
return node;
}

private String[] toLabels(Collection<String> labels) {
if (labels==null || labels.isEmpty()) return NO_LABELS;
return labels.toArray(new String[labels.size()]);
}

@Override
Expand All @@ -80,6 +98,11 @@ public Node getOrCreateNode(String indexName, String key, Object value, final Ma
return getRestAPI().getOrCreateNode(nodeIndex, key, value, properties);
}

@Override
public Node merge(String labelName, String key, Object value, final Map<String, Object> nodeProperties, Collection<String> labels) {
return schemaIndexProvider.merge(labelName,key,value,nodeProperties, labels);
}


@Override
public Relationship getOrCreateRelationship(String indexName, String key, Object value, Node startNode, Node endNode, String type, Map<String, Object> properties) {
Expand Down
Expand Up @@ -242,7 +242,8 @@ public PlatformTransactionManager neo4jTransactionManager() throws Exception {
public EntityIndexCreator entityIndexCreator() throws Exception {
return new EntityIndexCreator(
indexProvider(),
schemaIndexProvider()
schemaIndexProvider(),
nodeTypeRepresentationStrategy().isLabelBased()
);
}

Expand Down
Expand Up @@ -41,8 +41,13 @@ public interface GraphDatabase {
/**
* creates the node and initializes its properties
*/
Node createNode(Map<String, Object> props);
Node createNode(Map<String, Object> props, Collection<String> labels);

/**
* creates the node uniquely or returns an existing node with the same label-key-value combination.
* properties are used to initialize the node. It needs a unique constraint to work correctly.
*/
Node merge(String labelName, String key, Object value, final Map<String, Object> properties, Collection<String> labels);
/**
* creates the node uniquely or returns an existing node with the same index-key-value combination.
* properties are used to initialize the node.
Expand Down
Expand Up @@ -39,10 +39,6 @@ protected Collection<FieldAccessorListenerFactory> createListenerFactories() {
template,
new PropertyFieldAccessorFactory(template),
new ConvertingNodePropertyFieldAccessorFactory(template)),
/*new SchemaIndexingPropertyFieldAccessorListenerFactory(
template,
new PropertyFieldAccessorFactory(template),
new ConvertingNodePropertyFieldAccessorFactory(template)), */
new ValidatingNodePropertyFieldAccessorListenerFactory(template)
);
}
Expand All @@ -53,7 +49,6 @@ protected Collection<? extends FieldAccessorFactory> createAccessorFactories() {
new IdFieldAccessorFactory(template),
new TransientFieldAccessorFactory(),
//TODO Labels new LabelFieldAccessorFactory(template),
new SchemaIndexingFieldAccessorFactory(template),
new TraversalFieldAccessorFactory(template),
new QueryFieldAccessorFactory(template),
new PropertyFieldAccessorFactory(template),
Expand Down
Expand Up @@ -16,8 +16,10 @@

package org.springframework.data.neo4j.fieldaccess;

import org.neo4j.graphdb.ConstraintViolationException;
import org.neo4j.graphdb.PropertyContainer;

import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.data.neo4j.mapping.MappingPolicy;
import org.springframework.data.neo4j.mapping.Neo4jPersistentProperty;
import org.springframework.data.neo4j.support.Neo4jTemplate;
Expand Down Expand Up @@ -67,10 +69,14 @@ public boolean isWriteable(final Object entity) {
@Override
public Object setValue(final Object entity, final Object newVal, MappingPolicy mappingPolicy) {
final PropertyContainer propertyContainer = template.getPersistentState(entity);
if (newVal==null) {
propertyContainer.removeProperty(propertyName);
} else {
propertyContainer.setProperty(propertyName, newVal);
try {
if (newVal==null) {
propertyContainer.removeProperty(propertyName);
} else {
propertyContainer.setProperty(propertyName, newVal);
}
} catch(ConstraintViolationException cve) {
throw new DataIntegrityViolationException("Unique constraint violated "+property.getOwner().getName()+"."+property.getName()+" new value "+newVal,cve);
}
return newVal;
}
Expand Down

This file was deleted.

This file was deleted.

0 comments on commit 2f724d6

Please sign in to comment.