8

私は親クラスとして :とUser.java2 つのクラスを持っています:を使用してデータベースの型列に応じて返されるエンティティです。FacebookUser または TwitterUser のインスタンスである可能性のある User をマップする正しいマッパーを書きたいと思います。私は意図したとおりに動作しないように見える次のマッパーを持っています。子ではなく親をマッピングするだけです:FacebookUser.javaTwitterUser.javaDiscriminatorColumnUser

@Mapper
public interface UserMapper {
    public static UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    User map(UserDTO userDTO);

    @InheritInverseConfiguration
    UserDTO map(User user);

    List<UserDTO> map(List<User> users);

    FacebookUser map(FacebookUserDTO userDTO);

    @InheritInverseConfiguration
    FacebookUserDTO map(FacebookUser user);

    TwitterUser map(TwitterUserDTO userDTO);

    @InheritInverseConfiguration
    TwitterUserDTO map(TwitterUser user);

}

それから私は使用します:

UserDTO userDto = UserMapper.INSTANCE.map(user);

マップするクラス:

@Entity
@Table(name = "users")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "type", discriminatorType = DiscriminatorType.STRING, length = 10)
@DiscriminatorValue(value = "Local")
public class User {
    @Column
    private String firstName;
    @Column
    private String lastName;
    ///... setters and getters
}

@Entity
@DiscriminatorValue(value = "Facebook")
public class FacebookUser extends User {
    @Column
    private String userId;
    ///... setters and getters
}

@Entity
@DiscriminatorValue(value = "Twitter")
public class TwitterUser extends User {
    @Column
    private String screenName; 
    ///... setters and getters
}

DTO:

public class UserDTO {
    private String firstName;
    private String lastName;
    ///... setters and getters
}

public class FacebookUserDTO extends UserDTO {
    private String userId;
    ///... setters and getters
}

public class TwitterUserDTO extends UserDTO {
    private String screenName; 
    ///... setters and getters
}

また、Facebook ユーザーと Twitter ユーザー、または基本ユーザーが混在するユーザーのリストがある場合:

次のユーザーがいるとしましょう。

User user = new User ("firstName","lastName");
User fbUser = new FacebookUser ("firstName","lastName","userId");
User twUser = new TwitterUser ("firstName","lastName","screenName");

List<User> users = new ArrayList<>();
users.add(user);
users.add(fbUser);
users.add(twUser);

//Then: 

List<UserDTO> dtos = UserMapper.INSTANCE.map(users);

私はfirstNameandだけを取得しますが、 orは取得しlastNameません。screenNameuserId

これに対する解決策はありますか?

4

1 に答える 1

8

現在、 mapstruct の機能としてはまだ利用できないようです: Type-Refinement マッピング (またはダウンキャスト マッピング) のサポート

Google グループで質問しました: https://groups.google.com/forum/?fromgroups#!topic/mapstruct-users/PqB-g1SBTPg

defaultインターフェイス内のメソッドを使用して手動でマッピングを行う必要があることがわかりました(Java 8の場合)。

そして、ほとんど適用できない親のマッピングに関する別の問題が発生したため、親クラスの子が呼び出す空のクラスをもう1つ作成しますLocalUserDTO

したがって、コードは次のようになります。

@Mapper
public interface UserMapper {
    public static UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);

    LocalUser map(LocalUserDTO userDTO);

    @InheritInverseConfiguration
    LocalUserDTO map(LocalUser user);


    List<UserDTO> map(List<User> users);

    FacebookUser map(FacebookUserDTO userDTO);

    @InheritInverseConfiguration
    FacebookUserDTO map(FacebookUser user);

    TwitterUser map(TwitterUserDTO userDTO);

    @InheritInverseConfiguration
    TwitterUserDTO map(TwitterUser user);

    default UserDTO map(User user) {

        if (user instanceof FacebookUser) {
            return this.map((FacebookUser) user);
        } else if (user instanceof TwitterUser) {
            return this.map((TwitterUser) user);
        } else {
            return this.map((LocalUser) user);
        }
    }

    @InheritInverseConfiguration
    default User map(UserDTO userDTO) {
        if (userDTO instanceof FacebookUserDTO) {
            return this.map((FacebookUserDTO) userDTO);
        } else if (userDTO instanceof TwitterUserDTO) {
            return this.map((TwitterUserDTO) userDTO);
        } else {
            return this.map((LocalUserDTO) userDTO);
        }
    }

}
于 2016-10-03T08:37:46.610 に答える