当前位置: 首页 > 知识库问答 >
问题:

使用自定义转换器在推土机中进行单向映射

袁卓
2023-03-14

请注意:如果这确实是实现我所寻找的目标的唯一方法,那么我会接受基于XML的解决方案,但我更喜欢使用Dozer的Java API的解决方案。

我是推土机的新手,正在尝试了解如何使用其API。它似乎默认为字段级映射(如果字段名称匹配),并允许在字段级映射(基于字段名称)不可能或不符合应用程序需要的情况下使用自定义映射器和转换器。

我有一种情况,我的应用程序将接受一个DTO,例如,ReportedIssue(一个由用户报告并通过HTTP发送到我的应用程序的问题)和一个issue(一个将持久化到MySQL DB的数据实体)。

以下是我的两个对象:

@Data
public class ReportedIssue {

    private String typeRefId;
    private String reporterRefId;
    private String info;

}

@Entity
@Table(name = "issues")
@Data
public class Issue {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = "issue_ref_id")
    private String refId;

    @Column(name = "issue_tracking_number")
    private String trackingNumber;

    @OneToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "issue_type_id", referencedColumnName = "issue_type_id")
    private IssueType type;

    @Column(name = "issue_reported_on")
    private Date reportedOn;

    @OneToOne(fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "issue_reporter_id", referencedColumnName = "account_id")
    private Account reporter;

    @Column(name = "issue_info")
    private String info;

}

因此,在应用程序前端,用户可以报告问题。前端将一个JSON版本的ReportedIssue发送到后端,在那里JSON被反序列化为一个DTO bean。然后,我需要Dozer将我的ReportedIssue转换为一个实体,然后我可以轻松地将其保存到MySQL数据库中。

以下是我的最佳尝试:

public class ReportedIssueConverter extends DozerConverter<ReportedIssue, Issue> {

    private AuthService authService;

    public ReportedIssueConverter(AuthService authService, Class<ReportedIssue> prototypeA, Class<Issue> prototypeB) {
      super(prototypeA, prototypeB);
      this.authService = authService;
    }

    public ReportedIssueConverter(Class<ReportedIssue> prototypeA, Class<Issue> prototypeB) {
        super(prototypeA, prototypeB);
    }

    @Override
    public Issue convertTo(ReportedIssue source, Issue destination) {

        Issue issue = new Issue();
        issue.setRefId(UUID.randomUUID().toString());
        issue.setType(IssueUtils.determineType(source));
        issue.setReportedOn(DateTimeUtils.nowInUTC());
        issue.setReporter(authService.currentUser());
        issue.setInfo(destination.getInfo());

        return issue;

    }

    @Override
    public ReportedIssue convertFrom(Issue source, ReportedIssue destination) {
        throw new UnsupportedOperationException("we currently don't map from issues to reported issues");
    }

}

这里有几个问题。首先,这样一个自定义转换器是必要的吗?或者是否有“更好的”(更符合标准或使用普遍接受的推土机实践)方法来使用推土机API执行此转换?但是,这个DozerConverter似乎主要用于双向映射用例。然而,在我的应用程序中,我永远不会有问题实例,需要将其映射回报告问题实例。因此,我只需要来自ReportedIssue的单向映射--


共有2个答案

夏知
2023-03-14

Gauntham的答案会奏效的。另一种选择:

实现com.github.推土机绘图机。果心BeanFactory您的自定义BeanFactory可以处理

Issue issue = new Issue();
issue.setRefId(UUID.randomUUID().toString());
issue.setReportedOn(DateTimeUtils.nowInUTC());
issue.setReporter(authService.currentUser());

然后根据您的喜好,这也可以进入豆子工厂

issue.setType(IssueUtils.determineType(source));

或者您可以在映射中单独处理它。需要知道如何调用IssueUtils,因此这要么是1)客户转换器,要么是2)对DTO或实体的更改,以便通过getter或setter获得功能

最后,这一行将在Dozer Java API映射中处理

issue.setInfo(destination.getInfo());

就个人而言,我喜欢推土机的com.github.推土机绘图机。果心装载机。应用程序编程接口。BeanMappingBuilder,其中可以明确告诉它如何映射2个bean,指定要使用的bean工厂和特定字段的自定义转换器。

mapping(ReportedIssue.class, Issue.class, oneWay(), wildcard(true), beanFactory(IssueBeanFactory.class.getName()).fields("this", "type", customConverter(IssueTypeConverter.class)

oneWay()、通配符(布尔)和beanFactory(字符串)可在推土机的TypeMappingOptions中找到,customConverter(Class.Class)可在推土机的FieldMappingOptions中找到。

  • oneWay()使映射仅在BeanMappingBuilder中指定的方向上工作
谯灿
2023-03-14

实际上,它可以在没有自定义转换器的情况下完成,在您的dto类中使用自定义getter方法来对应问题中的字段。Dozer通过尝试调用源类中相应名称的getter方法来映射目标类中的每个字段。

public class ReportedIssue {
    // fields.......

    public String getRefId() {
        UUID.randomUUID().toString()
    }

    public IssueType getType() {
        IssueUtils.determineType(this);
    }

    // similarly create getters for other required fields.

}

但对于问题中的报告者字段,您需要一个AuthService对象。我建议编写一个静态方法,如下所示:

public static Issue getIssue(AuthService auth, ReportedIssue dto) {
    Issue issue = //map using dozer
    issue.setReporter(authService.currentUser());
    return issue;
}
 类似资料:
  • 我一直在寻找在推土机映射中设置常量值的解决方案,并且在stackoverflow上阅读了很多关于这个问题的答案。所以我决定使用推土机自定义转换器。 让我澄清一下我的情况。 我有两个具有以下字段的bean: 豆A: Bean B: 的字段应始终等于。 因此,我创建了一个自定义转换器: 以及以下映射: 它工作得很好,并将值设置为。但是这种方法看起来很糟糕: 我必须在XML映射中设置一个字段作为源,才能

  • 我不确定我是否正确理解推土机映射器中的自定义创建方法。我需要将int类型的bean属性转换为TransTypeCodebook对象实例。但我得到了: 我的TransTypeCodebook课程 映射器部分 我设法通过自定义转换器解决了这个问题,但我不确定我是否理解自定义创建方法的概念,我想知道这个字符串是从哪里来的。有人能解释一下吗?

  • 考虑以下类。如何在不使用自定义转换器的情况下使用Dozer将A类转换为B类? 有人能为上述类提供推土机映射XML吗?

  • 在Dozer的帮助下,我想将映射到DTO类 但是这两种设置

  • 我试图使用Dozer映射UUID字段,遇到了Dozer github上提到的一个问题: https://github.com/DozerMapper/dozer/issues/83 问题是-显然,Dozer依赖于UUID中不存在的默认无参数构造函数。因此,该链接显示了如何告知推土机执行参考复制。然而,使用该提示并没有帮助,我仍然会遇到以下异常: org.dozer.java.lang.java.u

  • 我想让推土机地图成为我的职业: 到生成的,如下所示: . 也就是说,我正在尝试将嵌套类的字段映射到平面键目标。我使用的是JavaAPI的Dozer,而不是xml。我无法找到适当的构建器配置来管理它。基本代码类似于: