Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ionic-framework/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 值对象与mapstruct的通用映射_Java_Mapstruct_Value Objects - Fatal编程技术网

Java 值对象与mapstruct的通用映射

Java 值对象与mapstruct的通用映射,java,mapstruct,value-objects,Java,Mapstruct,Value Objects,尝试在我的业务模型中使用价值对象时,我遇到了以下代码的问题: @Mapper public abstract class TestMapstruct { public ValueObjectA mapA(String value){ return new ValueObjectA(value); } public abstract BusinessObject map(DTO dto); @Value public static cl

尝试在我的业务模型中使用价值对象时,我遇到了以下代码的问题:

@Mapper
public abstract class TestMapstruct {

    public ValueObjectA mapA(String value){
        return new ValueObjectA(value);
    }

    public abstract BusinessObject map(DTO dto);

    @Value
    public static class ValueObjectA {
        private String a;
    }

    @Value
    public static class ValueObjectB {
        private String b;
    }

    @Data
    public static class BusinessObject {
        private ValueObjectA a;
        private ValueObjectB b;
    }

    @Data
    public static class DTO {
        private String a;
        private String b;
    }
}
缺少映射(字符串->ValueObjectB)将导致以下编译错误消息:

无法将属性“java.lang.String b”映射到“test.ValueObjectB”。考虑声明/实现一个映射方法:“Test.ValueObjestBMAP(JavaLang.Stand value)”.< 我完全理解这一点,但我不想为我的每个ValueObject(在一个项目中可能有几十个)声明一个方法


是否有一种通用方法来声明(String->ValueObject)映射方法?

如果所有方法之间没有通用接口,则没有通用方法来声明

但是,如果您有一个公共接口,那么它是可能的。例如:

public interface ValueObject<T> {

    T getValue();

    void setValue(T value);

}
公共接口ValueObject{
T getValue();
无效设定值(T值);
}
然后您需要一个助手映射器:

public interface ValueObjectMapper {


    static <V extends ValueObject<T>, T> T mapToValue(V valueObject) {
        return valueObject == null ? null : valueObject.getValue();
    }

    static <V extends ValueObject<T>, T> V mapFromValueObject(T value, @TargetType Class<V> valueObjectClass) {
        if (value == null) {
            return null;
        }


        try {
            V valueObject = valueObjectClass.getDeclaredConstructor().newInstance();
            valueObject.setValue(value);

            return valueObject;
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

}
公共接口ValueObjectMapper{
静态T映射值(V valueObject){
返回valueObject==null?null:valueObject.getValue();
}
静态V mapFromValueObject(T值,@TargetType类valueObjectClass){
如果(值==null){
返回null;
}
试一试{
V valueObject=valueObjectClass.getDeclaredConstructor().newInstance();
valueObject.setValue(值);
返回值对象;
}catch(实例化异常|非法访问异常|调用目标异常|无此方法异常){
抛出新的运行时异常(e);
}
}
}
编辑:添加具有不可变值对象的示例

如果希望值对象不可变,则可以执行以下操作:

public interface ValueObject<T> {
    T getValue();
}


public interface ValueObjectMapper {


    static <V extends ValueObject<T>, T> T mapToValue(V valueObject) {
        return valueObject == null ? null : valueObject.getValue();
    }

    static <V extends ValueObject<T>, T> V mapFromValueObject(T value, @TargetType Class<V> valueObjectClass) {
        if (value == null) {
            return null;
        }


        try {
            V valueObject = valueObjectClass.getDeclaredConstructor(value.getClass()).newInstance(value);

            return valueObject;
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }

}
公共接口ValueObject{
T getValue();
}
公共接口ValueObjectMapper{
静态T映射值(V valueObject){
返回valueObject==null?null:valueObject.getValue();
}
静态V mapFromValueObject(T值,@TargetType类valueObjectClass){
如果(值==null){
返回null;
}
试一试{
V valueObject=valueObjectClass.getDeclaredConstructor(value.getClass()).newInstance(value);
返回值对象;
}catch(实例化异常|非法访问异常|调用目标异常|无此方法异常){
抛出新的运行时异常(e);
}
}
}

注意:要做到这一点,您必须确保所有ValueObjects都有一个具有该值的构造函数。

我不希望在我的ValueObjects中声明setter和使用参数化构造函数,但它工作起来很有魅力。注意:由于反射操作,缺少抛出声明。您还可以使其与不可变的ValueObject一起工作。我更新了我的答案,也有了这个。我还通过重新抛出
RuntimeException
添加了异常处理功能,效果非常好,我注意到Mapstruct能够处理MappingMethod抛出异常(catch+rethrow RuntimeException),是的,我们可以处理。它还可以很好地处理抛出的异常(如果您在接口上定义它们:)