-
-
Notifications
You must be signed in to change notification settings - Fork 946
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
#1057 documentation for Controlling forged name based bean mapping fr…
…om root level with @mapping
- Loading branch information
Showing
2 changed files
with
101 additions
and
22 deletions.
There are no files selected for viewing
87 changes: 87 additions & 0 deletions
87
documentation/src/main/asciidoc/controlling-nested-bean-mappings.asciidoc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,87 @@ | ||
[[controlling-nested-bean-mappings]] | ||
=== Controlling nested bean mappings | ||
|
||
As explained above, MapStruct will generate a method based on the name of the source and target property. Unfortunately, in many occasions these names do not match. | ||
|
||
The ‘.’ notation in an `@Mapping` source or target type can be used to control how properties should be mapped when names do not match. | ||
There is an elaborate https://github.com/mapstruct/mapstruct-examples/tree/master/mapstruct-nested-bean-mappings[example] in our examples repository to explain how this problem can be overcome. | ||
|
||
In the simplest scenario there’s a property on a nested level that needs to be corrected. | ||
Take for instance a property `fish` which has an identical name in `FishTankDto` and `FishTank`. | ||
For this property MapStruct automatically generates a mapping: `FishDto fishToFishDto(Fish fish)`. | ||
MapStruct cannot possibly be aware of the deviating properties `kind` and `type`. | ||
Therefore this can be addressed in a mapping rule: `@Mapping(target="fish.kind", source="fish.type")`. | ||
This tells MapStruct to deviate from looking for a name `kind` at this level and map it to `type`. | ||
|
||
.Mapper controlling nested beans mappings I | ||
==== | ||
[source, java, linenums] | ||
[subs="verbatim,attributes"] | ||
---- | ||
@Mapper | ||
public interface FishTankMapper { | ||
@Mappings({ | ||
@Mapping(target = "fish.kind", source = "fish.type"), | ||
@Mapping(target = "fish.name", ignore = true), | ||
@Mapping(target = "ornament", source = "interior.ornament"), | ||
@Mapping(target = "material.materialType", source = "material"), | ||
@Mapping(target = "quality.report.organisation.name", source = "quality.report.organisationName") | ||
}) | ||
FishTankDto map( FishTank source ); | ||
} | ||
---- | ||
==== | ||
|
||
The same constructs can be used to ignore certain properties at a nesting level, as is demonstrated in the second `@Mapping` rule. | ||
|
||
MapStruct can even be used to “cherry pick” properties when source and target do not share the same nesting level (the same number of properties). | ||
This can be done in the source – and in the target type. This is demonstrated in the next 2 rules: `@Mapping(target="ornament", source="interior.ornament")` and `@Mapping(target="material.materialType", source="material")`. | ||
|
||
The latter can even be done when mappings first share a common base. | ||
For example: all properties that share the same name of `Quality` are mapped to `QualityDto`. | ||
Likewise, all properties of `Report` are mapped to `ReportDto`, with one exception: `organisation` in `OrganisationDto` is left empty (since there is no organization at the source level). | ||
Only the `name` is populated with the `organisationName` from `Report`. | ||
This is demonstrated in `@Mapping(target="quality.report.organisation.name", source="quality.report.organisationName")` | ||
|
||
Coming back to the original example: what if `kind` and `type` would be beans themselves? | ||
In that case MapStruct would again generate a method continuing to map. | ||
Such is demonstrated in the next example: | ||
|
||
|
||
.Mapper controlling nested beans mappings II | ||
==== | ||
[source, java, linenums] | ||
[subs="verbatim,attributes"] | ||
---- | ||
@Mapper | ||
public interface FishTankMapperWithDocument { | ||
@Mappings({ | ||
@Mapping(target = "fish.kind", source = "fish.type"), | ||
@Mapping(target = "fish.name", expression = "java(\"Jaws\")"), | ||
@Mapping(target = "plant", ignore = true ), | ||
@Mapping(target = "ornament", ignore = true ), | ||
@Mapping(target = "material", ignore = true), | ||
@Mapping(target = "quality.document", source = "quality.report"), | ||
@Mapping(target = "quality.document.organisation.name", constant = "NoIdeaInc" ) | ||
}) | ||
FishTankWithNestedDocumentDto map( FishTank source ); | ||
} | ||
---- | ||
==== | ||
|
||
Note what happens in `@Mapping(target="quality.document", source="quality.report")`. | ||
`DocumentDto` does not exist as such on the target side. It is mapped from `Report`. | ||
MapStruct continues to generate mapping code here. That mapping it self can be guided towards another name. | ||
This even works for constants and expression. Which is shown in the final example: `@Mapping(target="quality.document.organisation.name", constant="NoIdeaInc")`. | ||
|
||
MapStruct will perform a null check on each nested property in the source. | ||
|
||
[TIP] | ||
==== | ||
Instead of configuring everything via the parent method we encourage users to explicitly write their own nested methods. | ||
This puts the configuration of the nested mapping into one place (method) where it can be reused from several methods in the upper level, | ||
instead of re-configuring the same things on all of those upper methods. | ||
==== |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters