11

I have Object1 and Object2. Now, I want to map object3, with attributes from 1 & 2.

Say, I have 2 object:

1. User: {first_name, last_name, id}
2. Address: {street, locality, city, state, pin, id}

Now, with these, I want to map that in

User_View: {firstName, lastName, city, state}.

Where, first_name & last_name will be from User object and city & state from Address object.

Now, my question is, how to do that?

However, currently, I'm doing like this

@Mapper    
public abstract class UserViewMapper {
        @Mappings({
                    @Mapping(source = "first_name", target = "firstName"),
                    @Mapping(source = "last_name", target = "lastName"),
                    @Mapping(target = "city", ignore = true),
                    @Mapping(target = "state", ignore = true)

            })
            public abstract UserView userToView(User user);

        public UserView addressToView(UserView userView, Address address) {

                if (userView == null) {
                    return null;
                }

                if (address == null) {
                    return null;
                }

                userView.setCity(address.getCity());
                userView.setState(address.getState()); 

            return userView;

            }
    }

But, here, I have to manually write the mapping in addressToView().

Therefore, is there, any way, to avoid that?

Or, what would be the preferred way, to handle such situations?

anij
  • 1,322
  • 5
  • 23
  • 39

2 Answers2

13

You can declare a mapping method with several source parameters and refer to the properties of all these parameters in your @Mapping annotations:

@Mapper
public abstract class UserViewMapper {

    @Mapping(source = "first_name", target = "user.firstName"),
    @Mapping(source = "last_name", target = "user.lastName"),
    public abstract UserView userAndAddressToView(User user, Address address);
}

As the "city" and "state" property names match in source and target, there is no need for mapping them.

Also see the chapter "Defining a mapper" in the reference documentation for more details.

Gunnar
  • 18,095
  • 1
  • 53
  • 73
  • Thanks for the quick reply. one question, what, if i have same attribute in both the input objects, that means, what if, User & Address, both have an attribute with same name, which one, will be mapped, or how i will define the source for that? – anij Dec 07 '15 at 10:48
  • 3
    I think you are mixing up source and target in your answer. It should be: `@Mapping(source = "user.first_name", target = "firstName")` – fuemf5 Feb 14 '18 at 14:13
0

Using MapStruct you are missing a step using the @Mapper annotation. The @Mapper will create the implementation of the mappings.

You should review the docs at this link http://mapstruct.org/documentation/stable/reference/html/

Specifically

  1. Defining a mapper

In this section you’ll learn how to define a bean mapper with MapStruct and which options you have to do so. 3.1 Basic mappings

To create a mapper simply define a Java interface with the required mapping method(s) and annotate it with the org.mapstruct.Mapper annotation:

@Mapper
public interface CarMapper {

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

    @Mapping(source = "name", target = "fullName")
    PersonDto personToPersonDto(Person person);
}

The @Mapper annotation causes the MapStruct code generator to create an implementation of the CarMapper interface during build-time.

Gunnar
  • 18,095
  • 1
  • 53
  • 73
Mike Murphy
  • 1,006
  • 8
  • 16
  • If [Java8, @Mappings not necessary](https://mapstruct.org/documentation/dev/api/org/mapstruct/Mappings.html): "When using Java 8 or later, you can omit the @ Mappings wrapper annotation and directly specify several @ Mapping annotations on one method." – cellepo Aug 30 '23 at 23:27