MapStructで拡張クラスをマップする方法

Aug 23 2020

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();
    }

回答

2 Pankaj Aug 23 2020 at 19:51

buiderコードを入力していないので)問題は、ビルダークラスに親クラスフィールドが含まれていないことだと思います。MapStructは、マッパーのコードを生成する際にいくつかの仮定を行います。ドキュメントから-

BuilderProviderのデフォルトの実装は、次のことを前提としています。

  1. この型には、ビルダーを返すパラメーターのないpublic staticbuilder作成メソッドがあります。したがって、たとえば、PersonにはPersonBuilderを返すパブリック静的メソッドがあります。
  2. ビルダータイプには、ビルド中のタイプを返すパラメーターのないパブリックメソッド(buildメソッド)があります。この例では、PersonBuilderにはPersonを返すメソッドがあります。
  3. 複数のビルドメソッドがある場合、MapStructはビルドと呼ばれるメソッドを探します。そのようなメソッドが存在する場合はこれが使用され、そうでない場合はコンパイルエラーが作成されます。

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();
}