removed the update method, added an explicit flag for participating in explicit outside transaction
This commit is contained in:
@@ -11,15 +11,6 @@ import java.util.Map;
|
||||
* @since 19.02.11
|
||||
*/
|
||||
public interface Neo4jOperations {
|
||||
/**
|
||||
* Executes the callback in a transactional context, throwing an exception in the callback will cause the transaction to be rolled back
|
||||
* The callback is passed a GraphDatabaseService.
|
||||
* @param callback for executing graph operations transactionally, not null
|
||||
* @param <T> return type
|
||||
* @return whatever the callback chooses to return
|
||||
* @throws org.springframework.dao.DataAccessException subclasses
|
||||
*/
|
||||
<T> T update(GraphCallback<T> callback);
|
||||
|
||||
/**
|
||||
* Executes the callback in a NON-transactional context.
|
||||
|
||||
@@ -24,11 +24,14 @@ import org.neo4j.graphdb.traversal.TraversalDescription;
|
||||
import org.neo4j.helpers.collection.IterableWrapper;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.graph.UncategorizedGraphStoreException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class Neo4jTemplate implements Neo4jOperations {
|
||||
|
||||
private final boolean useExplictTransactions;
|
||||
|
||||
private final GraphDatabaseService graphDatabaseService;
|
||||
|
||||
private final Neo4jExceptionTranslator exceptionTranslator = new Neo4jExceptionTranslator();
|
||||
@@ -43,8 +46,33 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a template that only participates in outside transactions, no implicit transactions are started
|
||||
* @param graphDatabaseService the neo4j graph database
|
||||
* @return a Neo4jTemplate instance
|
||||
*/
|
||||
public static Neo4jTemplate templateWithExplictTransactions(GraphDatabaseService graphDatabaseService) {
|
||||
return new Neo4jTemplate(graphDatabaseService,true);
|
||||
}
|
||||
|
||||
/**
|
||||
* creates a template that creates implicit transactions for its methods, including exec. If an outside transaction
|
||||
* is running those participate in the outside transaction.
|
||||
* @param graphDatabaseService the neo4j graph database
|
||||
*/
|
||||
public Neo4jTemplate(final GraphDatabaseService graphDatabaseService) {
|
||||
this(graphDatabaseService,false);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param graphDatabaseService the neo4j graph database
|
||||
* @param useExplictTransactions if set the template only participates in outside transactions,
|
||||
* no internal implicit transactions are started
|
||||
* @return a Neo4jTemplate instance
|
||||
*/
|
||||
public Neo4jTemplate(final GraphDatabaseService graphDatabaseService, boolean useExplictTransactions) {
|
||||
notNull(graphDatabaseService, "graphDatabaseService");
|
||||
this.useExplictTransactions = useExplictTransactions;
|
||||
this.graphDatabaseService = graphDatabaseService;
|
||||
index = this.graphDatabaseService.index();
|
||||
}
|
||||
@@ -53,32 +81,29 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
return exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T update(final GraphCallback<T> callback) {
|
||||
notNull(callback, "callback");
|
||||
Transaction tx = graphDatabaseService.beginTx();
|
||||
try {
|
||||
T result = exec(callback);
|
||||
tx.success();
|
||||
return result;
|
||||
} catch (RuntimeException e) {
|
||||
tx.failure();
|
||||
throw e;
|
||||
} finally {
|
||||
tx.finish();
|
||||
private Transaction beginTx() {
|
||||
if (useExplictTransactions) {
|
||||
return new NullTransaction();
|
||||
}
|
||||
return graphDatabaseService.beginTx();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public <T> T exec(final GraphCallback<T> callback) {
|
||||
notNull(callback, "callback");
|
||||
Transaction tx = beginTx();
|
||||
try {
|
||||
return callback.doWithGraph(graphDatabaseService);
|
||||
T result = callback.doWithGraph(graphDatabaseService);
|
||||
tx.success();
|
||||
return result;
|
||||
} catch (RuntimeException e) {
|
||||
tx.failure();
|
||||
throw translateExceptionIfPossible(e);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
throw new UncategorizedGraphStoreException("Error executing callback",e);
|
||||
} finally {
|
||||
tx.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +118,7 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
|
||||
@Override
|
||||
public Node createNode(final Map<String, Object> properties, final String... indexFields) {
|
||||
return update(new GraphCallback<Node>() {
|
||||
return exec(new GraphCallback<Node>() {
|
||||
@Override
|
||||
public Node doWithGraph(GraphDatabaseService graph) throws Exception {
|
||||
Node node = graphDatabaseService.createNode();
|
||||
@@ -135,11 +160,11 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
@Override
|
||||
public <T extends PropertyContainer> T index(final String indexName, final T element, final String field, final Object value) {
|
||||
notNull(element, "element", field, "field", value, "value");
|
||||
update(new GraphCallback.WithoutResult() {
|
||||
exec(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabaseService graph) throws Exception {
|
||||
RelationshipIndex relationshipIndex = relationshipIndexAllowsNull(indexName);
|
||||
if (relationshipIndex != null && element instanceof Relationship) {
|
||||
if (element instanceof Relationship) {
|
||||
RelationshipIndex relationshipIndex = relationshipWriteIndex(indexName);
|
||||
relationshipIndex.add((Relationship) element, field, value);
|
||||
} else if (element instanceof Node) {
|
||||
nodeIndex(indexName).add((Node) element, field, value);
|
||||
@@ -151,11 +176,11 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
return element;
|
||||
}
|
||||
|
||||
private RelationshipIndex relationshipIndexAllowsNull(String indexName) {
|
||||
private RelationshipIndex relationshipWriteIndex(String indexName) {
|
||||
if (indexName == null) {
|
||||
return relationshipIndex("relationship");
|
||||
return index.forRelationships("relationship");
|
||||
}
|
||||
return relationshipIndex(indexName);
|
||||
return index.forRelationships(indexName);
|
||||
}
|
||||
|
||||
private RelationshipIndex relationshipIndex(String indexName) {
|
||||
@@ -267,7 +292,7 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
@Override
|
||||
public Relationship createRelationship(final Node startNode, final Node endNode, final RelationshipType relationshipType, final Map<String, Object> properties, final String... indexFields) {
|
||||
notNull(startNode, "startNode", endNode, "endNode", relationshipType, "relationshipType", properties, "properties");
|
||||
return update(new GraphCallback<Relationship>() {
|
||||
return exec(new GraphCallback<Relationship>() {
|
||||
@Override
|
||||
public Relationship doWithGraph(GraphDatabaseService graph) throws Exception {
|
||||
Relationship relationship = startNode.createRelationshipTo(endNode, relationshipType);
|
||||
@@ -289,4 +314,21 @@ public class Neo4jTemplate implements Neo4jOperations {
|
||||
}
|
||||
return primitive;
|
||||
}
|
||||
|
||||
private static class NullTransaction implements Transaction {
|
||||
@Override
|
||||
public void failure() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void success() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finish() {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ public class Neo4jTemplateApiTest {
|
||||
|
||||
@Test
|
||||
public void shouldExecuteCallbackInTransaction() throws Exception {
|
||||
Node refNode = template.update(new GraphCallback<Node>() {
|
||||
Node refNode = template.exec(new GraphCallback<Node>() {
|
||||
@Override
|
||||
public Node doWithGraph(GraphDatabaseService graph) throws Exception {
|
||||
Node referenceNode = graph.getReferenceNode();
|
||||
@@ -98,13 +98,13 @@ public class Neo4jTemplateApiTest {
|
||||
@Test
|
||||
public void shouldRollbackTransactionOnException() {
|
||||
try {
|
||||
template.update(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabaseService graph) throws Exception {
|
||||
graph.getReferenceNode().setProperty("test", "shouldRollbackTransactionOnException");
|
||||
throw new RuntimeException("please rollback");
|
||||
}
|
||||
});
|
||||
template.exec(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabaseService graph) throws Exception {
|
||||
graph.getReferenceNode().setProperty("test", "shouldRollbackTransactionOnException");
|
||||
throw new RuntimeException("please rollback");
|
||||
}
|
||||
});
|
||||
} catch(RuntimeException re){
|
||||
//ignore
|
||||
}
|
||||
@@ -117,7 +117,7 @@ public class Neo4jTemplateApiTest {
|
||||
new TransactionTemplate(tm).execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(final TransactionStatus status) {
|
||||
template.update(new GraphCallback.WithoutResult() {
|
||||
template.exec(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabaseService graph) throws Exception {
|
||||
graph.getReferenceNode().setProperty("test", "shouldRollbackTransactionOnException");
|
||||
@@ -141,6 +141,7 @@ public class Neo4jTemplateApiTest {
|
||||
|
||||
@Test(expected = DataAccessException.class)
|
||||
public void shouldConvertMissingTransactionExceptionToDataAccessException() {
|
||||
Neo4jTemplate template = new Neo4jTemplate(graphDatabase, true);
|
||||
template.exec(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabaseService graph) throws Exception {
|
||||
@@ -150,6 +151,7 @@ public class Neo4jTemplateApiTest {
|
||||
}
|
||||
@Test(expected = DataAccessException.class)
|
||||
public void shouldConvertNotFoundExceptionToDataAccessException() {
|
||||
Neo4jTemplate template = new Neo4jTemplate(graphDatabase, true);
|
||||
template.exec(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabaseService graph) throws Exception {
|
||||
|
||||
@@ -27,8 +27,9 @@ public class Neo4jTemplateTest extends NeoApiTest {
|
||||
@Test
|
||||
public void testSingleNode() {
|
||||
final Neo4jOperations template = new Neo4jTemplate(graph);
|
||||
template.update(new GraphCallback<Void>() {
|
||||
public Void doWithGraph(GraphDatabaseService graph) throws Exception {
|
||||
template.exec(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabaseService graph) throws Exception {
|
||||
Node refNode = graph.getReferenceNode();
|
||||
// TODO easy API Node node = graph.createNode(Property._("name", "Test"), Property._("size", 100));
|
||||
Node node = graph.createNode();
|
||||
@@ -40,17 +41,15 @@ public class Neo4jTemplateTest extends NeoApiTest {
|
||||
final Node nodeByRelationship = toTestNode.getEndNode();
|
||||
assertEquals("Test", nodeByRelationship.getProperty("name"));
|
||||
assertEquals(100, nodeByRelationship.getProperty("size"));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
template.update(new GraphCallback<Void>() {
|
||||
public Void doWithGraph(GraphDatabaseService graph) throws Exception {
|
||||
template.exec(new GraphCallback.WithoutResult() {
|
||||
public void doWithGraphWithoutResult(GraphDatabaseService graph) throws Exception {
|
||||
Node refNode = graph.getReferenceNode();
|
||||
final Relationship toTestNode = refNode.getSingleRelationship(HAS, Direction.OUTGOING);
|
||||
final Node nodeByRelationship = toTestNode.getEndNode();
|
||||
assertEquals("Test", nodeByRelationship.getProperty("name"));
|
||||
assertEquals(100, nodeByRelationship.getProperty("size"));
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -59,7 +58,7 @@ public class Neo4jTemplateTest extends NeoApiTest {
|
||||
public void testRollback() {
|
||||
final Neo4jOperations template = new Neo4jTemplate(graph);
|
||||
try {
|
||||
template.update(new GraphCallback.WithoutResult() {
|
||||
template.exec(new GraphCallback.WithoutResult() {
|
||||
@Override
|
||||
public void doWithGraphWithoutResult(GraphDatabaseService graph) throws Exception {
|
||||
Node node = graph.getReferenceNode();
|
||||
|
||||
@@ -26,21 +26,21 @@ public abstract class NeoApiTest {
|
||||
|
||||
private void clear() {
|
||||
try {
|
||||
template.update(new GraphCallback<Void>() {
|
||||
public Void doWithGraph(GraphDatabaseService graph) throws Exception {
|
||||
for (Node node : graph.getAllNodes()) {
|
||||
for (Relationship relationship : node.getRelationships()) {
|
||||
relationship.delete();
|
||||
template.exec(new GraphCallback<Void>() {
|
||||
public Void doWithGraph(GraphDatabaseService graph) throws Exception {
|
||||
for (Node node : graph.getAllNodes()) {
|
||||
for (Relationship relationship : node.getRelationships()) {
|
||||
relationship.delete();
|
||||
}
|
||||
}
|
||||
Node referenceNode = graph.getReferenceNode();
|
||||
for (Node node : graph.getAllNodes()) {
|
||||
if (node.equals(referenceNode)) continue;
|
||||
node.delete();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
Node referenceNode = graph.getReferenceNode();
|
||||
for (Node node : graph.getAllNodes()) {
|
||||
if (node.equals(referenceNode)) continue;
|
||||
node.delete();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
});
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
// ignore
|
||||
|
||||
@@ -24,7 +24,7 @@ public class NeoTraversalTest extends NeoApiTest {
|
||||
|
||||
@Test
|
||||
public void testSimpleTraverse() {
|
||||
template.update(new GraphCallback<Void>() {
|
||||
template.exec(new GraphCallback<Void>() {
|
||||
public Void doWithGraph(GraphDatabaseService graph) throws Exception {
|
||||
createFamily();
|
||||
return null;
|
||||
|
||||
Reference in New Issue
Block a user