You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Orika在父对象映射时为嵌套对象使用ObjectFactory?

解决MapStruct映射父对象时替换子对象为新实例的问题

我来帮你搞定这个MapStruct的困扰!首先得先搞清楚为什么你原来的代码不生效:

@Override public void mapBtoA(FooDto b, Foo a, MappingContext context) { a = new Foo(); a.setId(b.getId()); }

这段代码里,a = new Foo()只是重新给方法参数的局部引用赋值了,而Java是值传递,这个改变不会影响父对象里原来持有的Foo引用,所以父对象的子对象还是原来的那个,不会被替换。

下面给你几种可行的解决方案,你可以根据自己的场景选择:

方案一:使用ObjectFactory创建新实例

ObjectFactory是MapStruct用来创建目标对象实例的扩展点,我们可以用它来强制每次都生成新的Foo对象:

  1. 先定义一个ObjectFactory实现类:
public class FooObjectFactory implements ObjectFactory<Foo> {
    @Override
    public Foo create(Class<Foo> type) {
        // 每次调用都返回新的Foo实例
        return new Foo();
    }
}
  1. 在你的Mapper接口里指定这个ObjectFactory,同时定义子对象的映射方法:
@Mapper(objectFactory = FooObjectFactory.class)
public interface ParentMapper {
    // 父对象的映射方法,MapStruct会自动处理子对象的创建和映射
    Parent parentDtoToParent(ParentDto parentDto);

    // 子对象的映射方法,MapStruct会用我们的ObjectFactory创建新Foo实例,再填充属性
    Foo fooDtoToFoo(FooDto fooDto);
}

这样当映射父对象时,MapStruct会调用fooDtoToFoo方法,而这个方法会通过我们的ObjectFactory生成新的Foo实例,最终父对象里的子对象会被替换成这个新实例。

方案二:使用@Mapping的expression直接创建新实例

如果不想额外写ObjectFactory,也可以在父对象的映射方法里,通过expression直接指定创建新的Foo对象,再结合属性更新:

@Mapper
public interface ParentMapper {
    // 先创建新的Foo实例,再调用update方法填充属性
    @Mapping(target = "foo", expression = "java(new Foo())")
    Parent parentDtoToParent(ParentDto parentDto);

    // 这个方法用来给已有的Foo实例填充属性(这里就是我们刚创建的新实例)
    void updateFooFromDto(FooDto fooDto, @MappingTarget Foo foo);
}

这种方式更直接,不需要额外的工厂类,适合简单场景。

方案三:自定义Converter强制返回新实例

我们可以创建一个FooDto到Foo的Converter,确保每次转换都返回新实例:

  1. 实现Converter接口:
@Converter
public class FooDtoConverter implements Converter<FooDto, Foo> {
    @Override
    public Foo convert(FooDto source) {
        Foo newFoo = new Foo();
        newFoo.setId(source.getId());
        // 手动映射其他需要的属性
        return newFoo;
    }
}
  1. 在Mapper里引入这个Converter:
@Mapper(uses = FooDtoConverter.class)
public interface ParentMapper {
    Parent parentDtoToParent(ParentDto parentDto);
}

当MapStruct映射父对象的foo属性时,会调用这个Converter,自动用新创建的Foo实例替换原来的子对象。

总结

核心思路就是:不要试图在自定义映射方法里重新赋值方法参数的引用(这在Java里不会影响外部对象),而是让MapStruct通过ObjectFactory、Converter或者expression来负责创建新的子对象实例,这样就能实现父对象映射时替换子对象为新引用的需求。

内容的提问来源于stack exchange,提问作者Guerric P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:35:22