如何在MapStruct中映射扩展类

huangapple go评论56阅读模式
英文:

How to map extended classes in MapStruct

问题

关于 mapStruct 的问题。我有一个情况,在这种情况下我从基本实体类扩展了一个类,不确定如何进行映射。以下是我的情况。

BaseEntity:

public class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "id")
    private Long id;
}

BaseDto:

public class BaseDto {
    private Long id;
}

UserEntity:

public class User extends BaseEntity {
    private String name;
    private String lastName;
    private String username;
    private String password;
    private String profilePicturePath;
}

UserDto:

public class UserDto extends BaseDto {
    private String name;
    private String lastName;
    private String username;
    private String password;
    private String profilePicturePath;
}

映射器如下:

@Mapper(uses = {BaseMapper.class})
public interface UserMapper {
    User userDtoToUser(UserDto userDto);
    UserDto userToUserDto(User user);
}

BaseMapper:

@Mapper
public interface BaseMapper {
    BaseEntity dtoToEntity(BaseDto baseDto);
    BaseDto entityToDto(BaseEntity baseEntity);
}

问题是我没有获得 ID 属性的映射。

谢谢您的时间。

编辑:

没有显示错误,在映射器实现(生成的代码)中没有为该 ID 进行映射:

@Override
public User userDtoToUser(UserDto userDto) {
    if ( userDto == null ) {
        return null;
    }

    UserBuilder user = User.builder();

    user.name( userDto.getName() );
    user.lastName( userDto.getLastName() );
    user.username( userDto.getUsername() );
    user.password( userDto.getPassword() );
    user.profilePicturePath( userDto.getProfilePicturePath() );

    return user.build();
}
英文:

Gotta question regarding mapStruct. I have case where I extend class from base entity and not sure how to map it. Here is my case.

BaseEntity:

public class BaseEntity {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name = "id")
    private Long id;
}

BaseDto:

public class BaseDto {

    private Long id;
}

UserEntity:

public class User extends BaseEntity {
    private String name;
    private String lastName;
    private String username;
    private String password;
    private String profilePicturePath;
}

UserDto:

public class UserDto extends BaseDto {
    private String name;
    private String lastName;
    private String username;
    private String password;
    private String profilePicturePath;
}

And mapper is like this:

@Mapper(uses = {BaseMapper.class})
public interface UserMapper {

    User userDtoToUser(UserDto userDto);

    UserDto userToUserDto(User user);
}

BaseMapper:

@Mapper
public interface BaseMapper {

    BaseEntity dtoToEntity(BaseDto baseDto);

    BaseDto entityToDto(BaseEntity baseEntity);
}

Problem is that I don't get ID property mapped.

Thank you for your time.

EDIT:

There is no error shown, in mapper implementation (generated code) there is no mapping for that ID:

 @Override
    public User userDtoToUser(UserDto userDto) {
        if ( userDto == null ) {
            return null;
        }

        UserBuilder user = User.builder();

        user.name( userDto.getName() );
        user.lastName( userDto.getLastName() );
        user.username( userDto.getUsername() );
        user.password( userDto.getPassword() );
        user.profilePicturePath( userDto.getProfilePicturePath() );

        return user.build();
    }

答案1

得分: 4

我猜测(因为您没有放置“builder”代码),问题可能在于您的构建器类未包含父类字段。MapStruct 在生成映射器的代码时会做一些假设。根据文档 -

> BuilderProvider 的默认实现假定以下内容:

  1. 该类型具有无参数的公共静态构建器创建方法,该方法返回一个构建器。例如,Person 具有一个返回 PersonBuilder 的公共静态方法。
  2. 构建器类型具有无参数的公共方法(构建方法),该方法返回正在构建的类型。在我们的示例中,PersonBuilder 有一个返回 Person 的方法。
  3. 如果存在多个 build 方法,则 MapStruct 将寻找一个名为 build 的方法,如果存在此类方法,则将使用该方法,否则将创建编译错误。

如果您正在使用 Lombok,可以通过使用 @SuperBuilder 来解决此问题,如下所示 -

@SuperBuilder
@Getter
@ToString
public class UserDto extends BaseDto {
  private String name;
  private String lastName;
  private String username;
  private String password;
  private String profilePicturePath;
}

@Getter
@SuperBuilder
class BaseDto {
  private Long id;
}

@SuperBuilder
@Getter
@ToString
public class User extends BaseEntity {
  private String name;
  private String lastName;
  private String username;
  private String password;
  private String profilePicturePath;
}

@Setter
@Getter
@SuperBuilder
class BaseEntity {
  private Long id;
}

并且生成的代码可能如下所示 -

@Override
public User userDtoToUser(UserDto userDto) {
    if ( userDto == null ) {
        return null;
    }

    UserBuilder<?, ?> user = User.builder();

    user.id( userDto.getId() );
    user.name( userDto.getName() );
    user.lastName( userDto.getLastName() );
    user.username( userDto.getUsername() );
    user.password( userDto.getPassword() );
    user.profilePicturePath( userDto.getProfilePicturePath() );

    return user.build();
}
英文:

I'm guessing (as you have not put buider code) the problem is that your builder class does not include parent class field. MapStruct makes some assumption while generating code for mapper. From documentation -

> The default implementation of the BuilderProvider assumes the
> following:

  1. The type has a parameterless public static builder creation method
    that returns a builder. So for example Person has a public static
    method that returns PersonBuilder.
  2. The builder type has a parameterless public method (build method)
    that returns the type being build In our example PersonBuilder has a
    method returning Person.
  3. In case there are multiple build methods, MapStruct will look for a
    method called build, if such method exists then this would be used,
    otherwise a compilation error would be created.

If you are using Lombok, you can solve this by using @SuperBuilder as -

@SuperBuilder
@Getter
@ToString
public class UserDto extends BaseDto {
  private String name;
  private String lastName;
  private String username;
  private String password;
  private String profilePicturePath;
}

@Getter
@SuperBuilder
class BaseDto {
  private Long id;
}

@SuperBuilder
@Getter
@ToString
public class User extends BaseEntity {
  private String name;
  private String lastName;
  private String username;
  private String password;
  private String profilePicturePath;
}

@Setter
@Getter
@SuperBuilder
class BaseEntity {
  private Long id;
}

And generated could looks like -

@Override
public User userDtoToUser(UserDto userDto) {
    if ( userDto == null ) {
        return null;
    }

    UserBuilder<?, ?> user = User.builder();

    user.id( userDto.getId() );
    user.name( userDto.getName() );
    user.lastName( userDto.getLastName() );
    user.username( userDto.getUsername() );
    user.password( userDto.getPassword() );
    user.profilePicturePath( userDto.getProfilePicturePath() );

    return user.build();
}

huangapple
  • 本文由 发表于 2020年8月23日 19:39:05
  • 转载请务必保留本文链接:https://go.coder-hub.com/63546495.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定