Coder Social home page Coder Social logo

mapstruct / mapstruct Goto Github PK

View Code? Open in Web Editor NEW
6.9K 138.0 918.0 11.02 MB

An annotation processor for generating type-safe bean mappers

Home Page: https://mapstruct.org/

License: Other

Java 98.40% FreeMarker 1.59% Kotlin 0.01%
mapstruct java annotation-processor mapping javabeans no-reflection bean-mapping

mapstruct's Introduction

MapStruct - Java bean mappings, the easy way!

Latest Stable Version Latest Version License

Build Status Coverage Status Gitter Code Quality: Java Total Alerts

What is MapStruct?

MapStruct is a Java annotation processor for the generation of type-safe and performant mappers for Java bean classes. It saves you from writing mapping code by hand, which is a tedious and error-prone task. The generator comes with sensible defaults and many built-in type conversions, but it steps out of your way when it comes to configuring or implementing special behavior.

Compared to mapping frameworks working at runtime, MapStruct offers the following advantages:

  • Fast execution by using plain method invocations instead of reflection
  • Compile-time type safety. Only objects and attributes mapping to each other can be mapped, so there's no accidental mapping of an order entity into a customer DTO, etc.
  • Self-contained code—no runtime dependencies
  • Clear error reports at build time if:
    • mappings are incomplete (not all target properties are mapped)
    • mappings are incorrect (cannot find a proper mapping method or type conversion)
  • Easily debuggable mapping code (or editable by hand—e.g. in case of a bug in the generator)

To create a mapping between two types, declare a mapper interface like this:

@Mapper
public interface CarMapper {

    CarMapper INSTANCE = Mappers.getMapper( CarMapper.class );

    @Mapping(target = "seatCount", source = "numberOfSeats")
    CarDto carToCarDto(Car car);
}

At compile time MapStruct will generate an implementation of this interface. The generated implementation uses plain Java method invocations for mapping between source and target objects, i.e. no reflection is involved. By default, properties are mapped if they have the same name in source and target, but you can control this and many other aspects using @Mapping and a handful of other annotations.

Requirements

MapStruct requires Java 1.8 or later.

Using MapStruct

MapStruct works in command line builds (plain javac, via Maven, Gradle, Ant, etc.) and IDEs.

