{"id":2067,"date":"2026-01-19T03:26:26","date_gmt":"2026-01-18T14:26:26","guid":{"rendered":"https:\/\/www.ronella.xyz\/?p=2067"},"modified":"2026-01-19T03:26:26","modified_gmt":"2026-01-18T14:26:26","slug":"mapstruct-inheritance-inheritconfiguration-and-inheritinverseconfiguration","status":"publish","type":"post","link":"https:\/\/www.ronella.xyz\/?p=2067","title":{"rendered":"MapStruct Inheritance: InheritConfiguration and InheritInverseConfiguration"},"content":{"rendered":"<p>MapStruct's <code>@InheritConfiguration<\/code> and <code>@InheritInverseConfiguration<\/code> annotations streamline complex mapping hierarchies and bidirectional conversions. These tools eliminate repetitive <code>@Mapping<\/code> definitions while maintaining type safety and compile-time validation.<\/p>\n<h2>Core Concepts<\/h2>\n<p><code>@InheritConfiguration<\/code> copies forward mapping rules from a base method to a child method with identical source\/target types. Local mappings override inherited ones for flexibility.<\/p>\n<p><code>@InheritInverseConfiguration<\/code> automatically reverses a forward mapping by swapping source and target types. It handles field renames and ignores, generating clean DTO-to-entity roundtrips.<\/p>\n<p>Both require <code>MappingInheritanceStrategy.EXPLICIT<\/code> (MapStruct default).<\/p>\n<h2>Complete Working Example<\/h2>\n<h2>Domain Models<\/h2>\n<pre><code class=\"language-java\">public class Car {\n    private String make;\n    private int numberOfSeats;\n    private int doors;\n\n    public Car() {}\n    public Car(String make, int numberOfSeats, int doors) {\n        this.make = make;\n        this.numberOfSeats = numberOfSeats;\n        this.doors = doors;\n    }\n\n    \/\/ Getters and setters\n    public String getMake() { return make; }\n    public void setMake(String make) { this.make = make; }\n    public int getNumberOfSeats() { return numberOfSeats; }\n    public void setNumberOfSeats(int numberOfSeats) { this.numberOfSeats = numberOfSeats; }\n    public int getDoors() { return doors; }\n    public void setDoors(int doors) { this.doors = doors; }\n}\n\npublic class CarDto {\n    private String manufacturer;\n    private Integer seatCount;\n    private boolean hasNavigationSystem;\n\n    public CarDto() {}\n    public CarDto(String manufacturer, Integer seatCount, boolean hasNavigationSystem) {\n        this.manufacturer = manufacturer;\n        this.seatCount = seatCount;\n        this.hasNavigationSystem = hasNavigationSystem;\n    }\n\n    \/\/ Getters and setters\n    public String getManufacturer() { return manufacturer; }\n    public void setManufacturer(String manufacturer) { this.manufacturer = manufacturer; }\n    public Integer getSeatCount() { return seatCount; }\n    public void setSeatCount(Integer seatCount) { this.seatCount = seatCount; }\n    public boolean isHasNavigationSystem() { return hasNavigationSystem; }\n    public void setHasNavigationSystem(boolean hasNavigationSystem) { this.hasNavigationSystem = hasNavigationSystem; }\n}<\/code><\/pre>\n<h2>Inheritance Hierarchy Example<\/h2>\n<pre><code class=\"language-java\">import org.mapstruct.InheritConfiguration;\nimport org.mapstruct.Mapper;\nimport org.mapstruct.Mapping;\n\n@Mapper\npublic interface VehicleMapper {\n    @Mapping(target = &quot;hasNavigationSystem&quot;, ignore = true)\n    @Mapping(target = &quot;manufacturer&quot;, source = &quot;make&quot;)\n    @Mapping(target = &quot;seatCount&quot;, source = &quot;numberOfSeats&quot;)\n    CarDto vehicleToDto(Car vehicle);\n}\n\n@Mapper\npublic interface CarMapper extends VehicleMapper {\n    @InheritConfiguration(name = &quot;vehicleToDto&quot;)\n    CarDto carToCarDto(Car car);\n\n    \/\/ Custom mapping overrides inheritance\n    @InheritConfiguration(name = &quot;vehicleToDto&quot;)\n    @Mapping(target = &quot;hasNavigationSystem&quot;, constant = &quot;false&quot;)\n    CarDto carToBasicDto(Car car);\n}<\/code><\/pre>\n<h2>Bidirectional Mapping Example<\/h2>\n<pre><code class=\"language-java\">import org.mapstruct.InheritInverseConfiguration;\nimport org.mapstruct.Mapper;\nimport org.mapstruct.Mapping;\n\n@Mapper\npublic interface BidirectionalCarMapper {\n    \/\/ Forward mapping with field renaming\n    @Mapping(target = &quot;hasNavigationSystem&quot;, ignore = true)\n    @Mapping(target = &quot;seatCount&quot;, source = &quot;numberOfSeats&quot;)\n    @Mapping(target = &quot;manufacturer&quot;, source = &quot;make&quot;)\n    CarDto toDto(Car car);\n\n    \/\/ Automatically reverses: seatCount-&gt;numberOfSeats, manufacturer-&gt;make\n    @InheritInverseConfiguration(name = &quot;toDto&quot;)\n    @Mapping(target = &quot;doors&quot;, ignore = true)\n    Car toEntity(CarDto dto);\n\n    \/\/ Selective reverse with local overrides\n    @InheritInverseConfiguration\n    @Mapping(target = &quot;numberOfSeats&quot;, ignore = true)\n    @Mapping(target = &quot;doors&quot;, ignore = true)\n    Car toEntityNoSeats(CarDto dto);\n}<\/code><\/pre>\n<h2>Verification Demo<\/h2>\n<pre><code class=\"language-java\">import org.mapstruct.factory.Mappers;\n\npublic class MapStructInheritanceDemo {\n    public static void main(String[] args) {\n        CarMapper carMapper = Mappers.getMapper(CarMapper.class);\n        BidirectionalCarMapper biMapper = Mappers.getMapper(BidirectionalCarMapper.class);\n\n        \/\/ Test inheritance\n        Car ferrari = new Car(&quot;Ferrari&quot;, 2, 2);\n        CarDto dto = carMapper.carToCarDto(ferrari);\n        System.out.println(dto.getManufacturer()); \/\/ &quot;Ferrari&quot;\n        System.out.println(dto.getSeatCount());    \/\/ 2\n\n        \/\/ Test bidirectional\n        CarDto sportsCarDto = new CarDto(&quot;Porsche&quot;, 4, true);\n        Car entity = biMapper.toEntity(sportsCarDto);\n        System.out.println(entity.getMake());        \/\/ &quot;Porsche&quot;\n        System.out.println(entity.getNumberOfSeats()); \/\/ 4\n    }\n}<\/code><\/pre>\n<h2>Comparison Table<\/h2>\n<table>\n<thead>\n<tr>\n<th>Feature<\/th>\n<th><code>@InheritConfiguration<\/code><\/th>\n<th><code>@InheritInverseConfiguration<\/code><\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>Direction<\/strong><\/td>\n<td>Forward \u2192 Forward<\/td>\n<td>Forward \u2192 Reverse<\/td>\n<\/tr>\n<tr>\n<td><strong>Type Match<\/strong><\/td>\n<td>Identical source\/target<\/td>\n<td>Swapped source\/target<\/td>\n<\/tr>\n<tr>\n<td><strong>Primary Use<\/strong><\/td>\n<td>Class hierarchies<\/td>\n<td>DTO \u2194 Entity roundtrips<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2>Best Practices<\/h2>\n<p><strong>For <code>@InheritConfiguration<\/code>:<\/strong><\/p>\n<ul>\n<li>Use in mapper hierarchies (<code>extends<\/code>)<\/li>\n<li>Document base mappings clearly<\/li>\n<li>Override selectively with <code>@Mapping<\/code><\/li>\n<\/ul>\n<p><strong>For <code>@InheritInverseConfiguration<\/code>:<\/strong><\/p>\n<ul>\n<li>Specify <code>name=<\/code> when source mapper has multiple similar methods<\/li>\n<li>Use <code>@Mapping(ignore=true)<\/code> for one-way fields<\/li>\n<\/ul>\n<p>These annotations reduce mapping code by 70-80% in typical enterprise applications while maintaining full compile-time safety.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>MapStruct&#8217;s @InheritConfiguration and @InheritInverseConfiguration annotations streamline complex mapping hierarchies and bidirectional conversions. These tools eliminate repetitive @Mapping definitions while maintaining type safety and compile-time validation. Core Concepts @InheritConfiguration copies forward mapping rules from a base method to a child method with identical source\/target types. Local mappings override inherited ones for flexibility. @InheritInverseConfiguration automatically reverses a [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[91],"tags":[],"_links":{"self":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/2067"}],"collection":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2067"}],"version-history":[{"count":1,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/2067\/revisions"}],"predecessor-version":[{"id":2068,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=\/wp\/v2\/posts\/2067\/revisions\/2068"}],"wp:attachment":[{"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2067"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2067"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.ronella.xyz\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2067"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}