enititymanager persistenceprovider, EM-Factory

This commit is contained in:
Michael Hunger
2010-08-24 21:42:48 +02:00
parent 3b54769f87
commit 6cfecbcba5
9 changed files with 353 additions and 7 deletions

View File

@@ -134,6 +134,11 @@
<artifactId>spring-jdbc</artifactId> <artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version> <version>${spring.version}</version>
</dependency> </dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId> <artifactId>spring-tx</artifactId>

View File

@@ -2,6 +2,7 @@ package org.springframework.persistence.graph.neo4j;
import org.neo4j.graphdb.GraphDatabaseService; import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node; import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.kernel.EmbeddedGraphDatabase; import org.neo4j.kernel.EmbeddedGraphDatabase;
import org.springframework.persistence.support.EntityInstantiator; import org.springframework.persistence.support.EntityInstantiator;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@@ -15,7 +16,7 @@ import javax.transaction.*;
* @since 20.08.2010 * @since 20.08.2010
* TODO Relationships * TODO Relationships
*/ */
@Service //@Service
public class Neo4jEntityManager implements EntityManager { public class Neo4jEntityManager implements EntityManager {
@Resource @Resource
GraphDatabaseService graphDatabaseService; GraphDatabaseService graphDatabaseService;
@@ -24,7 +25,15 @@ public class Neo4jEntityManager implements EntityManager {
EntityInstantiator<NodeBacked, Node> nodeInstantiator; EntityInstantiator<NodeBacked, Node> nodeInstantiator;
private volatile boolean closed; private volatile boolean closed;
private Node nodeFor(Object entity) { public Neo4jEntityManager(final GraphDatabaseService graphDatabaseService, final EntityInstantiator<NodeBacked, Node> nodeInstantiator) {
this.graphDatabaseService = graphDatabaseService;
this.nodeInstantiator = nodeInstantiator;
}
public Neo4jEntityManager() {
}
private Node nodeFor(final Object entity) {
checkClosed(); checkClosed();
if (!(entity instanceof NodeBacked)) throw new IllegalArgumentException("Not a nodebacked entity " + entity); if (!(entity instanceof NodeBacked)) throw new IllegalArgumentException("Not a nodebacked entity " + entity);
final Node node = ((NodeBacked) entity).getUnderlyingNode(); final Node node = ((NodeBacked) entity).getUnderlyingNode();
@@ -45,7 +54,11 @@ public class Neo4jEntityManager implements EntityManager {
@Override @Override
public void remove(final Object entity) { 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"}) @SuppressWarnings({"unchecked"})

View File

@@ -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<NodeBacked, Node> nodeInstantiator;
public Neo4jEntityManagerFactory() {
}
public Neo4jEntityManagerFactory(GraphDatabaseService graphDatabaseService, EntityInstantiator<NodeBacked, Node> 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;
}
}

View File

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

View File

@@ -62,9 +62,6 @@ public aspect Neo4jNodeBacking extends AbstractTypeAnnotatingMixinFields<Graph.E
pointcut arbitraryUserConstructorOfNodeBackedObject(NodeBacked entity) : pointcut arbitraryUserConstructorOfNodeBackedObject(NodeBacked entity) :
execution((@Graph.Entity *).new(..)) && execution((@Graph.Entity *).new(..)) &&
!execution((@Graph.Entity *).new(Node)) && !execution((@Graph.Entity *).new(Node)) &&
this(entity);
execution((@GraphEntity *).new(..)) &&
!execution((@GraphEntity *).new(Node)) &&
this(entity); // && !cflow(execution(* fromStateInternal(..)); this(entity); // && !cflow(execution(* fromStateInternal(..));

View File

@@ -0,0 +1,34 @@
package org.springframework.persistence.graph.neo4j;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.springframework.persistence.support.EntityInstantiator;
import javax.annotation.Resource;
import javax.persistence.EntityManagerFactory;
import javax.persistence.spi.PersistenceProvider;
import javax.persistence.spi.PersistenceUnitInfo;
import java.util.Map;
/**
* @author Michael Hunger
* @since 23.08.2010
*/
// todo handle additinal info + database path
public class Neo4jPersistenceProvider implements PersistenceProvider {
@Resource
GraphDatabaseService graphDatabaseService;
@Resource
EntityInstantiator<NodeBacked, Node> 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);
}
}

View File

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

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.0" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="neo4j-persistence" transaction-type="RESOURCE_LOCAL">
<provider>org.springframework.persistence.graph.neo4j.Neo4jPersistenceProvider</provider>
<properties>
<property name="neo4j.path" value="test/data"/> <!-- TODO handle this -->
</properties>
</persistence-unit>
</persistence>

View File

@@ -125,5 +125,15 @@
</bean> </bean>
<tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/> <tx:annotation-driven mode="aspectj" transaction-manager="transactionManager"/>
<bean class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" id="entityManagerFactory">
<property name="jpaDialect">
<bean class="org.springframework.persistence.graph.neo4j.Neo4jJpaDialect"/>
</property>
<property name="persistenceProvider">
<bean class="org.springframework.persistence.graph.neo4j.Neo4jPersistenceProvider"/>
</property>
</bean>
<!--bean id="neoEntityManager" class="org.springframework.persistence.graph.neo4j.Neo4jEntityManager" scope="prototype"/-->
</beans> </beans>