Skip to content

Commit 0355a2a

Browse files
fix: Update relationship properties objects before populating result entities.
Closes #2904
1 parent b38572d commit 0355a2a

File tree

4 files changed

+105
-6
lines changed

4 files changed

+105
-6
lines changed

Diff for: src/main/java/org/springframework/data/neo4j/core/mapping/MappingSupport.java

+20-2
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,9 @@ public static Object getRelationshipOrRelationshipPropertiesObject(Neo4jMappingC
179179
PersistentPropertyAccessor<Object> relationshipPropertiesAccessor = persistentEntity.getPropertyAccessor(relationshipPropertiesValue);
180180
relationshipPropertiesAccessor.setProperty(persistentEntity.getPersistentProperty(TargetNode.class), newRelationshipObject);
181181
newRelationshipObject = relationshipPropertiesAccessor.getBean();
182+
183+
// If we recreate or manipulate the object including it's accessor, we must update it in the holder as well.
184+
entityHolder.setRelationshipProperties(newRelationshipObject);
182185
}
183186
return newRelationshipObject;
184187
}
@@ -190,14 +193,17 @@ private MappingSupport() {}
190193
*/
191194
@API(status = API.Status.INTERNAL)
192195
public final static class RelationshipPropertiesWithEntityHolder {
193-
private final PersistentPropertyAccessor<?> relationshipPropertiesPropertyAccessor;
194-
private final Object relationshipProperties;
196+
197+
private final Neo4jPersistentEntity<?> relationshipPropertiesEntity;
198+
private PersistentPropertyAccessor<?> relationshipPropertiesPropertyAccessor;
199+
private Object relationshipProperties;
195200
private final Object relatedEntity;
196201

197202
RelationshipPropertiesWithEntityHolder(
198203
Neo4jPersistentEntity<?> relationshipPropertiesEntity,
199204
Object relationshipProperties, Object relatedEntity
200205
) {
206+
this.relationshipPropertiesEntity = relationshipPropertiesEntity;
201207
this.relationshipPropertiesPropertyAccessor = relationshipPropertiesEntity.getPropertyAccessor(relationshipProperties);
202208
this.relationshipProperties = relationshipProperties;
203209
this.relatedEntity = relatedEntity;
@@ -211,6 +217,11 @@ public Object getRelationshipProperties() {
211217
return relationshipProperties;
212218
}
213219

220+
private void setRelationshipProperties(Object relationshipProperties) {
221+
this.relationshipProperties = relationshipProperties;
222+
this.relationshipPropertiesPropertyAccessor = relationshipPropertiesEntity.getPropertyAccessor(this.relationshipProperties);
223+
}
224+
214225
public Object getRelatedEntity() {
215226
return relatedEntity;
216227
}
@@ -231,5 +242,12 @@ public boolean equals(Object o) {
231242
public int hashCode() {
232243
return Objects.hash(relationshipProperties, relatedEntity);
233244
}
245+
246+
@Override
247+
public String toString() {
248+
return "RelationshipPropertiesWithEntityHolder{" +
249+
"relationshipProperties=" + relationshipProperties +
250+
'}';
251+
}
234252
}
235253
}

Diff for: src/test/java/org/springframework/data/neo4j/documentation/domain/MovieEntity.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ public class MovieEntity {
4444

4545
// tag::mapping.relationship.properties[]
4646
@Relationship(type = "ACTED_IN", direction = Direction.INCOMING) // <.>
47-
private List<Roles> actorsAndRoles;
47+
private List<Roles> actorsAndRoles = new ArrayList<>();
4848
// end::mapping.relationship.properties[]
4949

5050
@Relationship(type = "DIRECTED", direction = Direction.INCOMING)

Diff for: src/test/java/org/springframework/data/neo4j/documentation/domain/Roles.java

+13
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,21 @@ public Roles(PersonEntity person, List<String> roles) {
4141
this.roles = roles;
4242
}
4343

44+
// end::mapping.relationship.properties[]
45+
public Long getId() {
46+
return id;
47+
}
48+
// tag::mapping.relationship.properties[]
49+
4450
public List<String> getRoles() {
4551
return roles;
4652
}
53+
54+
@Override
55+
public String toString() {
56+
return "Roles{" +
57+
"id=" + id +
58+
'}' + this.hashCode();
59+
}
4760
}
4861
// end::mapping.relationship.properties[]

Diff for: src/test/java/org/springframework/data/neo4j/documentation/spring_boot/TemplateExampleTest.java

+71-3
Original file line numberDiff line numberDiff line change
@@ -23,24 +23,59 @@
2323
import java.util.Optional;
2424

2525
// end::faq.template-imperative-pt1[]
26-
import org.junit.jupiter.api.Disabled;
26+
import org.junit.jupiter.api.BeforeEach;
2727
// tag::faq.template-imperative-pt1[]
2828
import org.junit.jupiter.api.Test;
29+
// end::faq.template-imperative-pt1[]
30+
import org.neo4j.driver.Driver;
31+
// tag::faq.template-imperative-pt1[]
2932
import org.springframework.beans.factory.annotation.Autowired;
33+
// end::faq.template-imperative-pt1[]
34+
import org.springframework.context.annotation.Bean;
35+
import org.springframework.context.annotation.Configuration;
36+
import org.springframework.data.neo4j.core.DatabaseSelectionProvider;
37+
// tag::faq.template-imperative-pt1[]
3038
import org.springframework.data.neo4j.core.Neo4jTemplate;
39+
// end::faq.template-imperative-pt1[]
40+
import org.springframework.data.neo4j.core.transaction.Neo4jBookmarkManager;
41+
import org.springframework.data.neo4j.core.transaction.Neo4jTransactionManager;
42+
// tag::faq.template-imperative-pt1[]
3143
import org.springframework.data.neo4j.documentation.domain.MovieEntity;
3244
import org.springframework.data.neo4j.documentation.domain.PersonEntity;
3345
import org.springframework.data.neo4j.documentation.domain.Roles;
46+
// end::faq.template-imperative-pt1[]
47+
import org.springframework.data.neo4j.repository.config.EnableNeo4jRepositories;
48+
import org.springframework.data.neo4j.test.BookmarkCapture;
49+
import org.springframework.data.neo4j.test.Neo4jExtension;
50+
import org.springframework.data.neo4j.test.Neo4jImperativeTestConfiguration;
51+
import org.springframework.data.neo4j.test.Neo4jIntegrationTest;
52+
import org.springframework.transaction.PlatformTransactionManager;
53+
import org.springframework.transaction.annotation.EnableTransactionManagement;
54+
// tag::faq.template-imperative-pt1[]
3455

3556
// end::faq.template-imperative-pt1[]
3657

3758
/**
3859
* @author Michael J. Simons
3960
*/
40-
@Disabled
61+
@Neo4jIntegrationTest
4162
// tag::faq.template-imperative-pt2[]
4263
public class TemplateExampleTest {
4364

65+
// end::faq.template-imperative-pt2[]
66+
67+
protected static Neo4jExtension.Neo4jConnectionSupport neo4jConnectionSupport;
68+
69+
@BeforeEach
70+
void setup(@Autowired Driver driver, @Autowired BookmarkCapture bookmarkCapture) {
71+
try (var session = driver.session(bookmarkCapture.createSessionConfig()); var transaction = session.beginTransaction()) {
72+
transaction.run("MATCH (n) detach delete n").consume();
73+
transaction.commit();
74+
bookmarkCapture.seedWith(session.lastBookmarks());
75+
}
76+
}
77+
78+
// tag::faq.template-imperative-pt2[]
4479
@Test
4580
void shouldSaveAndReadEntities(@Autowired Neo4jTemplate neo4jTemplate) {
4681

@@ -53,12 +88,45 @@ void shouldSaveAndReadEntities(@Autowired Neo4jTemplate neo4jTemplate) {
5388
movie.getActorsAndRoles().add(roles1);
5489
movie.getActorsAndRoles().add(roles2);
5590

56-
neo4jTemplate.save(movie);
91+
MovieEntity result = neo4jTemplate.save(movie);
92+
// end::mapping.relationship.properties[]
93+
assertThat(result.getActorsAndRoles()).allSatisfy(relationship -> assertThat(relationship.getId()).isNotNull());
94+
// tag::mapping.relationship.properties[]
5795

5896
Optional<PersonEntity> person = neo4jTemplate.findById("Dean Jones", PersonEntity.class);
5997
assertThat(person).map(PersonEntity::getBorn).hasValue(1931);
6098

6199
assertThat(neo4jTemplate.count(PersonEntity.class)).isEqualTo(2L);
62100
}
101+
102+
// end::faq.template-imperative-pt2[]
103+
@Configuration
104+
@EnableTransactionManagement
105+
@EnableNeo4jRepositories(considerNestedRepositories = true)
106+
static class Config extends Neo4jImperativeTestConfiguration {
107+
108+
@Bean
109+
public Driver driver() {
110+
return neo4jConnectionSupport.getDriver();
111+
}
112+
113+
@Bean
114+
public BookmarkCapture bookmarkCapture() {
115+
return new BookmarkCapture();
116+
}
117+
118+
@Override
119+
public PlatformTransactionManager transactionManager(Driver driver, DatabaseSelectionProvider databaseNameProvider) {
120+
121+
BookmarkCapture bookmarkCapture = bookmarkCapture();
122+
return new Neo4jTransactionManager(driver, databaseNameProvider, Neo4jBookmarkManager.create(bookmarkCapture));
123+
}
124+
125+
@Override
126+
public boolean isCypher5Compatible() {
127+
return neo4jConnectionSupport.isCypher5SyntaxCompatible();
128+
}
129+
}
130+
// tag::faq.template-imperative-pt2[]
63131
}
64132
// end::faq.template-imperative-pt2[]

0 commit comments

Comments
 (0)