GH-1985 - Make sure derived queries on the same property of the same entity but different relationships use multiple matches.

This closes #1985 by adding the same test that is available in Neo4j-OGM
and prior versions of SDN.
This commit is contained in:
Michael Simons
2021-04-20 14:28:23 +02:00
parent 21f9d3338e
commit f7bf8a0350
5 changed files with 161 additions and 4 deletions

View File

@@ -86,6 +86,8 @@ import org.springframework.data.neo4j.integration.imperative.repositories.Person
import org.springframework.data.neo4j.integration.imperative.repositories.PersonWithNoConstructorRepository;
import org.springframework.data.neo4j.integration.imperative.repositories.PersonWithWitherRepository;
import org.springframework.data.neo4j.integration.imperative.repositories.ThingRepository;
import org.springframework.data.neo4j.integration.shared.common.Flight;
import org.springframework.data.neo4j.integration.imperative.repositories.FlightRepository;
import org.springframework.data.neo4j.integration.shared.common.AltHobby;
import org.springframework.data.neo4j.integration.shared.common.AltLikedByPersonRelationship;
import org.springframework.data.neo4j.integration.shared.common.AltPerson;
@@ -210,6 +212,20 @@ class RepositoryIT {
true, 1L, TEST_PERSON1_BORN_ON, "something", Arrays.asList("a", "b"), NEO4J_HQ, createdAt.toInstant());
person2 = new PersonWithAllConstructor(id2, TEST_PERSON2_NAME, TEST_PERSON2_FIRST_NAME, TEST_PERSON_SAMEVALUE,
false, 2L, TEST_PERSON2_BORN_ON, null, Collections.emptyList(), SFO, null);
transaction.run("CREATE (lhr:Airport {code: 'LHR', name: 'London Heathrow'})\n" +
"CREATE (lax:Airport {code: 'LAX', name: 'Los Angeles'})\n" +
"CREATE (cdg:Airport {code: 'CDG', name: 'Paris Charles de Gaulle'})\n" +
"CREATE (f1:Flight {name: 'FL 001'})\n" +
"CREATE (f2:Flight {name: 'FL 002'})\n" +
"CREATE (f3:Flight {name: 'FL 003'})\n" +
"CREATE (f1) -[:DEPARTS] ->(lhr)\n" +
"CREATE (f1) -[:ARRIVES] ->(lax)\n" +
"CREATE (f2) -[:DEPARTS] ->(lhr)\n" +
"CREATE (f2) -[:ARRIVES] ->(cdg)\n" +
"CREATE (f3) -[:DEPARTS] ->(lax)\n" +
"CREATE (f3) -[:ARRIVES] ->(lhr)\n" +
"RETURN *");
}
@Test
@@ -734,6 +750,14 @@ class RepositoryIT {
assertThat(slice.get()).hasSize(1).extracting("name").containsExactly(TEST_PERSON1_NAME);
assertThat(slice.hasNext()).isFalse();
}
@Test // GH-1985
void filtersOnSameEntitiesButDifferentRelationsShouldWork(@Autowired FlightRepository repository) {
List<Flight> flights = repository.findAllByDepartureCodeAndArrivalCode("LHR", "LAX");
assertThat(flights).hasSize(1)
.first().extracting(Flight::getName).isEqualTo("FL 001");
}
}
@Nested
@@ -4271,7 +4295,10 @@ class RepositoryIT {
@Override
protected Collection<String> getMappingBasePackages() {
return Arrays.asList(PersonWithAllConstructor.class.getPackage().getName());
return Arrays.asList(
PersonWithAllConstructor.class.getPackage().getName(),
Flight.class.getPackage().getName()
);
}
@Bean

View File

@@ -0,0 +1,28 @@
/*
* Copyright 2011-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.integration.imperative.repositories;
import org.springframework.data.neo4j.integration.shared.common.Flight;
import org.springframework.data.neo4j.repository.Neo4jRepository;
import java.util.List;
/**
* @author Michael J. Simons
*/
public interface FlightRepository extends Neo4jRepository<Flight, Long> {
List<Flight> findAllByDepartureCodeAndArrivalCode(String departureCode, String arrivalCode);
}

View File

@@ -18,7 +18,6 @@ package org.springframework.data.neo4j.integration.issues.gh2210;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.neo4j.driver.Driver;
import org.neo4j.driver.Record;
import org.neo4j.driver.Transaction;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@@ -70,14 +69,14 @@ class GH2210IT {
params.put("numberB", numberB);
params.put("numberC", numberC);
params.put("numberD", numberD);
Record r = transaction.run("create (a:SomeEntity {number: $numberA, name: \"A\"})\n"
transaction.run("create (a:SomeEntity {number: $numberA, name: \"A\"})\n"
+ "create (b:SomeEntity {number: $numberB, name: \"B\"})\n"
+ "create (c:SomeEntity {number: $numberC, name: \"C\"})\n"
+ "create (d:SomeEntity {number: $numberD, name: \"D\"})\n"
+ "create (a) -[:SOME_RELATION_TO {someData: \"d1\"}] -> (b)\n"
+ "create (b) <-[:SOME_RELATION_TO {someData: \"d2\"}] - (c)\n"
+ "create (c) <-[:SOME_RELATION_TO {someData: \"d3\"}] - (d)\n"
+ "return * ", params).single();
+ "return * ", params);
transaction.commit();
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2011-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.integration.shared.common;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
/**
* @author Michael J. Simons
*/
@Node
public class Airport {
@Id
String code; // e.g. "LAX"
String name; // e.g. "Los Angeles"
public Airport(String code, String name) {
this.code = code;
this.name = name;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2011-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.neo4j.integration.shared.common;
import org.springframework.data.neo4j.core.schema.GeneratedValue;
import org.springframework.data.neo4j.core.schema.Id;
import org.springframework.data.neo4j.core.schema.Node;
import org.springframework.data.neo4j.core.schema.Relationship;
/**
* @author Michael J. Simons
*/
@Node
public class Flight {
@Id @GeneratedValue
private Long id;
private final String name;
@Relationship(type = "DEPARTS")
private final Airport departure;
@Relationship(type = "ARRIVES")
private final Airport arrival;
public Flight(String name, Airport departure, Airport arrival) {
this.name = name;
this.departure = departure;
this.arrival = arrival;
}
public String getName() {
return name;
}
public Airport getDeparture() {
return departure;
}
public Airport getArrival() {
return arrival;
}
}