我想使用 mapstruct 将 String 转换为 enum
enum TestEnum {
NO("no");
String code;
TestEnum(String code) {
this.code = code
}
public String getCode() {
return code;
}
}
Run Code Online (Sandbox Code Playgroud)
我有一个从服务中获得的代码,我想将此代码转换为 Enum 如何通过 mapstruct 以更简单的方式执行此操作
还没有弄清楚如何传递额外的参数或替代方案。
目前我正在映射订单和订单行。两个对象是不同的并且需要@mappings。示例我有一个 Order 和 OrderRequest 对象,两者都不同,需要 @Mappings 注释来映射值,与 OrderLines 相同。
我创建了以下映射器
所以我的问题是 OrderLine 需要来自 Order 对象的 OrderId。然而,在 OrderLineMapper 中,它传递的是 OrderLine 而不是 Order。如何将 OrderId 发送到 OrderLineMapper?目前,我让 OrderMapper 执行 @AfterMapper,循环遍历 orderLines 并填充 OrderId。
任何帮助都会很棒。
类 订单映射器
@Mapper(componentModel = "spring", uses = {OrderLineMappers.class})
public abstract class OrderMapper {
@AfterMapping
protected void orderRequestFromOrder( Order order, @MappingTarget
OrderRequest orderRequest ) {
//Wanting to do this at the OrderLineMapper class and not here
String orderId = order.getId();
List<OrderLineRequest> lines …Run Code Online (Sandbox Code Playgroud) 我找不到任何关于 jackson 的 ObjectMapper 与其他映射器(如 dozer/mapStruct/modelMapping/等)之间差异的解释。所有的文章都比较了 dozer/mapStruct/modelMapping 但他们忽略了 ObjectMapper。我不明白有什么问题?是同一个映射器吗?
我有父级(产品)和子级(书籍、家具),并且希望将产品实体映射到产品 DTO。如您所见,产品被映射并存储在数据库中的单个表中。如何映射具有子项额外详细信息的父项产品?
实体
@Entity
@Table(name = "product")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class Product {
@Id
private long id;
private String productName;
}
@Entity
@DiscriminatorValue("Book")
public class Book extends Product {
private String author;
...
}
@Entity
@DiscriminatorValue("Furniture")
public class Furniture extends Product {
String color;
...
}
Run Code Online (Sandbox Code Playgroud)
数据传输组织
public class ProductDto {
private long id;
private String productName;
...
}
public class BookDto extends ProductDto {
private String author;
...
}
public class …Run Code Online (Sandbox Code Playgroud) 我想映射以下类
class Schedule {
ZoneId timezoneId;
List<AvailabilityRule> rules;
}
Run Code Online (Sandbox Code Playgroud)
class AvailabilityRule {
long startEpoch;
long endEpoch;
}
Run Code Online (Sandbox Code Playgroud)
到这些课程。
class ScheduleDTO {
String timezone;
List<AvailabilityRuleDTO> rules;
}
Run Code Online (Sandbox Code Playgroud)
class AvailabilityRuleDTO {
ZonedDateTime startTime;
ZonedDateTime endTime;
}
Run Code Online (Sandbox Code Playgroud)
timezoneId计算时startEpoch需要和startTime。
Instant instant = Instant.ofEpochMilli(startEpoch);
ZonedDateTime zonedDateTime = instant.atZone(timezoneId);
Run Code Online (Sandbox Code Playgroud)
我如何使用mapstruct 来实现这一点?
我想要的伪代码
@Mapping(source = {"startEpoch", "timezoneId"}, target = "startTime", qualifiedByName = "epochToString")
AvailabilityRuleDTO toAvailabilityRuleDTO(AvailabilityRule
availabilityRule, Schedule schedule);
Run Code Online (Sandbox Code Playgroud) 我正在处理与数据库中的延迟加载对象相关的问题。
假设我们有以下实体。
@Entity(name = "User")
@Table(name = "USERS")
public class User{
@Id
@GeneratedValue
private int id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="NOTES_ID")
private List<Note> notes;
}
Run Code Online (Sandbox Code Playgroud)
而 Dto 将是
@Mapper
public interface UserDtoMapper{
/** the INSTACE HERE **/
User fromDto(UserDto dto);
UserDto toDto(User user);
}
Run Code Online (Sandbox Code Playgroud)
那么哪个可能是获取所有用户而没有 EJBException 的最佳方法,因为我正在获取他们懒惰?
编辑:解决方案
假设您有以下数据模型
@Entity(name = "User")
@Table(name = "USERS")
public class User{
@Id
@GeneratedValue
private int id
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name="NOTES_ID")
private List<Note> notes;
}
Run Code Online (Sandbox Code Playgroud)
addresses但因为延迟加载(通过休眠或任何其他框架)最终会出现异常。此外,您可以忽略addressesfrom 被映射,如@Mehmet …
我已经开始使用 Mapstruct 将 JPA 实体映射到 DTO。对于基本实体,这非常有效。
我的问题:某些实体具有延迟加载的集合,其中包含我不希望总是想要获取和映射的其他详细信息。作为解决方案,我添加了一个基本超类,其中包含始终映射的所有字段,以及一个包含集合的子类。它们都代表相同的实体,因此它们使用相同的源类。
当我尝试创建一个包含映射到来自同一源的两种类型的方法的 Mapper 时,即使方法签名(至少是返回类型)不同,我也会收到一个不明确的映射方法错误。我会以错误的方式解决这个问题吗?我不能使用相同源的 DTO 使用子类吗?
编辑: 以防万一,我正在使用 mapstruct-jdk8:1.1.0.Final
编辑 2: 下面的例子只是我头顶上的一个例子。当我实际使用代码时,它起作用了。事实证明,我的问题是示例中未包含的内容。当我添加映射票证集合的方法时,似乎发生了错误。这可能意味着问题与继承无关(直接?)。我可能缺少一些配置,但我不确定要查找什么。
简单的例子:
票务实体
public class Ticket {
private long id;
private String title;
private Set<Comment> comments;
// Getters and setters
}
Run Code Online (Sandbox Code Playgroud)
票务DTO
public class TicketDTO {
private long id;
private String title;
// Getters and setters
}
Run Code Online (Sandbox Code Playgroud)
带有评论的票 DTO
public class TicketWithCommentsDTO extends TicketDTO {
private List<CommentDTO> comments;
// Getters and setters
}
Run Code Online (Sandbox Code Playgroud)
票务映射器界面
@Mapper(uses= { CommentMapper.class })
public interface TicketMapper {
TicketDTO …Run Code Online (Sandbox Code Playgroud) 我需要一个映射来实现此目的:
@Mapping(source = "a", target = "result.transactions[0].a"),
@Mapping(source = "b", target = "result.transactions[0].b"),
@Mapping(source = "c", target = "result.transactions[0].c"),
...
Response dataToResponse(DataModel model);
Run Code Online (Sandbox Code Playgroud)
但这种语法不起作用(顺便说一句:这适用于 Spring Bean 包装器)。这样的解决方案只是一个半生不熟的解决方案:
@AsList
public <T> List<T> asList( T in ) {
List<T> result = new ArrayList<T>();
if ( in!=null ) {
result.add(in);
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
这仅适用于一个属性,因为它总是为每个属性创建一个新列表。我不需要将每个属性映射到新列表的第一个元素。该列表必须重复使用,但我不知道这是如何工作的。实现这一目标的正确方法是什么?我想到了这样的事情:
@Mapping(source = "a", target = "transaction.a"),
@Mapping(source = "b", target = "transaction.b"),
@Mapping(source = "c", target = "transaction.c"),
...
Transaction dataToTransaction(DataModel model);
Run Code Online (Sandbox Code Playgroud)
进而...
@Mapping([use Transaction from …Run Code Online (Sandbox Code Playgroud) 我想将MapStruct映射器与Spring的Conversion模型结合起来。因此,我将每个Mapper接口声明为Spring的扩展Converter:
@Mapper
public interface CarMapper extends Converter<Car, CarDto> {
@Override
CarDto convert(Car car);
}
Run Code Online (Sandbox Code Playgroud)
然后,我可以通过注入standard来使用mapper bean ConversionService:
class CarWarehouse {
@Autowired
private ConversionService conversionService;
...
public CarDto getCarInformation(Car car) {
return conversionService.convert(car, CarDto.class);
}
}
Run Code Online (Sandbox Code Playgroud)
这很好用,但是我想知道是否有一种方法可以避免通过uses属性直接将一些Mappers注入到其他对象中。我想要做的是告诉映射到use了ConversionService雇用其他制图。但是,由于ConversionService的convert方法与MapStruct的映射方法的标准模式不匹配,因此代码生成插件无法识别在寻找子映射时可以使用该服务。基本上,我想写的是
@Mapper(uses=ConversionService.class)
public interface ParentMapper extends Converter<Parent, ParentDto>
Run Code Online (Sandbox Code Playgroud)
代替
@Mapper(uses={ChildMapper1.class, ChildMapper2.class, ChildMapper3.class})
public interface ParentMapper extends Converter<Parent, ParentDto>
Run Code Online (Sandbox Code Playgroud)
有没有办法做到这一点?
编辑
既然有人问过了,可以说我有一个CarMapper上面的定义,它的类型Car和CarDto …
我有一个项目,我经常在其中映射 dto -> db 模型。几乎我所有的数据库模型都有一些附加字段,例如版本,这些字段从未从 dto 映射。
是否有任何可能性或优雅的解决方法可以仅通过名称全局忽略目标字段?
现在我必须使用@Mapping(target = "version", ignore = true). 无法使用@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE),因为当我不小心遗漏任何重要属性时,我希望收到警告或错误。我使用 控制默认行为'-Amapstruct.unmappedTargetPolicy=WARN',在开发新函数期间我将其更改为 ERROR。
有些人可能会说这些只是警告,但是当警告太多时,就更难发现错误。
Mapstruct 1.3.1.Final,可能会在不久的将来迁移到 1.4.1.Final。搜索了文档,但找不到任何有用的东西。
预先感谢您的回答:)
mapstruct ×10
java ×8
mapping ×3
enums ×1
hibernate ×1
jackson ×1
java-ee-7 ×1
lazy-loading ×1
mapper ×1
modelmapper ×1
objectmapper ×1
spring ×1
spring-boot ×1