DATAGRAPH-546 - Add Neo4jOperations.saveOnly

This commit is contained in:
Michael Hunger
2015-03-15 01:05:31 +01:00
parent f28eb2a840
commit caab9d08b4
10 changed files with 53 additions and 11 deletions

View File

@@ -96,7 +96,7 @@ public class RelatedToViaCollectionFieldAccessorFactory implements FieldAccessor
private void persistEntities( final Collection<Object> relationshipEntities, RelationshipType relationshipType ) {
for (Object entity : relationshipEntities) {
template.save(entity, relationshipType);
template.save(entity, relationshipType, template.getMappingPolicy(entity));
}
}

View File

@@ -89,7 +89,7 @@ public class RelatedToViaSingleFieldAccessorFactory implements FieldAccessorFact
private void persistEntities( final Collection<Object> relationshipEntities, RelationshipType relationshipType ) {
for (Object entity : relationshipEntities) {
template.save(entity, relationshipType);
template.save(entity, relationshipType, template.getMappingPolicy(entity));
}
}

View File

@@ -27,9 +27,10 @@ import static java.util.Arrays.asList;
public interface MappingPolicy {
enum Option {
FIELD_DIRECT, SHOULD_LOAD,NO_TYPE_CHECK
FIELD_DIRECT, SHOULD_LOAD,NO_TYPE_CHECK, NO_RELOAD
}
boolean accessField();
boolean noReload();
boolean shouldLoad();
boolean noTypeCheck();
MappingPolicy combineWith(MappingPolicy mappingPolicy);
@@ -53,6 +54,11 @@ public interface MappingPolicy {
return options.contains(Option.FIELD_DIRECT);
}
@Override
public boolean noReload() {
return options.contains(Option.NO_RELOAD);
}
@Override
public boolean shouldLoad() {
return options.contains(Option.SHOULD_LOAD);
@@ -111,6 +117,7 @@ public interface MappingPolicy {
}
public MappingPolicy LOAD_POLICY = new DefaultMappingPolicy(Option.SHOULD_LOAD);
public MappingPolicy NO_RELOAD_POLICY = new DefaultMappingPolicy(Option.NO_RELOAD);
public MappingPolicy DEFAULT_POLICY = new DefaultMappingPolicy();
public MappingPolicy MAP_FIELD_DIRECT_POLICY = new DefaultMappingPolicy(Option.FIELD_DIRECT);
public MappingPolicy NO_TYPE_CHECK_POLICY = new DefaultMappingPolicy(Option.NO_TYPE_CHECK);

View File

@@ -91,6 +91,11 @@ public abstract class AbstractGraphRepository<S extends PropertyContainer, T> im
return template.save(entity);
}
@Transactional
public <U extends T> void saveOnly(U entity) {
template.saveOnly(entity);
}
@Override
@Transactional
public <U extends T> Iterable<U> save(Iterable<U> entities) {

View File

@@ -55,4 +55,6 @@ public interface CRUDRepository<T> extends PagingAndSortingRepository<T, Long> {
Result<T> query(String query, Map<String, Object> params);
<U extends T> void saveOnly(U entity);
}

View File

@@ -351,13 +351,18 @@ public class Neo4jTemplate implements Neo4jOperations, ApplicationContextAware {
@Override
@SuppressWarnings("unchecked")
public <T> T save(T entity) {
return save(entity, null);
return save(entity, null, getMappingPolicy(entity));
}
@Override
public <T> void saveOnly(T entity) {
save(entity, null, getMappingPolicy(entity).combineWith(MappingPolicy.NO_RELOAD_POLICY));
}
@SuppressWarnings("unchecked")
public <T> T save(T entity, final RelationshipType annotationProvidedRelationshipType) {
public <T> T save(T entity, final RelationshipType annotationProvidedRelationshipType, MappingPolicy mappingPolicy) {
if (applicationContext != null) applicationContext.publishEvent(new BeforeSaveEvent<T>(this, entity));
T t = (T) infrastructure.getEntityPersister().persist(entity, getMappingPolicy(entity), this, annotationProvidedRelationshipType);
T t = (T) infrastructure.getEntityPersister().persist(entity, mappingPolicy, this, annotationProvidedRelationshipType);
if (applicationContext != null) applicationContext.publishEvent(new AfterSaveEvent<T>(this, entity));
return t;
}

View File

@@ -245,12 +245,14 @@ public class Neo4jEntityPersister implements EntityPersister, Neo4jEntityConvert
if (isNodeEntity(type)) {
final Node node = this.<Node>getPersistentState(entity);
this.nodeConverter.write(entity, node,mappingPolicy, template, null );
if (mappingPolicy.noReload()) return null;
return createEntityFromState(getPersistentState(entity),type, getMappingPolicy(type), template);
//return entity; // TODO ?
}
if (isRelationshipEntity(type)) {
final Relationship relationship = this.<Relationship>getPersistentState(entity);
this.relationshipConverter.write(entity, relationship,mappingPolicy, template, annotationProvidedRelationshipType );
if (mappingPolicy.noReload()) return null;
return createEntityFromState(getPersistentState(entity),type, getMappingPolicy(type), template);
// return entity; // TODO ?
}

View File

@@ -261,6 +261,13 @@ public interface Neo4jOperations {
*/
<T> T save(T entity);
/**
* Stores the given entity in the graph, if the entity is already attached to the graph, the node is updated, otherwise
* a new node is created. Attached relationships will be cascaded.
* This method is also provided by the appropriate repository.
*/
<T> void saveOnly(T entity);
Number getId(Object entity);
/**

View File

@@ -300,6 +300,16 @@ public class EntityNeo4jTemplateTests extends EntityTestBase {
assertEquals("created node with name", "Thomas", node.getProperty("name"));
}
@Test @Transactional
public void testSaveOnly() throws Exception {
final Person thomas = new Person("Thomas", 30);
neo4jOperations.saveOnly(thomas);
final Node node = getNodeState(thomas);
assertNotNull("created node",node);
assertEquals("created node with id", (Long) node.getId(), thomas.getId());
assertEquals("created node with name", "Thomas", node.getProperty("name"));
}
static abstract class ManagedTestEntity implements ManagedEntity {}
@Test @Transactional
public void testIsManaged() throws Exception {

View File

@@ -50,7 +50,10 @@ Neo4jOperations neo = new Neo4jTemplate(graphDatabase);
== Entity-Persistence
`Neo4jTemplate` allows to `save`, `find(One/All)`, `count`, `delete` and `projectTo` entities. It provides the stored type information via `getStoredJavaType` and can `fetch` lazy-loaded entities or `load` them altogether.
`Neo4jTemplate` allows to `save`,`saveOnly`, `find(One/All)`, `count`, `delete` and `projectTo` entities. It provides the stored type information via `getStoredJavaType` and can `fetch` lazy-loaded entities or `load` them altogether.
The `saveOnly` method will not reload the entity from the database, saving a number of requests that are often not necessary.
It's also available in the `GraphRepository` interface.
== Result
@@ -86,7 +89,8 @@ Neo4j Template offers basic lifecycle events via Spring's event mechanism using
* BeforeSaveEvent
* AfterSaveEvent
* DeleteEvent - after the event has been deleted
* BeforeDeleteEvent
* AfterDeleteEvent
The following example demonstrates how to hook into the application lifecycle and register listeners that perform behaviour across types of entities during this life cycle:
@@ -121,10 +125,10 @@ public class ApplicationConfig extends Neo4jConfiguration {
}
@Bean
ApplicationListener<DeleteEvent> deleteEventApplicationListener() {
return new ApplicationListener<DeleteEvent>() {
ApplicationListener<BeforeDeleteEvent> beforeDeleteEventApplicationListener() {
return new ApplicationListener<BeforeDeleteEvent>() {
@Override
public void onApplicationEvent(DeleteEvent event) {
public void onApplicationEvent(BeforeDeleteEvent event) {
AcmeEntity entity = (AcmeEntity) event.getEntity();
auditLog.onEventDeleted(entity);
}