diff --git a/pom.xml b/pom.xml
index 027ad9e7e..da3f1da7e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -134,6 +134,11 @@
spring-jdbc
${spring.version}
+
+ org.springframework
+ spring-orm
+ ${spring.version}
+
org.springframework
spring-tx
diff --git a/src/main/java/org/springframework/persistence/graph/neo4j/Neo4jEntityManager.java b/src/main/java/org/springframework/persistence/graph/neo4j/Neo4jEntityManager.java
index 2d9ad50bf..2b6db26a1 100644
--- a/src/main/java/org/springframework/persistence/graph/neo4j/Neo4jEntityManager.java
+++ b/src/main/java/org/springframework/persistence/graph/neo4j/Neo4jEntityManager.java
@@ -2,6 +2,7 @@ package org.springframework.persistence.graph.neo4j;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
+import org.neo4j.graphdb.Relationship;
import org.neo4j.kernel.EmbeddedGraphDatabase;
import org.springframework.persistence.support.EntityInstantiator;
import org.springframework.stereotype.Service;
@@ -15,7 +16,7 @@ import javax.transaction.*;
* @since 20.08.2010
* TODO Relationships
*/
-@Service
+//@Service
public class Neo4jEntityManager implements EntityManager {
@Resource
GraphDatabaseService graphDatabaseService;
@@ -24,7 +25,15 @@ public class Neo4jEntityManager implements EntityManager {
EntityInstantiator nodeInstantiator;
private volatile boolean closed;
- private Node nodeFor(Object entity) {
+ public Neo4jEntityManager(final GraphDatabaseService graphDatabaseService, final EntityInstantiator nodeInstantiator) {
+ this.graphDatabaseService = graphDatabaseService;
+ this.nodeInstantiator = nodeInstantiator;
+ }
+
+ public Neo4jEntityManager() {
+ }
+
+ private Node nodeFor(final Object entity) {
checkClosed();
if (!(entity instanceof NodeBacked)) throw new IllegalArgumentException("Not a nodebacked entity " + entity);
final Node node = ((NodeBacked) entity).getUnderlyingNode();
@@ -45,7 +54,11 @@ public class Neo4jEntityManager implements EntityManager {
@Override
public void remove(final Object entity) {
- nodeFor(entity).delete();
+ final Node node = nodeFor(entity);
+ for (final Relationship r : node.getRelationships()) {
+ r.delete();
+ }
+ node.delete();
}
@SuppressWarnings({"unchecked"})
diff --git a/src/main/java/org/springframework/persistence/graph/neo4j/Neo4jEntityManagerFactory.java b/src/main/java/org/springframework/persistence/graph/neo4j/Neo4jEntityManagerFactory.java
new file mode 100644
index 000000000..19f7d1741
--- /dev/null
+++ b/src/main/java/org/springframework/persistence/graph/neo4j/Neo4jEntityManagerFactory.java
@@ -0,0 +1,50 @@
+package org.springframework.persistence.graph.neo4j;
+
+import org.neo4j.graphdb.GraphDatabaseService;
+import org.neo4j.graphdb.Node;
+import org.springframework.beans.factory.annotation.Configurable;
+import org.springframework.persistence.support.EntityInstantiator;
+
+import javax.annotation.Resource;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import java.util.Map;
+
+/**
+ * @author Michael Hunger
+ * @since 23.08.2010
+ */
+public class Neo4jEntityManagerFactory implements EntityManagerFactory {
+ @Resource
+ GraphDatabaseService graphDatabaseService;
+ @Resource
+ EntityInstantiator nodeInstantiator;
+
+ public Neo4jEntityManagerFactory() {
+ }
+
+ public Neo4jEntityManagerFactory(GraphDatabaseService graphDatabaseService, EntityInstantiator nodeInstantiator) {
+ this.graphDatabaseService = graphDatabaseService;
+ this.nodeInstantiator = nodeInstantiator;
+ }
+
+ @Override
+ public EntityManager createEntityManager() {
+ return new Neo4jEntityManager(graphDatabaseService,nodeInstantiator);
+ }
+
+ /* TODO handle different directories for target datastore */
+ @Override
+ public EntityManager createEntityManager(Map map) {
+ return new Neo4jEntityManager(graphDatabaseService,nodeInstantiator);
+ }
+
+ @Override
+ public void close() {
+ }
+
+ @Override
+ public boolean isOpen() {
+ return true;
+ }
+}
diff --git a/src/main/java/org/springframework/persistence/graph/neo4j/Neo4jJpaDialect.java b/src/main/java/org/springframework/persistence/graph/neo4j/Neo4jJpaDialect.java
new file mode 100644
index 000000000..04977cbba
--- /dev/null
+++ b/src/main/java/org/springframework/persistence/graph/neo4j/Neo4jJpaDialect.java
@@ -0,0 +1,70 @@
+package org.springframework.persistence.graph.neo4j;
+
+import org.springframework.dao.DataAccessException;
+import org.springframework.jdbc.datasource.ConnectionHandle;
+import org.springframework.orm.jpa.EntityManagerFactoryPlusOperations;
+import org.springframework.orm.jpa.EntityManagerPlusOperations;
+import org.springframework.orm.jpa.JpaDialect;
+import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.TransactionException;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.PersistenceException;
+import java.sql.SQLException;
+
+/**
+ * @author Michael Hunger
+ * @since 23.08.2010
+ */
+public class Neo4jJpaDialect implements JpaDialect {
+ @Override
+ public boolean supportsEntityManagerFactoryPlusOperations() {
+ return false;
+ }
+
+ @Override
+ public boolean supportsEntityManagerPlusOperations() {
+ return false;
+ }
+
+ @Override
+ public EntityManagerFactoryPlusOperations getEntityManagerFactoryPlusOperations(final EntityManagerFactory entityManagerFactory) {
+ return null;
+ }
+
+ @Override
+ public EntityManagerPlusOperations getEntityManagerPlusOperations(final EntityManager entityManager) {
+ return null;
+ }
+
+ // todo
+ @Override
+ public Object beginTransaction(final EntityManager entityManager, final TransactionDefinition transactionDefinition) throws PersistenceException, SQLException, TransactionException {
+ return null;
+ }
+
+ @Override
+ public Object prepareTransaction(final EntityManager entityManager, final boolean b, final String s) throws PersistenceException {
+ return null;
+ }
+
+ @Override
+ public void cleanupTransaction(final Object o) {
+ }
+
+ @Override
+ public ConnectionHandle getJdbcConnection(final EntityManager entityManager, final boolean b) throws PersistenceException, SQLException {
+ return null;
+ }
+
+ @Override
+ public void releaseJdbcConnection(final ConnectionHandle connectionHandle, final EntityManager entityManager) throws PersistenceException, SQLException {
+ }
+
+ // todo
+ @Override
+ public DataAccessException translateExceptionIfPossible(final RuntimeException e) {
+ return null;
+ }
+}
diff --git a/src/main/java/org/springframework/persistence/graph/neo4j/Neo4jNodeBacking.aj b/src/main/java/org/springframework/persistence/graph/neo4j/Neo4jNodeBacking.aj
index bb4316b2f..610a0ccdf 100644
--- a/src/main/java/org/springframework/persistence/graph/neo4j/Neo4jNodeBacking.aj
+++ b/src/main/java/org/springframework/persistence/graph/neo4j/Neo4jNodeBacking.aj
@@ -62,9 +62,6 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields nodeInstantiator;
+
+ @Override
+ public EntityManagerFactory createEntityManagerFactory(String emName, Map map) {
+ return new Neo4jEntityManagerFactory(graphDatabaseService,nodeInstantiator);
+ }
+
+ @Override
+ public EntityManagerFactory createContainerEntityManagerFactory(PersistenceUnitInfo info, Map map) {
+ return new Neo4jEntityManagerFactory(graphDatabaseService,nodeInstantiator);
+ }
+}
diff --git a/src/test/java/org/springframework/persistence/graph/neo4j/Neo4jEntityManagerTest.java b/src/test/java/org/springframework/persistence/graph/neo4j/Neo4jEntityManagerTest.java
new file mode 100644
index 000000000..2efd5053e
--- /dev/null
+++ b/src/test/java/org/springframework/persistence/graph/neo4j/Neo4jEntityManagerTest.java
@@ -0,0 +1,157 @@
+package org.springframework.persistence.graph.neo4j;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import javax.annotation.Resource;
+import javax.persistence.EntityManager;
+import javax.persistence.EntityTransaction;
+import javax.persistence.PersistenceContext;
+
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.neo4j.graphdb.GraphDatabaseService;
+import org.neo4j.graphdb.Node;
+import org.springframework.dao.InvalidDataAccessApiUsageException;
+import org.springframework.persistence.test.Person;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * @author Michael Hunger
+ * @since 20.08.2010
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {"classpath:org/springframework/persistence/test/graph/Neo4jGraphPersistenceTest-context.xml"})
+@Transactional
+public class Neo4jEntityManagerTest {
+ @Resource
+ GraphDatabaseService graphDatabaseService;
+ @PersistenceContext(unitName="neo4j-persistence")
+ EntityManager entityManager;
+
+ Person person;
+ private Node node;
+
+ @Before
+ public void cleanDb() {
+ Neo4jHelper.cleanDb(graphDatabaseService);
+ node = graphDatabaseService.createNode();
+ person = new Person(node);
+ }
+
+ @Test
+ public void testPersist() throws Exception {
+ entityManager.persist(person);
+ }
+
+ @Test
+ public void testMerge() throws Exception {
+ Person merged=entityManager.merge(person);
+ assertEquals(person,merged);
+ }
+ @Ignore
+ @Test
+ public void testRemove() throws Exception {
+ long nodeId=node.getId();
+ entityManager.remove(person);
+ final Node foundNode = graphDatabaseService.getNodeById(nodeId);
+ assertNull(foundNode);
+ }
+ @Test
+ public void testFind() throws Exception {
+ final Person found = entityManager.find(Person.class, node.getId());
+ assertEquals(person,found);
+ }
+
+ @Test
+ public void testGetReference() throws Exception {
+ final Person found = entityManager.getReference(Person.class, node.getId());
+ assertEquals(person,found);
+ }
+
+ @Test
+ public void testFlush() throws Exception {
+ }
+
+ @Test
+ public void testSetFlushMode() throws Exception {
+ }
+
+ @Test
+ public void testGetFlushMode() throws Exception {
+ }
+
+ @Test
+ public void testLock() throws Exception {
+ }
+
+ @Test
+ public void testRefresh() throws Exception {
+ entityManager.refresh(person);
+ assertEquals(node, person.getUnderlyingNode());
+ }
+ @Test
+ public void testClear() throws Exception {
+ }
+
+ @Test(expected=InvalidDataAccessApiUsageException.class)
+ public void removeThrowsErrorForNonNodeBacked() throws Exception {
+ entityManager.remove(new Object());
+ }
+
+ @Test
+ public void testContains() throws Exception {
+ final Person p2 = new Person("Rod",39);
+ assertTrue(entityManager.contains(person));
+ assertTrue(entityManager.contains(p2));
+ assertFalse(entityManager.contains(new Object()));
+ }
+/*
+ @Test
+ public void testCreateQuery() throws Exception {
+ }
+
+ @Test
+ public void testCreateNamedQuery() throws Exception {
+ }
+
+ @Test
+ public void testCreateNativeQuery() throws Exception {
+ }
+
+ @Test
+ public void testJoinTransaction() throws Exception {
+ }
+*/
+ @Test
+ public void testGetDelegate() throws Exception {
+ assertTrue(entityManager.getDelegate() instanceof GraphDatabaseService);
+ }
+
+ @Test(expected=InvalidDataAccessApiUsageException.class)
+ public void testClose() throws Exception {
+ entityManager.close();
+ assertFalse(entityManager.isOpen());
+ entityManager.refresh(person);
+ }
+
+ @Test
+ public void testIsOpen() throws Exception {
+ assertTrue(entityManager.isOpen());
+ }
+
+ @Test
+ public void testGetTransaction() throws Exception {
+ final EntityTransaction transaction = entityManager.getTransaction();
+ assertFalse(transaction.getRollbackOnly());
+ person.setName("Michael");
+ entityManager.persist(person);
+ transaction.setRollbackOnly();
+ }
+}
diff --git a/src/test/resources/META-INF/persistence.xml b/src/test/resources/META-INF/persistence.xml
new file mode 100644
index 000000000..3c50f0d48
--- /dev/null
+++ b/src/test/resources/META-INF/persistence.xml
@@ -0,0 +1,10 @@
+
+
+
+
+ org.springframework.persistence.graph.neo4j.Neo4jPersistenceProvider
+
+
+
+
+
diff --git a/src/test/resources/org/springframework/persistence/test/graph/Neo4jGraphPersistenceTest-context.xml b/src/test/resources/org/springframework/persistence/test/graph/Neo4jGraphPersistenceTest-context.xml
index 559adff73..682ba9340 100644
--- a/src/test/resources/org/springframework/persistence/test/graph/Neo4jGraphPersistenceTest-context.xml
+++ b/src/test/resources/org/springframework/persistence/test/graph/Neo4jGraphPersistenceTest-context.xml
@@ -125,5 +125,15 @@
-
+
+
+
+
+
+
+
+
+
+
+