Mapstruct 版本 1.2.0.Final 不转换嵌入式类型?

Mapstruct version 1.2.0.Final not converting embedded types?

完成 mapstruct tutorial 之后,我的印象是 Mapstruct 确实正确地转换了嵌入类型。我不确定我在这里做错了什么。任何建议将不胜感激...

我在 IntelliJ 2017 中工作,安装了 Mapstruct 插件。失败的测试包括声明嵌入对象(在本例中为 jobData 对象内的作业对象)为空:

java.lang.AssertionError: Expected: is not null but: was null Expected :is not null

实际:空

以下代码是源、目标、映射器接口和实现,以及失败的测试。一件有趣的事是 impls 没有为嵌入式类型调用转换器的引用。

@Entity
@Data
@NoArgsConstructor
public class JobData {

    private static final long serialVersionUID = 1L;

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

    @OneToOne
    private Job job;

    @Size(min = 5, max = 50)
    private String providerName;
}

@Data
@NoArgsConstructor
public class JobDataDTO {

    private static final long serialVersionUID = 1L;
    private Long id;
    private JobDTO jobDTO;
    private String providerName;
}

@Data
@NoArgsConstructor
public class JobDTO {

    private static final long serialVersionUID = 1L;
    private Long id;
    private JobState jobState;
    private Date creationDateTime;
}

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Job {

    private static final long serialVersionUID = 1L;

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

    @NotNull
    @Enumerated(value = EnumType.STRING)
    private JobState jobState;

    @NotNull
    private Date creationDateTime;
}


@Mapper
public interface JobDataMapper {
    JobDataMapper INSTANCE = Mappers.getMapper(JobDataMapper.class);
    JobDataDTO jobDataToJobDataDTO(JobData jobData);
    JobData jobDataDTOToJobData(JobDataDTO jobData);
    JobDTO jobToJobDTO(Job job);
    Job jobDTOToJob(JobDTO jobDTO);

}

@Generated(
    value = "org.mapstruct.ap.MappingProcessor",
    date = "2018-03-24T16:33:39-0600",
    comments = "version: 1.2.0.Final, compiler: javac, environment: Java 1.8.0_144 (Oracle Corporation)"
)
@Component
public class JobDataMapperImpl implements JobDataMapper {

    @Override
    public JobDataDTO jobDataToJobDataDTO(JobData jobData) {
        if ( jobData == null ) {
            return null;
        }

        JobDataDTO jobDataDTO = new JobDataDTO();

        jobDataDTO.setId( jobData.getId() );
        jobDataDTO.setProviderName( jobData.getProviderName() );

        return jobDataDTO;
    }

    @Override
    public JobData jobDataDTOToJobData(JobDataDTO jobData) {
        if ( jobData == null ) {
            return null;
        }

        JobData jobData1 = new JobData();

        jobData1.setId( jobData.getId() );
        jobData1.setProviderName( jobData.getProviderName() );

        return jobData1;
    }

    @Override
    public JobDTO jobToJobDTO(Job job) {
        if ( job == null ) {
            return null;
        }

        JobDTO jobDTO = new JobDTO();

        jobDTO.setId( job.getId() );
        jobDTO.setJobState( job.getJobState() );
        jobDTO.setCreationDateTime( job.getCreationDateTime() );

        return jobDTO;
    }

    @Override
    public Job jobDTOToJob(JobDTO jobDTO) {
        if ( jobDTO == null ) {
            return null;
        }

        Job job = new Job();

        job.setId( jobDTO.getId() );
        job.setJobState( jobDTO.getJobState() );
        job.setCreationDateTime( jobDTO.getCreationDateTime() );

        return job;
    }
}

public class JobDataMapperTest {

    private static final long TEST_LONG = 1L;
    private static final String TEST_STRING = "CUSTOMER";
    private static final Date TEST_DATE = new Date();

    private JobDataMapper jobDataMapper = JobDataMapper.INSTANCE;

    private Job job;
    private JobData jobData;

    private JobDTO jobDTO;
    private JobDataDTO jobDataDTO;

    @Before
    public void setUp() throws Exception {
        job = new Job();
        jobDTO = new JobDTO();

        jobData = new JobData();
        jobDataDTO = new JobDataDTO();
    }

    @Test
    public void jobDataToJobDataDTO_EmbeddedJobDTODataConversion() {
        jobData.setId(TEST_LONG);

        job.setId(TEST_LONG);

        jobData.setJob(job);

        jobDataDTO = jobDataMapper.jobDataToJobDataDTO(jobData);

        assertThat(jobDataDTO.getId(), is(notNullValue()));
        assertThat(jobDataDTO.getId(), is(instanceOf(Long.class)));
        assertThat(jobDataDTO.getId(), is(TEST_LONG));

        assertThat(jobDataDTO.getJobDTO(), is(notNullValue()));
        assertThat(jobDataDTO.getJobDTO(), is(instanceOf(JobDTO.class)));
        assertThat(jobDataDTO.getJobDTO().getId(), is(TEST_LONG));

    }

    @Test
    public void jobDataDTOToJobData_EmbeddedJobDTODataConversion() {
        jobDataDTO.setId(TEST_LONG);

        jobDTO.setId(TEST_LONG);

        jobDataDTO.setJobDTO(jobDTO);

        jobData = jobDataMapper.jobDataDTOToJobData(jobDataDTO);

        assertThat(jobData.getId(), is(notNullValue()));
        assertThat(jobData.getId(), is(instanceOf(Long.class)));
        assertThat(jobData.getId(), is(TEST_LONG));

        assertThat(jobData.getJob(), is(notNullValue()));
        assertThat(jobData.getJob(), is(instanceOf(JobDTO.class)));
        assertThat(jobData.getJob().getId(), is(TEST_LONG));
    }
}

你检查过你的日志了吗?您应该对未映射的目标属性(jobjobDTO)有一些警告。您需要告诉 MapStruct 如何使用 @Mapping.

映射它们

您的映射器应如下所示:

@Mapper
public interface JobDataMapper {
    JobDataMapper INSTANCE = Mappers.getMapper(JobDataMapper.class);
    JobDataDTO jobDataToJobDataDTO(JobData jobData);
    JobData jobDataDTOToJobData(JobDataDTO jobData);

    @InheritInverseMapping
    JobDTO jobToJobDTO(Job job);

    @Mapping(target = "job", source = "jobDTO")
    Job jobDTOToJob(JobDTO jobDTO);
}

使用 @Mapping(target = "job", source = "jobDTO"),您告诉 MapStruct 它需要将 jobDTO 映射到 job。使用 @InheritInverseMapping 你是说继承所有逆向配置(即 @Mapping(target = "jobDTO", source = "job"))。

您还可以使用 @Mapper(unmappedTargetPolicy = ReportingPolicy.ERROR)

启用 ReportingPolicy#ERROR,如果存在未映射的目标 属性,构建将失败