【问题标题】:Mapstruct Kotlin Gradle - Interface Implementation are not completeMapstruct Kotlin Gradle - 接口实现不完整
【发布时间】:2021-09-23 02:34:44
【问题描述】:

-实体定义

@entity
data class Customer(
@id @GeneratedValue
var id: UUID? = null,
@column(columnDefinition = "text")
val name: String,
@column(columnDefinition = "text")
val phoneNo: String,
val dateOfBirth: LocalDate,
val customerSince: LocalDate,
@column(columnDefinition = "timestamp default current timestamp")
val lastUpdatedAt: LocalDateTime,
@OnetoOne
val address: Address,
@OnetoOne
val paymentInfo: PaymentInfo
)

-映射定义

@Mapper(unmappedTargetPolicy = ReportingPolicy.IGNORE)
interface CustomerMapper {
@mapping(source = "id", target = "customerId")
fun toCustomerDto(customer: Customer): CustomerDto

@InheritInverseConfiguration
fun toCustomer(customerDto: CustomerDto): Customer
}

-生成代码

@generated(
value = "org.mapstruct.ap.MappingProcessor",
date = "2021-07-13T21:56:38-0600",
comments = "version: 1.4.2.Final, compiler: IncrementalProcessingEnvironment from kotlin-annotation-processing-gradle-1.5.20.jar, environment: Java 11.0.10 (Oracle Corporation)"
)
@component
public class CustomerMapperImpl implements CustomerMapper {

@Override
public CustomerDto toCustomerDto(Customer customer) {
    if ( customer == null ) {
        return null;
    }

    UUID customerId = null;
    String name = null;
    String phoneNo = null;
    LocalDate dateOfBirth = null;
    LocalDate customerSince = null;
    LocalDateTime lastUpdatedAt = null;
    AddressDto address = null;
    PaymentInfoDto paymentInfo = null;

    customerId = customer.getId();
    name = customer.getName();
    phoneNo = customer.getPhoneNo();
    dateOfBirth = customer.getDateOfBirth();
    customerSince = customer.getCustomerSince();
    lastUpdatedAt = customer.getLastUpdatedAt();
    address = addressToAddressDto( customer.getAddress() );
    paymentInfo = paymentInfoToPaymentInfoDto( customer.getPaymentInfo() );

    CustomerDto customerDto = new CustomerDto( customerId, name, phoneNo, dateOfBirth, customerSince, lastUpdatedAt, address, paymentInfo );

    return customerDto;
}

@Override
public Customer toCustomer(CustomerDto customerDto) {
    if ( customerDto == null ) {
        return null;
    }

    Customer customer = new Customer();

    customer.setId( customerDto.getCustomerId() );

    return customer;
}

protected AddressDto addressToAddressDto(Address address) {
    if ( address == null ) {
        return null;
    }

    int streetNo = 0;
    String streetName = null;
    String city = null;
    String state = null;
    int zip = 0;

    streetNo = address.getStreetNo();
    streetName = address.getStreetName();
    city = address.getCity();
    state = address.getState();
    zip = address.getZip();

    AddressDto addressDto = new AddressDto( streetNo, streetName, city, state, zip );

    return addressDto;
}

protected PaymentInfoDto paymentInfoToPaymentInfoDto(PaymentInfo paymentInfo) {
    if ( paymentInfo == null ) {
        return null;
    }

    String creditCard = null;
    int expiryMonth = 0;
    int expiryYear = 0;
    int cvv = 0;

    creditCard = paymentInfo.getCreditCard();
    expiryMonth = paymentInfo.getExpiryMonth();
    expiryYear = paymentInfo.getExpiryYear();
    cvv = paymentInfo.getCvv();

    PaymentInfoDto paymentInfoDto = new PaymentInfoDto( creditCard, expiryMonth, expiryYear, cvv );

    return paymentInfoDto;
}
}

-Gradle 构建脚本 导入 org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
id("org.springframework.boot") version "2.5.2"
id("io.spring.dependency-management") version "1.0.11.RELEASE"
kotlin("jvm") version "1.5.20"
kotlin("plugin.spring") version "1.5.20"
kotlin("kapt") version "1.5.20"
kotlin("plugin.jpa") version "1.5.20"
}

group = "com.example"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_11

repositories {
mavenCentral()
}

dependencies {
implementation("org.springframework.boot:spring-boot-starter")
implementation("org.jetbrains.kotlin:kotlin-reflect")
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("org.mapstruct:mapstruct:1.4.2.Final")
kapt("org.mapstruct:mapstruct-processor:1.4.2.Final")
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
implementation("org.springframework.boot:spring-boot-starter-data-jpa")
runtimeOnly("org.postgresql:postgresql")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}

tasks.withType {
kotlinOptions {
freeCompilerArgs = listOf("-Xjsr305=strict")
jvmTarget = "11"
}
}

tasks.withType {
useJUnitPlatform()
}

kapt {
arguments {

arg("mapstruct.defaultComponentModel", "spring")
}
}

-问题: 尽管 Mapstruct 正在为 toCustomer 函数生成代码,但由于除了 id 字段之外未设置 Customer 的属性,因此实现被破坏。需要做什么才能正确实现所有接口。在 Kotlin 和 Gradle 的 mapstruct 上存在一个相关问题,即结果不一致,有时会生成代码,有时不会,我也遇到过 https://github.com/mapstruct/mapstruct/issues/2499

【问题讨论】:

    标签: kotlin mapstruct gradle-kotlin-dsl


    【解决方案1】:

    这里的问题与 Gradle 无关,与 Kotlin 数据类的定义方式有关。

    我不是 Kotlin 专家。

    但是,当您在 Data 类中使用 val 时,Kotlin 将生成许多构造函数,包括默认的空构造函数。由于我们目前在注解处理过程中无法轻易检测一个类是否是 Kotlin 数据类,因此 MapStruct 选择了错误的构造函数来执行映射。

    已经报告了一个问题,可以找到here

    【讨论】:

    • 目前是否有任何变通方法/黑客可以解决此问题?我还没有看到这个问题的优先级。
    • 如果您可以在其中一个构造函数上强制添加注释,那么使用任何包中的@Default 对其进行注释应该可以工作
    • @SarangKanabargi 您是否设法找到解决方案? @Filip,在构造函数上使用 @Default 注释在 Kotlin v1.5+ 之前工作,但它不再工作了
    猜你喜欢
    • 2013-06-15
    • 1970-01-01
    • 2020-10-17
    • 2021-01-29
    • 2019-10-03
    • 2018-06-25
    • 1970-01-01
    • 2022-11-07
    • 2018-01-29
    相关资源
    最近更新 更多