尝试在我的商业模式中使用值对象,我遇到了以下代码的问题:
@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 b"。考虑声明/实现一个映射方法:"test。ValueObjectB map(java.lang.String value(".
我完全理解这一点,但我宁愿不为每个 ValueObject 声明一个方法(一个项目中可能有几十个(。
有没有通用方法来声明(字符串 -> ValueObject(映射方法?
如果所有方法之间没有通用接口,则没有通用方法可以执行此操作。
但是,如果您有一个通用接口,那么这是可能的。例如:
public interface ValueObject<T> {
T getValue();
void setValue(T value);
}
然后你需要一个帮助器映射器:
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);
}
}
}
编辑:添加具有不可变值对象的示例。
如果您希望值对象不可变,则可以执行以下操作:
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 都有一个具有该值的构造函数。