我的父类是:User.java
和2个类:FacebookUser.java
和TwitterUser.java
它们是使用DiscriminatorColumn
返回的实体,取决于数据库中的类型列,我想编写正确的Map器来Map可能是FacebookUser或TwitterUser示例的用户。我有以下Map器,似乎没有按预期工作,仅MapUser
父项而不是子项:
@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);
要Map的类:
@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);
我只得到了firstName
和lastName
,但没有screenName
或userId
。
有什么解决办法吗?
2条答案
按热度按时间rsl1atfo1#
目前,它似乎还不能作为mapstruct的一个特性:Support for Type-Refinement mapping (or Downcast Mapping)
我在他们的谷歌群里问了一个问题:https://groups.google.com/forum/?fromgroups#!topic/mapstruct-users/PqB-g1SBTPg
并发现我需要使用接口内部的
default
方法进行手动Map(对于Java 8)。并且得到了另一个几乎不适用的Map父类的问题,所以我再写一个空类,父类的子类叫做
LocalUserDTO
:因此代码如下所示:
c9x0cxw02#
我昨天在谷歌上搜索了这个问题,但是在网上找不到任何东西,所以让我们把这个留在这里。
由于前一个答案中提到的问题已经在今年早些时候得到解决,Mapstruct现在正式支持通过
@SubclassMapping
进行向下转换。但是你不能把参数化类
List<User>
放到那个注解中,而且Mapstruct实际上并没有使用上面的List规范,因此,还需要一个函数。这也适用于类中的字段。对于我的情况,我们有一个类似于类中的列表字段。最初我只添加了
@SubclassMapping
,但在检查了Mapstruct生成的代码后,我发现它没有使用列表转换的方法。添加@IterableMapping
修复了这一问题。考虑一个包含列表字段的
UsersWrapper
类。和一个
UsersWrapperDTO
。然后,我们可以在Map器中使用另一种方法。
Mapstruct实际上生成了可读性很强的代码,所以如果您发现它的工作方式不如您想象的那样,首先检查一下也是一种选择。
我对Mapstruct不熟悉,所以花了一个下午的时间才把它们拼在一起!不过,我需要把这两个注解组合在一起,这看起来确实很简单,也很有意义。希望这篇文章能为人们节省一些时间。