Skip to content

Commit

Permalink
fix(core): Unlink many-to-one when null parent
Browse files Browse the repository at this point in the history
  • Loading branch information
JoseLion committed Mar 5, 2024
1 parent 11927b2 commit 6ed5c21
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 20 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,8 @@ public record City(
> [!Note]
> Notice that having the `countryId` field, which maps to the foreign key column, is required for the relationship to work properly.
If the annotation is `persist = true` and the field is `null` upon persistence, the annotation shall never delete the parent because it can still have other linked children. However, it will change the foreign key to `null` to unlink the children from the parent.

### ManyToMany

The `@ManyToMany` annotation lets you mark fields to have a many-to-many relationship. The default behavior of the annotation is to populate the field after mapping the entity object, create/update the associated entities, and link the relations on the join table. The annotation uses the join table transparently, meaning you **don't need** to create an entity type for the join table on your codebase.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public Mono<Object> persist(final ManyToOne annotation, final Field field) {
final var savedId = this.idValueOf(saved);
final var newEntity = Reflect.update(this.entity, field, saved);
return Reflect.update(newEntity, foreignField, savedId);
});
})
.defaultIfEmpty(Reflect.update(this.entity, foreignField, null));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@

private final String chicago = "Chicago";

private final String manhattan = "Manhattan";

@Nested class populate {
@Test void populates_the_field_with_the_parent_entity() {
countryRepo.save(usa)
Expand Down Expand Up @@ -66,7 +68,7 @@
}

@Nested class persist {
@Nested class when_the_annotation_does_not_configure_persist {
@Nested class when_the_persist_option_is_false {
@Test void does_not_persist_the_annotated_field_by_default() {
countryRepo.save(usa)
.map(saved -> saved.withName("USA"))
Expand All @@ -90,25 +92,66 @@
}
}

@Nested class when_the_annotation_sets_persist_to_true {
@Test void persists_the_annotated_field() {
final var manhattan = Town.of("Manhattan");
@Nested class when_the_persist_option_is_true {
@Nested class and_the_parent_does_not_exist {
@Test void creates_the_parent_entity() {
Mono.just(usa)
.map(Town.of(manhattan)::withCountry)
.flatMap(townRepo::save)
.map(Town::id)
.flatMap(townRepo::findById)
.zipWhen(saved -> countryRepo.findById(saved.countryId()))
.as(TxStepVerifier::withRollback)
.assertNext(consumer((town, country) -> {
assertThat(town.countryId()).isEqualTo(country.id());
assertThat(town.country().id()).isEqualTo(country.id());
assertThat(country.towns())
.extracting(Town::name)
.containsExactly(manhattan);
}))
.verifyComplete();
}
}

Mono.just(usa)
.map(manhattan::withCountry)
.flatMap(townRepo::save)
.map(Town::id)
.flatMap(townRepo::findById)
.zipWhen(saved -> countryRepo.findById(saved.countryId()))
.as(TxStepVerifier::withRollback)
.assertNext(consumer((town, country) -> {
assertThat(town.countryId()).isEqualTo(country.id());
assertThat(town.country().id()).isEqualTo(country.id());
assertThat(country.towns())
.extracting(Town::name)
.containsExactly(manhattan.name());
}))
.verifyComplete();
@Nested class and_the_parent_does_already_exists {
@Test void updates_the_parent_entity() {
Mono.just(usa)
.map(Town.of(manhattan)::withCountry)
.flatMap(townRepo::save)
.map(town -> town.withCountryBy(country -> country.withName("USA")))
.flatMap(townRepo::save)
.map(Town::id)
.flatMap(townRepo::findById)
.zipWhen(saved -> countryRepo.findById(saved.countryId()))
.as(TxStepVerifier::withRollback)
.assertNext(consumer((town, country) -> {
assertThat(town.countryId()).isEqualTo(country.id());
assertThat(town.country().id()).isEqualTo(country.id());
assertThat(country.name()).isEqualTo("USA");
assertThat(country.towns())
.extracting(Town::name)
.containsExactly(manhattan);
}))
.verifyComplete();
}
}

@Nested class and_the_parent_is_null {
@Test void unlinks_the_entity_from_the_parent() {
Mono.just(usa)
.map(Town.of(manhattan)::withCountry)
.flatMap(townRepo::save)
.map(town -> town.withCountry(null))
.flatMap(townRepo::save)
.map(Town::id)
.flatMap(townRepo::findById)
.as(TxStepVerifier::withRollback)
.assertNext(town -> {
assertThat(town.country()).isNull();
assertThat(town.countryId()).isNull();
})
.verifyComplete();
}
}
}
}
Expand Down

0 comments on commit 6ed5c21

Please sign in to comment.