For Eclipse, a dedicated plug-in is in development (see https://github.com/mapstruct/mapstruct-eclipse). It goes beyond what's possible with an annotation processor, providing content assist for annotation attributes, quick fixes and more.

For IntelliJ the plug-in is available within the IntelliJ marketplace (see https://plugins.jetbrains.com/plugin/10036-mapstruct-support).

Maven

For Maven-based projects, add the following to your POM file in order to use MapStruct (the dependencies are available at Maven Central):

...
<properties>
    <org.mapstruct.version>1.5.5.Final</org.mapstruct.version>
</properties>
...
<dependencies>
    <dependency>
        <groupId>org.mapstruct</groupId>
        <artifactId>mapstruct</artifactId>
        <version>${org.mapstruct.version}</version>
    </dependency>
</dependencies>
...
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <annotationProcessorPaths>
                    <path>
                        <groupId>org.mapstruct</groupId>
                        <artifactId>mapstruct-processor</artifactId>
                        <version>${org.mapstruct.version}</version>
                    </path>
                </annotationProcessorPaths>
            </configuration>
        </plugin>
    </plugins>
</build>
...

Gradle

For Gradle, you need something along the following lines:

plugins {
    ...
    id "com.diffplug.eclipse.apt" version "3.26.0" // Only for Eclipse
}

dependencies {
    ...
    implementation 'org.mapstruct:mapstruct:1.5.5.Final'

    annotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final'
    testAnnotationProcessor 'org.mapstruct:mapstruct-processor:1.5.5.Final' // if you are using mapstruct in test code
}
...

If you don't work with a dependency management tool, you can obtain a distribution bundle from Releases page.

Documentation and getting help

To learn more about MapStruct, refer to the project homepage. The reference documentation covers all provided functionality in detail. If you need help please ask it in the Discussions.

Building from Source

MapStruct uses Maven for its build. Java 11 is required for building MapStruct from source. To build the complete project, run

./mvnw clean install

from the root of the project directory. To skip the distribution module, run

./mvnw clean install -DskipDistribution=true

Importing into IDE

MapStruct uses the gem annotation processor to generate mapping gems for its own annotations. Therefore, for seamless integration within an IDE annotation processing needs to be enabled.

IntelliJ

Make sure that you have at least IntelliJ 2018.2.x (needed since support for annotationProcessors from the maven-compiler-plugin is from that version). Enable annotation processing in IntelliJ (Build, Execution, Deployment -> Compiler -> Annotation Processors)

Eclipse

Make sure that you have the m2e_apt plugin installed.

Links

Licensing

MapStruct is licensed under the Apache License, Version 2.0 (the "License"); you may not use this project except in compliance with the License. You may obtain a copy of the License at https://www.apache.org/licenses/LICENSE-2.0.

mapstruct's People

Contributors

agudian avatar bedla avatar blackbaud-jasonbodnar avatar captain1653 avatar chenzijia12300 avatar chris922 avatar chschu avatar dependabot[bot] avatar dgruntz avatar ecormaksin avatar eforest avatar evaristegalois11 avatar filiphr avatar fml2 avatar greuelpirat avatar gunnarmorling avatar hduelme avatar incaseoftrouble avatar jccampanero avatar judeniroshan avatar kevcodez avatar navpil avatar neoxfire avatar nikolas-charalambidis avatar prasanth08 avatar sjaakd avatar thunderhook avatar xyzst avatar yokotaso avatar zegveld avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mapstruct's Issues

Properties from super classes are not mapped

Currently, mapstruct only maps those properties that are declared directly by a class. Properties from the super class are not mapped.

I think there's also a concept required to define such super class attribute mappings at once place and re-use that definition for the mapping of the inherited classes... E.g. by extending the Mapper-interface with a Mapper interface that defines partial mappings from/to the (potentially abstract) super classes.

Provide support for common component models

Currently mapper instances are retrieved via Mapper#getMapper(Class<?> mapperType) and the Interface.INSTANCE pattern.

This does not integrate really well with common component models such as CDI or Spring. Therefore it should be configurable to create mapper implementations in form of CDI or Spring beans, e.g. by adding the required annotations to the implementation type.

The approach schould be extensible in order to easily add support for other models in the future. The target model should be configurable on the mapper level, e.g. via @Mapper( componentType = "cdi" ) and globally via an AP option.

Add more tests for mapping methods with target parameters

Follow up to #19:

  • Add tests for reverse methods (with target parameters in original and/or reverse method)
  • Which configuration should apply if there is a reverse method and two corresponding "forward" methods, one with and one without target parameter?
  • Invoke method with target parameter to map property from within another mapping method

@agudian Would you like to have a look at this?

Provide OSGi-enabled JARs

Only really makes sense for the annotation JAR (someone could want to use the Mappers factory at runtime).

Support for Sync and Clone

Hi,

Would it be possible to have sync and clone method support so that, when I am converting DTO to DAO, I can say all the DTO instance data is synced with an existing instance of DAO object..

Regards,
Raja Nagendra Kumar
C.T.O
www.tejasoft.com

Find 'nearest' property mapping method and use it

Consider the following example:

  • class A extends SuperA
  • class B extends SuperB
  • class Source has property prop:A
  • class Target has property prop:SuperB (or, as a first step, prop:B)
  • FooMapper with B mapToB(SuperA superA)
  • BarMapper uses FooMapper
  • BarMapper has method Target mapSourceToTarget(Source source)

And, guess what: the implementation of Target mapSourceToTarget(Source source) uses B mapToB(SuperA superA) to map from Source.prop to Target.prop. And sure, if there was a method B mapToB(A a), then that method would be used.

The question is: what's the exact metric for the method distance?

Support mapping into existing instances

From Andreas:

It should be possible to populate an existing object as mapping target instead of creating a new instance:

Foo mapInto(Bar source, Foo target);

When doing that, it should be possible to specify how to treat existing collections. E.g. it is usually harmful when replacing an existing PersistentSet with a new HashSet instead of calling clear() and addAll(..).

Emit warnings for precision loss

This follows up on #1; If built-in conversion causes a possible precision loss (e.g. from long to int), a warning or error should be created. If the concerned attribute is mapped via @Mapping the marker should be at the annotation, otherwise at the mapping method(s).

It might be a good idea to make it configurable either globally and or via an attribute in @Mapper whether the error kind should be WARNING or ERROR.

Support for nested properties

It would be nice if MapStruct could support compound properties mappings. For example I would like to map Person.Address.street property to PersonDto.addressStreet.

First of all @Mapping annotation could support dot-notation of properties (for example @Mapping(source="address.street", target="addressStreet")). However ideally MapStruct could automagically try to map Person.Address.street to PersonDto.addressStreet, if there is no Person.addressStreet property in the source bean and no PersonDto.Address.street in the target bean.

Hook into the mapping process by calling @BeforeMapping / @AfterMapping methods

... e.g. to call a certain method that might flush the entity manager before starting to map ;).

Perhaps by:

  • making the Freemarker template file name configurable in the AP
  • or (perhaps better): allow to specify a super class for the mapping impl and call before / after methods. The super class might define methods for that, annotated with @BeforeMapping or something similar.

Cheers,
Andreas

Avoid redundancy in FreeMarker template

Currently the FreeMarker template has two nearly identical sections for generating a mapping method and its reverse mapping method. Investigate how this could be avoided.

Optionally raise an error if an attribute in the target object is unmapped

There should be an option (global as well as on on the mapper level) for configuring whether an error should be raised if an attribute of the target type of a mapping method is not set in the implemented method since there is no corresponding source attribute.

Depending on the use case this can indicate a bug with the object structure, e.g. when an attribute of a view object is not populated.

Move Mappers type to another package

The Mappers type should be moved to something like org.mapstruct.factory as it is independent from the annotations and likely to be used not that much due to the recent CDI/Spring enablement.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.