{"id":638,"date":"2026-01-17T00:47:40","date_gmt":"2026-01-16T23:47:40","guid":{"rendered":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=638"},"modified":"2026-02-16T00:49:24","modified_gmt":"2026-02-15T23:49:24","slug":"mapstruct-und-iterablemapping-typsichere-objektabbildung-in-java","status":"publish","type":"post","link":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/?p=638","title":{"rendered":"MapStruct und @IterableMapping \u2013 Typsichere Objektabbildung in Java"},"content":{"rendered":"\n<h2 class=\"wp-block-heading\">Was ist MapStruct?<\/h2>\n\n\n\n<p><strong>MapStruct<\/strong> ist ein Annotation-basierter Codegenerator zur Abbildung (Mapping) von Java-Beans. Ziel ist es, wiederkehrende und fehleranf\u00e4llige Konvertierungslogik \u2013 etwa zwischen Entit\u00e4ten und DTOs \u2013 deklarativ zu beschreiben und den eigentlichen Mapping-Code zur Compile-Zeit generieren zu lassen.<\/p>\n\n\n\n<p>Im Gegensatz zu Reflection-basierten Frameworks wie <strong>ModelMapper<\/strong> oder <strong>Dozer<\/strong> erzeugt MapStruct reinen Java-Code ohne Laufzeit-Overhead. Dadurch ist es:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Performant<\/strong> (keine Reflection)<\/li>\n\n\n\n<li><strong>Typsicher<\/strong> (Fehler fallen beim Kompilieren auf)<\/li>\n\n\n\n<li><strong>Debug-freundlich<\/strong> (generierter Code ist lesbar)<\/li>\n<\/ul>\n\n\n\n<p>Typische Einsatzszenarien:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Entity \u2194 DTO Mapping<\/li>\n\n\n\n<li>API-Modelle \u2194 Dom\u00e4nenmodelle<\/li>\n\n\n\n<li>Persistenzschicht \u2194 Business-Schicht<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Grundprinzip von MapStruct<\/h2>\n\n\n\n<p>Ein Mapper wird als Interface definiert und mit <code>@Mapper<\/code> annotiert:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs\">@Mapper\npublic interface UserMapper {\n\n    UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);\n\n    UserDto toDto(User user);\n\n    User toEntity(UserDto dto);\n}\n<\/code><\/span><\/pre>\n\n\n<p>MapStruct generiert zur Compile-Zeit eine Implementierung wie <code>UserMapperImpl<\/code>.<\/p>\n\n\n\n<p>Felder mit gleichem Namen und kompatiblem Typ werden automatisch gemappt. Abweichungen k\u00f6nnen mit <code>@Mapping<\/code> konfiguriert werden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@Mapping<\/span>(source = <span class=\"hljs-string\">\"firstName\"<\/span>, target = <span class=\"hljs-string\">\"givenName\"<\/span>)\nUserDto toDto(User user);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Collections in MapStruct<\/h1>\n\n\n\n<p>In realen Anwendungen werden selten einzelne Objekte gemappt \u2013 h\u00e4ufig sind es Listen oder Sets.<\/p>\n\n\n\n<p>Ein einfaches Beispiel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">List<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">UserDto<\/span>&gt;<\/span> toDtoList(List<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">User<\/span>&gt;<\/span> users);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>MapStruct erkennt automatisch:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Es existiert eine <code>toDto(User user)<\/code>-Methode<\/li>\n\n\n\n<li>Also wird diese f\u00fcr jedes Element der Liste verwendet<\/li>\n<\/ul>\n\n\n\n<p>Der generierte Code sieht sinngem\u00e4\u00df so aus:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php\"><span class=\"hljs-keyword\">List<\/span>&lt;UserDto&gt; <span class=\"hljs-keyword\">list<\/span> = <span class=\"hljs-keyword\">new<\/span> ArrayList&lt;&gt;(users.size());\n<span class=\"hljs-keyword\">for<\/span> (User user : users) {\n    <span class=\"hljs-keyword\">list<\/span>.add(toDto(user));\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Doch was passiert, wenn:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>mehrere m\u00f6gliche Mapping-Methoden existieren?<\/li>\n\n\n\n<li>spezielle Qualifier verwendet werden?<\/li>\n\n\n\n<li>Null-Werte behandelt werden sollen?<\/li>\n\n\n\n<li>ein anderes Collection-Format erzeugt werden soll?<\/li>\n<\/ul>\n\n\n\n<p>Hier kommt <code>@IterableMapping<\/code> ins Spiel.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\"><code>@IterableMapping<\/code> \u2013 Kontrolle \u00fcber Collection-Mappings<\/h1>\n\n\n\n<p><code>@IterableMapping<\/code> erlaubt es, das Verhalten beim Mapping von Iterables (List, Set, Collection etc.) gezielt zu konfigurieren.<\/p>\n\n\n\n<p>Beispiel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@IterableMapping<\/span>(qualifiedByName = <span class=\"hljs-string\">\"lightweight\"<\/span>)\nList&lt;UserDto&gt; toDtoList(List&lt;User&gt; users);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Diese Annotation wird verwendet, wenn:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Mehrere Mapping-Methoden f\u00fcr denselben Typ existieren<\/li>\n\n\n\n<li>Eine bestimmte Mapping-Variante erzwungen werden soll<\/li>\n\n\n\n<li>Formatierungen (z. B. bei Datumswerten) notwendig sind<\/li>\n\n\n\n<li>Null-Handling gesteuert werden soll<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Beispiel: Mehrere Mapping-Varianten<\/h2>\n\n\n\n<p>Angenommen, es gibt zwei Varianten:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@Named<\/span>(\"detailed\")\nUserDto toDetailedDto(User user);\n\n<span class=\"hljs-keyword\">@Named<\/span>(\"lightweight\")\nUserDto toLightweightDto(User user);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Nun kann explizit gesteuert werden, welche Methode f\u00fcr eine Liste verwendet wird:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@IterableMapping<\/span>(qualifiedByName = <span class=\"hljs-string\">\"lightweight\"<\/span>)\nList&lt;UserDto&gt; toLightweightDtoList(List&lt;User&gt; users);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Ohne <code>@IterableMapping<\/code> w\u00fcrde MapStruct einen Ambiguit\u00e4tsfehler erzeugen.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Null-Handling mit <code>@IterableMapping<\/code><\/h2>\n\n\n\n<p>MapStruct bietet verschiedene Strategien f\u00fcr Null-Werte.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">@IterableMapping(nullValueMappingStrategy = NullValueMappingStrategy.RETURN_DEFAULT)\nList<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">UserDto<\/span>&gt;<\/span> toDtoList(List<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">User<\/span>&gt;<\/span> users);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Optionen:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>RETURN_NULL<\/code> (Standard)<\/li>\n\n\n\n<li><code>RETURN_DEFAULT<\/code> \u2192 leere Liste statt <code>null<\/code><\/li>\n<\/ul>\n\n\n\n<p>Gerade in REST-APIs ist <code>RETURN_DEFAULT<\/code> h\u00e4ufig sinnvoll, um NullPointerExceptions zu vermeiden.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">Datumsformatierung in Collections<\/h2>\n\n\n\n<p>Auch Formatierungen k\u00f6nnen \u00fcber <code>@IterableMapping<\/code> konfiguriert werden:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript\">@IterableMapping(dateFormat = <span class=\"hljs-string\">\"dd.MM.yyyy\"<\/span>)\nList&lt;<span class=\"hljs-built_in\">String<\/span>&gt; mapDates(List&lt;<span class=\"hljs-built_in\">Date<\/span>&gt; dates);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Hier wird jedes <code>Date<\/code>-Element mit dem angegebenen Format in einen <code>String<\/code> konvertiert.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\">ElementTargetType festlegen<\/h2>\n\n\n\n<p>Wenn der Zieltyp nicht eindeutig ist, kann <code>elementTargetType<\/code> helfen:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"HTML, XML\" data-shcb-language-slug=\"xml\"><span><code class=\"hljs language-xml\">@IterableMapping(elementTargetType = SpecialUserDto.class)\nList<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">UserDto<\/span>&gt;<\/span> mapUsers(List<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">User<\/span>&gt;<\/span> users);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">HTML, XML<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">xml<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Dies ist insbesondere bei Vererbungshierarchien n\u00fctzlich.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Zusammenspiel mit <code>@Mapping<\/code> und <code>@BeanMapping<\/code><\/h1>\n\n\n\n<p>Wichtig zu verstehen:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><code>@Mapping<\/code> \u2192 Konfiguration einzelner Felder<\/li>\n\n\n\n<li><code>@BeanMapping<\/code> \u2192 Konfiguration f\u00fcr Objekt-Mappings<\/li>\n\n\n\n<li><code>@IterableMapping<\/code> \u2192 Konfiguration f\u00fcr Collection-Mappings<\/li>\n<\/ul>\n\n\n\n<p>Beispiel:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"CSS\" data-shcb-language-slug=\"css\"><span><code class=\"hljs language-css\"><span class=\"hljs-keyword\">@BeanMapping<\/span>(ignoreByDefault = true)\n@Mapping(target = <span class=\"hljs-string\">\"id\"<\/span>, source = <span class=\"hljs-string\">\"id\"<\/span>)\n@Mapping(target = <span class=\"hljs-string\">\"name\"<\/span>, source = <span class=\"hljs-string\">\"name\"<\/span>)\nUserDto toSlimDto(User user);\n\n<span class=\"hljs-keyword\">@IterableMapping<\/span>(qualifiedByName = <span class=\"hljs-string\">\"toSlimDto\"<\/span>)\nList&lt;UserDto&gt; toSlimDtoList(List&lt;User&gt; users);\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code-Sprache:<\/span> <span class=\"shcb-language__name\">CSS<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">css<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>So lassen sich sehr gezielt unterschiedliche Projektionen definieren.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Performance-Aspekte<\/h1>\n\n\n\n<p>Da MapStruct reinen Java-Code generiert:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Keine Reflection<\/li>\n\n\n\n<li>Keine Proxy-Objekte<\/li>\n\n\n\n<li>Keine Laufzeit-Analyse<\/li>\n<\/ul>\n\n\n\n<p>Das macht es besonders attraktiv in:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Microservices<\/li>\n\n\n\n<li>Hochperformanten REST-APIs<\/li>\n\n\n\n<li>Batch-Verarbeitung gro\u00dfer Datenmengen<\/li>\n<\/ul>\n\n\n\n<p>Gerade bei gro\u00dfen Collections ist dies ein entscheidender Vorteil gegen\u00fcber dynamischen Mappern.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Best Practices f\u00fcr <code>@IterableMapping<\/code><\/h1>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Explizit qualifizieren<\/strong>, wenn mehrere Mapping-Methoden existieren<\/li>\n\n\n\n<li><strong>NullValueMappingStrategy bewusst setzen<\/strong><\/li>\n\n\n\n<li><strong>DTO-Varianten sauber benennen<\/strong><\/li>\n\n\n\n<li>Collection-Mapping-Methoden klar von Einzel-Mappings trennen<\/li>\n\n\n\n<li>Keine unn\u00f6tigen Konfigurationen \u2013 MapStruct arbeitet konventionsbasiert<\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h1 class=\"wp-block-heading\">Fazit<\/h1>\n\n\n\n<p>MapStruct bietet eine elegante, performante und typsichere L\u00f6sung zur Objektabbildung in Java. W\u00e4hrend einfache Collection-Mappings automatisch funktionieren, erm\u00f6glicht <code>@IterableMapping<\/code> eine pr\u00e4zise Steuerung bei komplexeren Anforderungen.<\/p>\n\n\n\n<p>Besonders in gr\u00f6\u00dferen Projekten mit:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>mehreren DTO-Varianten<\/li>\n\n\n\n<li>differenzierten API-Projektionen<\/li>\n\n\n\n<li>Vererbungsstrukturen<\/li>\n\n\n\n<li>spezifischem Null-Handling<\/li>\n<\/ul>\n\n\n\n<p>ist <code>@IterableMapping<\/code> ein zentrales Werkzeug, um Mapping-Logik sauber, deklarativ und wartbar zu halten.<\/p>\n\n\n\n<p>Wer strukturierte, explizite und compile-time gepr\u00fcfte Mappings bevorzugt, findet in MapStruct eine robuste Alternative zu Reflection-basierten L\u00f6sungen \u2013 mit klaren Vorteilen in Performance und Wartbarkeit.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Was ist MapStruct? MapStruct ist ein Annotation-basierter Codegenerator zur Abbildung (Mapping) von Java-Beans. Ziel ist es, wiederkehrende und fehleranf\u00e4llige Konvertierungslogik \u2013 etwa zwischen Entit\u00e4ten und DTOs \u2013 deklarativ zu beschreiben und den eigentlichen Mapping-Code zur Compile-Zeit generieren zu lassen. Im Gegensatz zu Reflection-basierten Frameworks wie ModelMapper oder Dozer erzeugt MapStruct reinen Java-Code ohne Laufzeit-Overhead. Dadurch [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-638","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/638","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=638"}],"version-history":[{"count":1,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/638\/revisions"}],"predecessor-version":[{"id":639,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=\/wp\/v2\/posts\/638\/revisions\/639"}],"wp:attachment":[{"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=638"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=638"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.xn--javaeinfacherklrt-4qb.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=638"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}