#386 - Add integration test for deep nested derived queries support.
SDN supports derived queries over several, deeply nested properties in the following version combinations: - Spring Data Kay SR9 + Neo4j-OGM 3.0.4 - Spring Data Lovelace RC1 + Neo4j-OGM 3.1.1 As of writing, Spring Boot 2.0.4 picks up Spring Data Kay SR9 + Neo4j-OGM 3.1.0. This is an unsupported combination, see https://github.com/spring-projects/spring-boot/issues/13999. This tests asserts the correct versions for Spring Boot 2.1.0+ and 2.0.5+. Also fixes the use of final field relationships in the domain classes used in the test and removed the usage of deprecated API.
This commit is contained in:
committed by
Oliver Gierke
parent
dc58547743
commit
802b5564c4
@@ -19,12 +19,12 @@ package example.springdata.neo4j;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.neo4j.ogm.annotation.GraphId;
|
||||
import org.neo4j.ogm.annotation.GeneratedValue;
|
||||
import org.neo4j.ogm.annotation.Id;
|
||||
import org.neo4j.ogm.annotation.NodeEntity;
|
||||
import org.neo4j.ogm.annotation.Relationship;
|
||||
|
||||
@@ -33,16 +33,20 @@ import org.neo4j.ogm.annotation.Relationship;
|
||||
*
|
||||
* @author Luanne Misquitta
|
||||
* @author Oliver Gierke
|
||||
* @author Michael J. Simons
|
||||
*/
|
||||
@NodeEntity(label = "Actor")
|
||||
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public class Actor {
|
||||
|
||||
private @GraphId Long id;
|
||||
private final String name;
|
||||
private final @Relationship(type = "ACTED_IN") Set<Role> roles = new HashSet<>();
|
||||
private @Id @GeneratedValue Long id;
|
||||
private String name;
|
||||
private @Relationship(type = "ACTED_IN") Set<Role> roles = new HashSet<>();
|
||||
|
||||
public Actor(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public void actedIn(Movie movie, String roleName) {
|
||||
|
||||
|
||||
@@ -15,11 +15,22 @@
|
||||
*/
|
||||
package example.springdata.neo4j;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.data.neo4j.repository.Neo4jRepository;
|
||||
|
||||
/**
|
||||
* {@link GraphRepository} for {@link Actor}s.
|
||||
* {@link Neo4jRepository} for {@link Actor actors}.
|
||||
*
|
||||
* @author Luanne Misquitta
|
||||
* @author Michael J. Simons
|
||||
*/
|
||||
public interface ActorRepository extends Neo4jRepository<Actor, Long> {}
|
||||
public interface ActorRepository extends Neo4jRepository<Actor, Long> {
|
||||
/**
|
||||
* Nested property from select from roles -> movie -> title,
|
||||
* where this here represents the start node in a relationship and movie the end node.
|
||||
* @param title
|
||||
* @return
|
||||
*/
|
||||
List<Actor> findAllByRolesMovieTitle(String title);
|
||||
}
|
||||
|
||||
@@ -19,12 +19,12 @@ package example.springdata.neo4j;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.neo4j.ogm.annotation.GraphId;
|
||||
import org.neo4j.ogm.annotation.GeneratedValue;
|
||||
import org.neo4j.ogm.annotation.Id;
|
||||
import org.neo4j.ogm.annotation.NodeEntity;
|
||||
import org.neo4j.ogm.annotation.Relationship;
|
||||
|
||||
@@ -33,14 +33,18 @@ import org.neo4j.ogm.annotation.Relationship;
|
||||
*
|
||||
* @author Luanne Misquitta
|
||||
* @author Oliver Gierke
|
||||
* @author Michael J. Simons
|
||||
*/
|
||||
@NodeEntity(label = "Movie")
|
||||
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public class Movie {
|
||||
|
||||
private @GraphId Long id;
|
||||
private final String title;
|
||||
private final @Relationship(type = "ACTED_IN", direction = "INCOMING") Set<Role> roles = new HashSet<>();
|
||||
private @Id @GeneratedValue Long id;
|
||||
private String title;
|
||||
private @Relationship(type = "ACTED_IN", direction = "INCOMING") Set<Role> roles = new HashSet<>();
|
||||
|
||||
public Movie(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,10 @@ package example.springdata.neo4j;
|
||||
import lombok.AccessLevel;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import org.neo4j.ogm.annotation.EndNode;
|
||||
import org.neo4j.ogm.annotation.GraphId;
|
||||
import org.neo4j.ogm.annotation.GeneratedValue;
|
||||
import org.neo4j.ogm.annotation.Id;
|
||||
import org.neo4j.ogm.annotation.RelationshipEntity;
|
||||
import org.neo4j.ogm.annotation.StartNode;
|
||||
|
||||
@@ -29,15 +29,21 @@ import org.neo4j.ogm.annotation.StartNode;
|
||||
* A Role relationship entity between an actor and movie.
|
||||
*
|
||||
* @author Luanne Misquitta
|
||||
* @author Michael J. Simons
|
||||
*/
|
||||
@RelationshipEntity(type = "ACTED_IN")
|
||||
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public class Role {
|
||||
|
||||
private @GraphId Long id;
|
||||
private final @StartNode Actor actor;
|
||||
private final String role;
|
||||
private final @EndNode Movie movie;
|
||||
private @Id @GeneratedValue Long id;
|
||||
private @StartNode Actor actor;
|
||||
private String role;
|
||||
private @EndNode Movie movie;
|
||||
|
||||
Role(Actor actor, String role, Movie movie) {
|
||||
this.actor = actor;
|
||||
this.role = role;
|
||||
this.movie = movie;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,20 +16,27 @@
|
||||
package example.springdata.neo4j;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.SpringBootVersion;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.data.util.Version;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Simple integration test demonstrating the use of the ActorRepository
|
||||
*
|
||||
* @author Luanne Misquitta
|
||||
* @author Oliver Gierke
|
||||
* @author Michael J. Simons
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringBootTest
|
||||
@@ -37,14 +44,12 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
public class ActorRepositoryIntegrationTest {
|
||||
|
||||
@SpringBootApplication
|
||||
static class ExampleConfig {}
|
||||
static class ExampleConfig {
|
||||
}
|
||||
|
||||
@Autowired ActorRepository actorRepository;
|
||||
|
||||
/**
|
||||
* @see #131
|
||||
*/
|
||||
@Test
|
||||
@Test // #131
|
||||
public void shouldBeAbleToSaveAndLoadActor() {
|
||||
|
||||
Movie goblet = new Movie("Harry Potter and the Goblet of Fire");
|
||||
@@ -57,7 +62,52 @@ public class ActorRepositoryIntegrationTest {
|
||||
assertThat(actorRepository.findById(daniel.getId())).hasValueSatisfying(actor -> {
|
||||
assertThat(actor.getName()).isEqualTo(daniel.getName());
|
||||
assertThat(actor.getRoles()).hasSize(1).first()
|
||||
.satisfies(role -> assertThat(role.getRole()).isEqualTo("Harry Potter"));
|
||||
.satisfies(role -> assertThat(role.getRole()).isEqualTo("Harry Potter"));
|
||||
});
|
||||
}
|
||||
|
||||
@Test // #386
|
||||
public void shouldBeAbleToHandleNestedProperties() {
|
||||
|
||||
assumeTrue(thatSupportForNestedPropertiesIsAvailable());
|
||||
|
||||
Movie theParentTrap = new Movie("The Parent Trap");
|
||||
Movie iKnowWhoKilledMe = new Movie("I Know Who Killed Me");
|
||||
|
||||
Actor lindsayLohan = new Actor("Lindsay Lohan");
|
||||
|
||||
lindsayLohan.actedIn(theParentTrap, "Hallie Parker");
|
||||
lindsayLohan.actedIn(theParentTrap, "Annie James");
|
||||
lindsayLohan.actedIn(iKnowWhoKilledMe, "Aubrey Fleming");
|
||||
lindsayLohan.actedIn(iKnowWhoKilledMe, "Dakota Moss");
|
||||
actorRepository.save(lindsayLohan);
|
||||
|
||||
Actor nealMcDonough = new Actor("Neal McDonough");
|
||||
nealMcDonough.actedIn(iKnowWhoKilledMe, "Daniel Fleming");
|
||||
actorRepository.save(nealMcDonough);
|
||||
|
||||
assertThat(actorRepository.findAllByRolesMovieTitle(iKnowWhoKilledMe.getTitle())).hasSize(2)
|
||||
.extracting(Actor::getName).contains(lindsayLohan.getName(), nealMcDonough.getName());
|
||||
}
|
||||
|
||||
private static boolean thatSupportForNestedPropertiesIsAvailable() {
|
||||
|
||||
Version minVersion = Version.parse("2.0.5");
|
||||
Optional<String> currentSpringBootVersion = Optional.ofNullable(SpringBootVersion.getVersion());
|
||||
|
||||
return currentSpringBootVersion.map(Version::parse)
|
||||
.map(v -> v.isGreaterThanOrEqualTo(minVersion))
|
||||
.orElseGet(ActorRepositoryIntegrationTest::fallBackToVersionSpecificClasses);
|
||||
}
|
||||
|
||||
private static boolean fallBackToVersionSpecificClasses() {
|
||||
|
||||
ClassLoader usedClassLoader = ActorRepositoryIntegrationTest.class.getClassLoader();
|
||||
|
||||
String fqnBoot210Class = "org.springframework.boot.autoconfigure.insight.InsightsProperties";
|
||||
String fqnBoot205Class = "org.springframework.boot.autoconfigure.security.servlet.RequestMatcherProvider";
|
||||
|
||||
return ClassUtils.isPresent(fqnBoot210Class, usedClassLoader) || ClassUtils
|
||||
.isPresent(fqnBoot205Class, usedClassLoader);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user