- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我们正在使用 immutables framework生成所有 DTO。现在我们想用 mapstruct 将这些对象映射到另一个对象。 .但生成的 DTO 是不可变的,没有 setter 也没有构造函数,对应于构建器模式。它们仅通过静态 builder()
方法访问的相应构建器来填充。
我们改为尝试将 DTO1 映射到 DTO2.Builder,如果 mapstruct 能够识别 Builder 中的 setter,这将起作用,但它们没有 void 返回类型,而是返回 Builder 本身以进行流畅的连接。
下面是示例代码。
我们有两个接口(interface)
@Value.Immutable
public interface MammalDto {
public Integer getNumberOfLegs();
public Long getNumberOfStomachs();
}
和
@Value.Immutable
public interface MammalEntity {
public Long getNumberOfLegs();
public Long getNumberOfStomachs();
}
然后我们有 mapstruct 的 Mapper 接口(interface):
@Mapper(uses = ObjectFactory.class)
public interface SourceTargetMapper {
SourceTargetMapper MAPPER = Mappers.getMapper( SourceTargetMapper.class );
ImmutableMammalEntity.Builder toTarget(MammalDto source);
}
为了让 mapstruct 找到 Builder,我们需要一个工厂:
public class ObjectFactory {
public ImmutableMammalDto.Builder createMammalDto() {
return ImmutableMammalDto.builder();
}
public ImmutableMammalEntity.Builder createMammalEntity() {
return ImmutableMammalEntity.builder();
}
}
为了生成代码,指示编译器插件使用两个注解处理器:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.6.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<annotationProcessorPaths>
<path>
<groupId>org.immutables</groupId>
<artifactId>value</artifactId>
<version>2.2.8</version>
</path>
<path>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.2.0.Beta3</version>
</path>
</annotationProcessorPaths>
</configuration>
</plugin>
注意:这仅适用于 mapstruct 版本 > 1.2.x。旧版本在干净构建(mvn clean compile
)中存在问题,它们找不到刚刚构建的不可变源。在第二个构建(没有清理)中,他们会找到不可变的实现,因为它们在注释处理器运行之前就在类路径上。此错误现已修复。
这就像一个魅力。首先生成接口(interface)的不可变实现,mapstruct 使用它们生成构建器。
但是测试显示没有设置任何属性:
@Test
public void test() {
MammalDto s = ImmutableMammalDto.builder().numberOfLegs(4).numberOfStomachs(3l).build();
MammalEntity t = SourceTargetMapper.MAPPER.toTarget(s).build();
assertThat(t.getNumberOfLegs()).isEqualTo(4);
assertThat(t.getNumberOfStomachs()).isEqualTo(3);
}
断言失败。一看 mapstruct 生成的映射器,它显然没有找到任何 setter:
@Generated(
value = "org.mapstruct.ap.MappingProcessor",
//...
)
public class SourceTargetMapperImpl implements SourceTargetMapper {
private final ObjectFactory objectFactory = new ObjectFactory();
@Override
public Builder toTarget(MammalDto source) {
if ( source == null ) {
return null;
}
Builder builder = objectFactory.createMammalEntity();
return builder;
}
}
返回空构建器。我认为原因是生成的构建器的 setter 实现,因为它返回自身以创建流畅的 API:
public final Builder numberOfLegs(Long numberOfLegs) {
this.numberOfLegs = Objects.requireNonNull(numberOfLegs, "numberOfLegs");
return this;
}
有没有办法让mapstruct找到这些setter?或者更好的方法来处理此类与构建器不可变的对象?
编辑:正如我在评论中所说,我遇到了 Issue #782 .在版本 1.2.0.Beta3 中仍然不支持构建器。但是有几个关于这个主题的讨论,所以如果有人有同样的问题,关注这个问题可能会很有趣。
最佳答案
您可以配置 Immutables 以在构建器中生成 setter:
@Value.Immutable
@Value.Style(init = "set*")
public interface MammalEntity {
public Long getNumberOfLegs();
public Long getNumberOfStomachs();
}
而且不需要ObjectBuilder,可以直接使用生成的Immutable类
@Mapper(uses = ImmutableMammalEntity.class)
public interface SourceTargetMapper {
SourceTargetMapper MAPPER = Mappers.getMapper( SourceTargetMapper.class );
ImmutableMammalEntity.Builder toTarget(MammalDto source);
}
您甚至可以在自己的注解中定义这些设置
@Value.Style(init = "set*")
public @interface SharedData {}
然后改用它
@SharedData
@Value.Immutable
public interface MammalEntity {
public Long getNumberOfLegs();
public Long getNumberOfStomachs();
}
关于java - 在 mapstruct 中使用构建器(使用不可变注释处理器)将对象映射到不可变对象(immutable对象),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38770813/
为什么禁用类型像 type t = A of int | B of string * mutable int 虽然允许此类类型: type t = A of int | B of string * i
我正在寻找一种类似结构的数据结构,我可以从中创建多个实例并具有某种类型提示而不是不可变的。 所以我有这样的东西: class ConnectionConfig(NamedTuple): nam
我需要转到引用的结构: class SearchKnot { var isWord : Bool = false var text : String = "" var to
如sec 10.4.3中所述 当控制进入执行时,执行以下步骤 功能对象F(调用者)中包含的功能代码的上下文 提供thisArg,而调用方提供argumentsList: 如
i make a game that start display Activity indicator And activity indicator bottom display UiLable wi
编辑:我在这里不断获得支持。只是为了记录,我认为这不再重要。自从我发布它以来我就不再需要它了。 我想在 Scala 中执行以下操作... def save(srcPath: String, destP
使用可变对象作为 Hashmap 键是一种不好的做法吗?当您尝试使用已修改足以更改其哈希码的键从 HashMap 中检索值时,会发生什么? 例如,给定 class Key { int a; /
如果您在Kotlin中访问List类型的Java值,则将获得(Mutable)List!类型。 例如。: Java代码: public class Example { public stati
我编写了 str 类(内置)的以下扩展,以便执行以下操作:假设我有字符串 "Ciao" ,通过做"Ciao" - "a"我想要的结果是字符串 "Cio" 。这是执行此操作的代码,并且运行良好: cla
使用可变对象作为 Hashmap 键是一种不好的做法吗?当您尝试使用已修改足以更改其哈希码的键从 HashMap 中检索值时,会发生什么? 例如,给定 class Key { int a; /
我正在为我的公司设计一个数据库来管理商业贷款。每笔贷款都可以有担保人,可以是个人或公司,在借款业务失败时作为财务支持。 我有 3 个表:Loan、Person 和 Company,它们存储明显的信息。
我使用二进制序列化从 C# 类中保存 F# 记录。一切正常: F#: type GameState = { LevelStatus : LevelStatus
import javax.swing.JOptionPane; public class HW { public static void main(String[] args) { Strin
使用 flatbuffer mutable 有多少性能损失? 是否“正确”使用 FlatBuffers 来拥有一个应该可编辑的对象/结构(即游戏状态) 在我的示例中,我现在有以下类: class Ga
std::function create_function (args...) { int x = initial_value (args...); return [x] () mut
我需要在 for 循环中找到用户输入的字符。我通常会这样做 如果(句子[i] == 'e') 但是因为在这里,'e' 将是一个单字母字符变量,我不知道如何获取要比较的值。我不能只输入 if (sent
我有一个这样的算法: let seed: Foo = ... let mut stack: Vec = Vec::new(); stack.push(&seed); while let Some(ne
这个问题可能看起来非常基础,但我很难弄清楚如何做。我有一个整数,我需要使用 for 循环来循环整数次。 首先,我尝试了—— fn main() { let number = 10; // An
如果我有以下结构: struct MyStruct { tuple: (i32, i32) }; 以及以下函数: // This will not compile fn function(&mut s
我希望在每个 session 的基础上指定列的默认值。下面的脚本不起作用,但描述了我想如何使用它。我目前使用的是 MySQL 5.5.28,但如果需要可以升级。 CREATE TABLE my_tbl
我是一名优秀的程序员,十分优秀!