removed the update method, added an explicit flag for participating in explicit outside transaction

This commit is contained in:
Michael Hunger
2011-02-23 22:45:53 +01:00
parent 887ed628dc
commit 402e5114ca
6 changed files with 96 additions and 62 deletions

View File

@@ -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.

View File

@@ -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() {
}
}
}

View File

@@ -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 {

View File

@@ -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();

View File

@@ -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

View File

@@ -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;