GH-2727 - Fix multiple levels of projecting properties mapping.
Closes #2727
This commit is contained in:
@@ -744,21 +744,7 @@ public enum CypherGenerator {
|
||||
if (property.isDynamicLabels() || property.isComposite()) {
|
||||
continue;
|
||||
}
|
||||
PropertyFilter.RelaxedPropertyPath from;
|
||||
|
||||
if (relationshipDescription == null) {
|
||||
from = parentPath.append(property.getFieldName());
|
||||
|
||||
} else if (relationshipDescription.hasRelationshipProperties()) {
|
||||
@SuppressWarnings("ConstantConditions") // All prerequisites have been checked by the persistence context at this point.
|
||||
String relationshipPropertyTargetNodeFieldName =
|
||||
((Neo4jPersistentEntity<?>) relationshipDescription.getRelationshipPropertiesEntity())
|
||||
.getPersistentProperty(TargetNode.class).getFieldName();
|
||||
|
||||
from = parentPath.append(relationshipPropertyTargetNodeFieldName + "." + property.getFieldName());
|
||||
} else {
|
||||
from = parentPath.append(property.getFieldName());
|
||||
}
|
||||
PropertyFilter.RelaxedPropertyPath from = parentPath.append(property.getFieldName());
|
||||
|
||||
if (!includeField.test(from)) {
|
||||
continue;
|
||||
@@ -828,7 +814,10 @@ public enum CypherGenerator {
|
||||
Neo4jPersistentEntity<?> endNodeDescription = (Neo4jPersistentEntity<?>) relationshipDescription.getTarget();
|
||||
|
||||
processedRelationships.add(relationshipDescription);
|
||||
PropertyFilter.RelaxedPropertyPath newParentPath = parentPath.append(relationshipDescription.getFieldName());
|
||||
PropertyFilter.RelaxedPropertyPath newParentPath = relationshipDescription.hasRelationshipProperties()
|
||||
? parentPath.append(relationshipDescription.getFieldName()).append(((Neo4jPersistentEntity<?>) relationshipDescription.getRelationshipPropertiesEntity())
|
||||
.getPersistentProperty(TargetNode.class).getFieldName())
|
||||
: parentPath.append(relationshipDescription.getFieldName());
|
||||
|
||||
if (relationshipDescription.isDynamic()) {
|
||||
Relationship relationship = relationshipDescription.isOutgoing()
|
||||
|
||||
@@ -145,6 +145,13 @@ import org.springframework.data.neo4j.integration.issues.gh2639.Sales;
|
||||
import org.springframework.data.neo4j.integration.issues.qbe.A;
|
||||
import org.springframework.data.neo4j.integration.issues.qbe.ARepository;
|
||||
import org.springframework.data.neo4j.integration.issues.qbe.B;
|
||||
import org.springframework.data.neo4j.integration.issues.gh2727.FirstLevelEntity;
|
||||
import org.springframework.data.neo4j.integration.issues.gh2727.FirstLevelEntityRepository;
|
||||
import org.springframework.data.neo4j.integration.issues.gh2727.FirstLevelProjection;
|
||||
import org.springframework.data.neo4j.integration.issues.gh2727.SecondLevelEntity;
|
||||
import org.springframework.data.neo4j.integration.issues.gh2727.SecondLevelEntityRelationship;
|
||||
import org.springframework.data.neo4j.integration.issues.gh2727.ThirdLevelEntity;
|
||||
import org.springframework.data.neo4j.integration.issues.gh2727.ThirdLevelEntityRelationship;
|
||||
import org.springframework.data.neo4j.integration.misc.ConcreteImplementationTwo;
|
||||
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
|
||||
import org.springframework.data.neo4j.repository.query.QueryFragmentsAndParameters;
|
||||
@@ -1030,6 +1037,59 @@ class IssuesIT extends TestBase {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
@Tag("GH-2727")
|
||||
void mapsProjectionChainWithRelationshipProperties(@Autowired FirstLevelEntityRepository firstLevelEntityRepository) {
|
||||
|
||||
String secondLevelValue = "someSecondLevelValue";
|
||||
String thirdLevelValue = "someThirdLevelValue";
|
||||
|
||||
final List<SecondLevelEntityRelationship> secondLevelEntityRelationships = new ArrayList<>();
|
||||
for (int i = 0; i < 2; i++) {
|
||||
final List<ThirdLevelEntityRelationship> thirdLevelEntityRelationships = new ArrayList<>();
|
||||
for (int j = 0; j < 3; j++) {
|
||||
final ThirdLevelEntity thirdLevelEntity = new ThirdLevelEntity();
|
||||
thirdLevelEntity.setSomeValue(thirdLevelValue);
|
||||
final ThirdLevelEntityRelationship thirdLevelRelationship = new ThirdLevelEntityRelationship();
|
||||
thirdLevelRelationship.setTarget(thirdLevelEntity);
|
||||
thirdLevelRelationship.setOrder(j + 1);
|
||||
thirdLevelEntityRelationships.add(thirdLevelRelationship);
|
||||
}
|
||||
|
||||
final SecondLevelEntity secondLevelEntity = SecondLevelEntity.builder()
|
||||
.thirdLevelEntityRelationshipProperties(thirdLevelEntityRelationships)
|
||||
.someValue(secondLevelValue)
|
||||
.build();
|
||||
|
||||
final SecondLevelEntityRelationship secondLevelRelationship = new SecondLevelEntityRelationship();
|
||||
secondLevelRelationship.setTarget(secondLevelEntity);
|
||||
secondLevelRelationship.setOrder(i + 1);
|
||||
secondLevelEntityRelationships.add(secondLevelRelationship);
|
||||
}
|
||||
|
||||
final FirstLevelEntity firstLevelEntity = FirstLevelEntity.builder()
|
||||
.secondLevelEntityRelationshipProperties(secondLevelEntityRelationships)
|
||||
.name("Test")
|
||||
.build();
|
||||
|
||||
firstLevelEntityRepository.save(firstLevelEntity);
|
||||
|
||||
FirstLevelProjection firstLevelProjection = firstLevelEntityRepository.findOneById(firstLevelEntity.getId());
|
||||
assertThat(firstLevelProjection).isNotNull();
|
||||
assertThat(firstLevelProjection.getSecondLevelEntityRelationshipProperties()).hasSize(2)
|
||||
.allSatisfy(secondLevelRelationship -> {
|
||||
assertThat(secondLevelRelationship.getTarget().getSomeValue().equals(secondLevelValue));
|
||||
assertThat(secondLevelRelationship.getOrder()).isGreaterThan(0);
|
||||
assertThat(secondLevelRelationship.getTarget().getThirdLevelEntityRelationshipProperties())
|
||||
.isNotEmpty()
|
||||
.allSatisfy(thirdLevel -> {
|
||||
assertThat(thirdLevel.getOrder()).isGreaterThan(0);
|
||||
assertThat(thirdLevel.getTarget()).isNotNull();
|
||||
assertThat(thirdLevel.getTarget().getSomeValue()).isEqualTo(thirdLevelValue);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableTransactionManagement
|
||||
@EnableNeo4jRepositories(namedQueriesLocation = "more-custom-queries.properties")
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2011-2023 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.issues.gh2727;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Gerrit Meier
|
||||
*/
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@Node("FirstLevel")
|
||||
@EqualsAndHashCode(of = {"id"})
|
||||
public class FirstLevelEntity {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@Relationship("HasSecondLevel")
|
||||
private List<SecondLevelEntityRelationship> secondLevelEntityRelationshipProperties;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2011-2023 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.issues.gh2727;
|
||||
|
||||
import org.springframework.data.neo4j.repository.Neo4jRepository;
|
||||
|
||||
/**
|
||||
* @author Gerrit Meier
|
||||
*/
|
||||
public interface FirstLevelEntityRepository extends Neo4jRepository<FirstLevelEntity, Long> {
|
||||
|
||||
FirstLevelProjection findOneById(Long id);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2011-2023 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.issues.gh2727;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Gerrit Meier
|
||||
*/
|
||||
public interface FirstLevelProjection {
|
||||
Long getId();
|
||||
|
||||
Set<SecondLevelRelationshipProjection> getSecondLevelEntityRelationshipProperties();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
interface SecondLevelRelationshipProjection {
|
||||
Long getId();
|
||||
|
||||
SecondLevelProjection getTarget();
|
||||
|
||||
Integer getOrder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2011-2023 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.issues.gh2727;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import org.springframework.data.neo4j.core.schema.GeneratedValue;
|
||||
import org.springframework.data.neo4j.core.schema.Property;
|
||||
import org.springframework.data.neo4j.core.schema.RelationshipId;
|
||||
import org.springframework.data.neo4j.core.schema.RelationshipProperties;
|
||||
import org.springframework.data.neo4j.core.schema.TargetNode;
|
||||
|
||||
/**
|
||||
* @author Gerrit Meier
|
||||
* @param <T> relationship properties type
|
||||
*/
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@RelationshipProperties
|
||||
public class OrderedRelation<T> implements Comparable<OrderedRelation<T>> {
|
||||
@RelationshipId
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
@TargetNode
|
||||
private T target;
|
||||
@Property
|
||||
private Integer order;
|
||||
|
||||
@Override
|
||||
public int compareTo(final OrderedRelation<T> o) {
|
||||
return order - o.order;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2011-2023 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.issues.gh2727;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
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;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Gerrit Meier
|
||||
*/
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@Node("SecondLevel")
|
||||
@EqualsAndHashCode(of = {"id"})
|
||||
public class SecondLevelEntity {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String someValue;
|
||||
|
||||
@Relationship("HasThirdLevel")
|
||||
private List<ThirdLevelEntityRelationship> thirdLevelEntityRelationshipProperties;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2011-2023 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.issues.gh2727;
|
||||
|
||||
/**
|
||||
* @author Gerrit Meier
|
||||
*/
|
||||
public class SecondLevelEntityRelationship extends OrderedRelation<SecondLevelEntity> {
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2011-2023 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.issues.gh2727;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author Gerrit Meier
|
||||
*/
|
||||
public interface SecondLevelProjection {
|
||||
Long getId();
|
||||
|
||||
String getSomeValue();
|
||||
|
||||
Set<ThirdLevelRelationshipProjection> getThirdLevelEntityRelationshipProperties();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
interface ThirdLevelRelationshipProjection {
|
||||
Long getId();
|
||||
|
||||
ThirdLevelProjection getTarget();
|
||||
|
||||
Integer getOrder();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2011-2023 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.issues.gh2727;
|
||||
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import lombok.Setter;
|
||||
import lombok.experimental.SuperBuilder;
|
||||
import org.springframework.data.neo4j.core.schema.GeneratedValue;
|
||||
import org.springframework.data.neo4j.core.schema.Id;
|
||||
import org.springframework.data.neo4j.core.schema.Node;
|
||||
|
||||
/**
|
||||
* @author Gerrit Meier
|
||||
*/
|
||||
@SuperBuilder
|
||||
@NoArgsConstructor
|
||||
@Getter
|
||||
@Setter
|
||||
@Node("ThirdLevel")
|
||||
@EqualsAndHashCode(of = {"id"})
|
||||
public class ThirdLevelEntity {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String someValue;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2011-2023 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.issues.gh2727;
|
||||
|
||||
/**
|
||||
* @author Gerrit Meier
|
||||
*/
|
||||
public class ThirdLevelEntityRelationship extends OrderedRelation<ThirdLevelEntity> {
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2011-2023 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.issues.gh2727;
|
||||
|
||||
/**
|
||||
* @author Gerrit Meier
|
||||
*/
|
||||
public interface ThirdLevelProjection {
|
||||
Long getId();
|
||||
|
||||
String getSomeValue();
|
||||
}
|
||||
Reference in New Issue
Block a user