DATAGRAPH-685 - LoadByProperty depth support in Neo4jOperations.
This commit is contained in:
@@ -95,6 +95,23 @@ public interface Neo4jOperations {
|
||||
*/
|
||||
<T> T loadByProperty(Class<T> type, String propertyName, Object propertyValue);
|
||||
|
||||
/**
|
||||
* Retrieves the entity of the specified type that contains a property matching the given name with the given value.
|
||||
* This method assumes that the requested property/value combination will be unique for all entities of this type in
|
||||
* the database and will throw an exception unless exactly one result is found. If several entities are expected to
|
||||
* be returned then use {@link #loadAllByProperty(Class, String, Object)} instead.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param propertyName The name of the property on the entity against which to match the given value
|
||||
* @param propertyValue The value of the named property against which to match entities
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related entities.
|
||||
* A value of 0 just loads the object's properties and no related entities. A value of -1 implies no depth limit.
|
||||
* @return The instance of T corresponding to the entity that matches the given property, never <code>null</code>
|
||||
* @throws NotFoundException if there are no matching entities
|
||||
* @throws IllegalStateException if there's more than one matching entity
|
||||
*/
|
||||
<T> T loadByProperty(Class<T> type, String propertyName, Object propertyValue, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the specified type that contain a property matching the given name with the given value.
|
||||
*
|
||||
@@ -106,6 +123,19 @@ public interface Neo4jOperations {
|
||||
*/
|
||||
<T> Collection<T> loadAllByProperty(Class<T> type, String propertyName, Object propertyValue);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the specified type that contain a property matching the given name with the given value.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param propertyName The name of the property on the entity against which to match the given value
|
||||
* @param propertyValue The value of the named property against which to match entities
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related entities.
|
||||
* A value of 0 just loads the object's properties and no related entities. A value of -1 implies no depth limit.
|
||||
* @return A {@link Collection} containing all the entities that match the given property or an empty {@link Collection} if
|
||||
* there aren't any matches, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAllByProperty(Class<T> type, String propertyName, Object propertyValue, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves the entity of the specified type that contains properties matching the ones supplied with given name and value.
|
||||
* This method assumes that the requested property/value combinations will be unique for all entities of this type in
|
||||
@@ -120,6 +150,22 @@ public interface Neo4jOperations {
|
||||
*/
|
||||
<T> T loadByProperties(Class<T> type, Filters parameters);
|
||||
|
||||
/**
|
||||
* Retrieves the entity of the specified type that contains properties matching the ones supplied with given name and value.
|
||||
* This method assumes that the requested property/value combinations will be unique for all entities of this type in
|
||||
* the database and will throw an exception unless exactly one result is found. If several entities are expected to
|
||||
* be returned then use {@link #loadAllByProperty(Class, String, Object)} instead.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param parameters The parameters to filter by
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related entities.
|
||||
* A value of 0 just loads the object's properties and no related entities. A value of -1 implies no depth limit.
|
||||
* @return The instance of T corresponding to the entity that matches the given properties, never <code>null</code>
|
||||
* @throws NotFoundException if there are no matching entities
|
||||
* @throws IllegalStateException if there's more than one matching entity
|
||||
*/
|
||||
<T> T loadByProperties(Class<T> type, Filters parameters, int depth);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the specified type that contain a properties matching the ones supplied with given name and value.
|
||||
*
|
||||
@@ -130,6 +176,18 @@ public interface Neo4jOperations {
|
||||
*/
|
||||
<T> Collection<T> loadAllByProperties(Class<T> type, Filters parameters);
|
||||
|
||||
/**
|
||||
* Retrieves all the entities of the specified type that contain a properties matching the ones supplied with given name and value.
|
||||
*
|
||||
* @param type The type of entity to load
|
||||
* @param parameters The parameters to filter by
|
||||
* @param depth The maximum number of relationships away from each loaded object to follow when loading related entities.
|
||||
* A value of 0 just loads the object's properties and no related entities. A value of -1 implies no depth limit.
|
||||
* @return A {@link Collection} containing all the entities that match the given properties or an empty {@link Collection} if
|
||||
* there aren't any matches, never <code>null</code>
|
||||
*/
|
||||
<T> Collection<T> loadAllByProperties(Class<T> type, Filters parameters, int depth);
|
||||
|
||||
/**
|
||||
* Saves the specified entity in the graph database. If the entity is currently transient then the persistent version of
|
||||
* the entity will be returned, containing its new graph ID.
|
||||
|
||||
@@ -138,8 +138,13 @@ public class Neo4jTemplate implements Neo4jOperations, ApplicationEventPublisher
|
||||
|
||||
@Override
|
||||
public <T> T loadByProperty(Class<T> type, String propertyName, Object propertyValue) {
|
||||
return loadByProperty(type, propertyName, propertyValue, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T loadByProperty(Class<T> type, String propertyName, Object propertyValue, int depth) {
|
||||
try {
|
||||
return getSingle(loadAllByProperty(type, propertyName, propertyValue));
|
||||
return getSingle(loadAllByProperty(type, propertyName, propertyValue, depth));
|
||||
} catch (Exception e) {
|
||||
throw Neo4jOgmExceptionTranslator.translateExceptionIfPossible(e);
|
||||
}
|
||||
@@ -164,8 +169,13 @@ public class Neo4jTemplate implements Neo4jOperations, ApplicationEventPublisher
|
||||
|
||||
@Override
|
||||
public <T> T loadByProperties(Class<T> type, Filters parameters) {
|
||||
return loadByProperties(type, parameters, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T loadByProperties(Class<T> type, Filters parameters, int depth) {
|
||||
try {
|
||||
return getSingle(loadAllByProperties(type, parameters));
|
||||
return getSingle(loadAllByProperties(type, parameters, depth));
|
||||
} catch (Exception e) {
|
||||
throw Neo4jOgmExceptionTranslator.translateExceptionIfPossible(e);
|
||||
}
|
||||
@@ -173,8 +183,13 @@ public class Neo4jTemplate implements Neo4jOperations, ApplicationEventPublisher
|
||||
|
||||
@Override
|
||||
public <T> Collection<T> loadAllByProperties(Class<T> type, Filters parameters) {
|
||||
return loadAllByProperties(type, parameters, 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> Collection<T> loadAllByProperties(Class<T> type, Filters parameters, int depth) {
|
||||
try {
|
||||
return session.loadAll(type, parameters);
|
||||
return session.loadAll(type, parameters, depth);
|
||||
} catch (Exception e) {
|
||||
throw Neo4jOgmExceptionTranslator.translateExceptionIfPossible(e);
|
||||
}
|
||||
|
||||
@@ -72,4 +72,8 @@ public class User extends Person{
|
||||
public Set<Rating> getRatings() {
|
||||
return ratings;
|
||||
}
|
||||
|
||||
public void setMiddleName(String middleName) {
|
||||
this.middleName = middleName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,11 @@ import org.junit.Test;
|
||||
import org.neo4j.cypher.javacompat.ExecutionEngine;
|
||||
import org.neo4j.graphdb.*;
|
||||
import org.neo4j.ogm.annotation.NodeEntity;
|
||||
import org.neo4j.ogm.cypher.BooleanOperator;
|
||||
import org.neo4j.ogm.cypher.ComparisonOperator;
|
||||
import org.neo4j.ogm.cypher.Filter;
|
||||
import org.neo4j.ogm.cypher.Filters;
|
||||
import org.neo4j.ogm.session.Session;
|
||||
import org.neo4j.ogm.session.SessionFactory;
|
||||
import org.neo4j.ogm.session.Utils;
|
||||
import org.neo4j.ogm.session.result.QueryStatistics;
|
||||
@@ -48,11 +50,13 @@ public class Neo4jTemplateTest {
|
||||
public static Neo4jIntegrationTestRule neo4jRule = new Neo4jIntegrationTestRule();
|
||||
|
||||
private Neo4jOperations template;
|
||||
private Session session;
|
||||
|
||||
@Before
|
||||
public void setUpOgmSession() {
|
||||
SessionFactory sessionFactory = new SessionFactory("org.springframework.data.neo4j.examples.movies.domain");
|
||||
this.template = new Neo4jTemplate(sessionFactory.openSession(neo4jRule.url()));
|
||||
session = sessionFactory.openSession(neo4jRule.url());
|
||||
this.template = new Neo4jTemplate(session);
|
||||
addArbitraryDataToDatabase();
|
||||
}
|
||||
|
||||
@@ -164,6 +168,113 @@ public class Neo4jTemplateTest {
|
||||
assertEquals("Horror", loadedGenre.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAGRAPH-685
|
||||
*/
|
||||
@Test
|
||||
public void shouldRetrieveEntitiesByMatchingPropertyAndDepth() {
|
||||
User user = new User("Harmanpreet Singh");
|
||||
TempMovie bollywood = new TempMovie("Desi Boyz");
|
||||
TempMovie hollywood = new TempMovie("Mission Impossible");
|
||||
template.save(user.rate(bollywood, 1, "Bakwaas"));
|
||||
template.save(user.rate(hollywood, 4, "Pretty good"));
|
||||
|
||||
session.clear();
|
||||
|
||||
User u = template.loadByProperty(User.class, "name", "Harmanpreet Singh",0);
|
||||
assertEquals(0,u.getRatings().size());
|
||||
|
||||
u = template.loadByProperty(User.class, "name", "Harmanpreet Singh",2);
|
||||
assertEquals(2,u.getRatings().size());
|
||||
assertNotNull(u.getRatings().iterator().next().getMovie().getRatings());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAGRAPH-685
|
||||
*/
|
||||
@Test
|
||||
public void shouldRetrieveAllEntitiesByMatchingPropertyAndDepth() {
|
||||
User user = new User("Harmanpreet Singh");
|
||||
TempMovie bollywood = new TempMovie("Desi Boyz");
|
||||
TempMovie hollywood = new TempMovie("Desi Boyz");
|
||||
template.save(user.rate(bollywood, 1, "Bakwaas"));
|
||||
template.save(user.rate(hollywood, 4, "Pretty good"));
|
||||
|
||||
session.clear();
|
||||
|
||||
Collection<TempMovie> m = template.loadAllByProperty(TempMovie.class, "name", "Desi Boyz",0);
|
||||
assertEquals(2,m.size());
|
||||
assertEquals(0, m.iterator().next().getRatings().size());
|
||||
|
||||
m = template.loadAllByProperty(TempMovie.class, "name", "Desi Boyz",1);
|
||||
assertEquals(2,m.size());
|
||||
assertEquals(1, m.iterator().next().getRatings().size());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @see DATAGRAPH-685
|
||||
*/
|
||||
@Test
|
||||
public void shouldRetrieveEntitiesByMatchingPropertiesAndDepth() {
|
||||
User user = new User("Harmanpreet Singh");
|
||||
user.setMiddleName("A");
|
||||
User user2 = new User("Harmanpreet Singh");
|
||||
user2.setMiddleName("B");
|
||||
TempMovie bollywood = new TempMovie("Desi Boyz");
|
||||
TempMovie hollywood = new TempMovie("Mission Impossible");
|
||||
template.save(user.rate(bollywood, 1, "Bakwaas"));
|
||||
template.save(user.rate(hollywood, 4, "Pretty good"));
|
||||
template.save(user2);
|
||||
|
||||
session.clear();
|
||||
|
||||
Filter nameFilter = new Filter("name","Harmanpreet Singh");
|
||||
Filter middleNameFilter = new Filter("middleName","A");
|
||||
middleNameFilter.setBooleanOperator(BooleanOperator.AND);
|
||||
Filters filters = new Filters();
|
||||
filters.add(nameFilter, middleNameFilter);
|
||||
|
||||
User u = template.loadByProperties(User.class,filters,0);
|
||||
assertEquals(0,u.getRatings().size());
|
||||
|
||||
u = template.loadByProperties(User.class, filters,2);
|
||||
assertEquals(2,u.getRatings().size());
|
||||
assertNotNull(u.getRatings().iterator().next().getMovie().getRatings());
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATAGRAPH-685
|
||||
*/
|
||||
@Test
|
||||
public void shouldRetrieveAllEntitiesByMatchingPropertiesAndDepth() {
|
||||
User user = new User("Harmanpreet Singh");
|
||||
user.setMiddleName("A");
|
||||
User user2 = new User("Harmanpreet Singh");
|
||||
user2.setMiddleName("A");
|
||||
TempMovie bollywood = new TempMovie("Desi Boyz");
|
||||
TempMovie hollywood = new TempMovie("Mission Impossible");
|
||||
template.save(user.rate(bollywood, 1, "Bakwaas"));
|
||||
template.save(user.rate(hollywood, 4, "Pretty good"));
|
||||
template.save(user2);
|
||||
|
||||
session.clear();
|
||||
|
||||
Filter nameFilter = new Filter("name","Harmanpreet Singh");
|
||||
Filter middleNameFilter = new Filter("middleName","A");
|
||||
middleNameFilter.setBooleanOperator(BooleanOperator.AND);
|
||||
Filters filters = new Filters();
|
||||
filters.add(nameFilter, middleNameFilter);
|
||||
|
||||
Collection<User> u = template.loadAllByProperties(User.class,filters,0);
|
||||
assertEquals(2,u.size());
|
||||
assertEquals(0,u.iterator().next().getRatings().size());
|
||||
|
||||
u = template.loadAllByProperties(User.class, filters,2);
|
||||
assertEquals(2,u.size());
|
||||
assertNotNull(u.iterator().next().getRatings().iterator().next().getMovie().getRatings());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldExecuteArbitraryUpdateQuery() {
|
||||
assertTrue("There shouldn't be any genres in the database", this.template.loadAll(Genre.class).isEmpty());
|
||||
|
||||
@@ -59,6 +59,11 @@ The named or indexed parameter `{param}` will be substituted by the actual metho
|
||||
Node and Relationship-Entities are handled directly and converted into their respective ids, Iterables thereof as well.
|
||||
All other parameters types are provided directly (i.e. Strings, Longs, etc).
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
In the current version, custom queries do not support paging, sorting or a custom depth.
|
||||
====
|
||||
|
||||
=== Query results
|
||||
|
||||
Typical results for queries are `Iterable<Type>`, `Iterable<Map<String,Object>>` or simply `Type`.
|
||||
@@ -140,7 +145,7 @@ public interface PersonRepository extends GraphRepository<Person> {
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
In the current version, derived finders and custom queries do not support paging, sorting or a custom depth.
|
||||
In the current version, derived finders do not support paging, sorting or a custom depth.
|
||||
====
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user