DATAGRAPH-546 - Add Neo4jOperations.saveOnly
This commit is contained in:
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 ?
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user