当前位置: 首页 > 知识库问答 >
问题:

有没有办法在Mapstruct映射器中为单个字段指定自定义getter?

淳于泓
2023-03-14

我试图找到一个更好的解决方案,以防止Hibernate代理初始化时,通过MapSTRt将实体映射到响应DTO。

我一直在将我们的代码库转换为使用ModelMapper中的MapStruct。如果我想用ModelMapper完成我的要求,我可以做如下简单的事情:

    modelMapper
        .createTypeMap(Entity.class, DTO.class)
        .addMapping(Entity::customGetterMethod, Category::setNormalSetterHere);

自定义getter方法允许我检查是否已经从数据库中获取了字段,以避免N 1次初始化。

它看起来像:

 public Set<Entity> customGetterMethod() {
    return Hibernate.isInitialized(this.entities) ? this.entities : null;
  }

我不能简单地覆盖普通的getter,因为在使用我们希望允许延迟初始化的实体时存在合理的情况。

我已经尝试覆盖默认命名策略以使用我自己的自定义getter命名,但是由于我仍然需要访问大多数基本字段的普通getter,我无法让它可靠地使用我的自定义getter并在默认getter存在时忽略它(即使我可以,它看起来仍然是一个混乱的解决方案,并且很难让队友跟上速度)。

到目前为止,解决方案是使用表达式,只需复制和修改生成的这些字段的映射代码:

  @Mapping(
      target = "entities",
      expression = "java( mapEntities( source.customGetterMethod(), context ) )")
  public abstract ResponseDto toDto(Entity source, @Context CycleAvoidingContext context);

   protected Set<ResponseDto> mapEntities(Set<Entity> set, CycleAvoidingContext context) {
       /* a copy of the auto-generated code for this mapping essentially */
  }

对于我们项目中的所有实体和关系,这很难持续,因为我必须为每个字段添加带有表达式字符串的注释映射以及自定义(不是自定义,只是复制)映射逻辑。从可运维性和留档的角度来看,它增加了很多复杂性。

我希望有人能告诉我其他一些mapstruct功能,以便以更精简的方式为特定字段使用自定义getter。

共有1个答案

徐焱
2023-03-14

你有两个选择,你现在可以使用这个,一个选择,你可以在未来使用。

使用bean风格的方法编写一个自定义getter。例如

public Set<Entity> getCustomEntities() {
    return Hibernate.isInitialized(this.entities) ? this.entities : null;
}

然后在映射中需要使用

@Mapping(target = "entities", source = "customEntities")

MapSTRt具有存在检查的概念。这允许您编写一个自定义布尔方法,MapSTRt将使用该方法来检查属性是否存在。

例如

public boolean hasEntities() {
    return Hibernate.isInitialized(this.entities);
}

从1.5开始,MapStruct将提供一种定制(bean外)条件(状态检查)方法。

例如

public MapStructHibernateUtils {


    @Condition
    public static <T> boolean isInitialized(Collection<T> collection) {
        return Hibernate.isInitialized(collection);
    }

}

然后在你的映射器中,你会做

@Mapper(uses = MapStructHibernateUtils.class)
public interface CustomMapper {


    ResponseDto toDto(Entity source, @Context CycleAvoidingContext context);

}

无需添加@Mapping,因为MapStruct将对getEntities()返回的集合调用isInitialized

 类似资料:
  • 我有一个自定义映射函数,它将映射到,但我只想在一个特殊情况下应用它。但是,它适用于所有int类型的源字段,而不仅仅是用注释的源字段。 源类: 目标类别: 映射器: 我想要实现的目标: 但是,生成的代码会执行以下操作: 删除表达式并进行时,映射结构对这两个值都使用。我尝试了地图结构以及。这两个类都使用龙目岛,但是,这在过去并不是一个问题。 这种行为是预期的吗?如果是的话,我还能怎么做?

  • 例如,我有以下接口映射器: 在代码中,您可以看到映射和一些默认方法,其中包含其他映射。如何在Mapstruct映射中使用这些方法,以便Mapstruct使用这些方法在字段中填充值?

  • 以下是我的上下文:我使用byteBuddy动态生成一个类,该类根据外部配置将一个对象转换为另一个对象。我遇到了一些问题,我想找到一个替代方案,这就是我发现MapStruct的方式。 因此,我试图构建简单的映射器,我想知道是否有可能自定义注释以添加转换函数。例如,我想要: 在mapper实现中,我会有如下内容: 如果有人能帮我做到这一点,我将不胜感激,这将节省我很多时间。 提前谢谢。

  • 我有一个映射定义为 其中定义如下: 反向映射是使用处理的。如何为反向映射指定自定义映射?

  • 这是我的例子。 我希望toDto方法使用toDto将Employee映射到EmployeeDto,但mapstruct会生成employeeDtoToEmployeeDto方法。我该怎么修? 谢谢

  • 我正在尝试按如下方式对Mapstruct嵌套映射器进行单元测试: 我正在尝试测试EventMapper: 但它在以下方面不断失败: 创建名为“eventMapper”的bean时出错:bean的实例化失败;嵌套的异常是org。springframework。豆。BeanInstationException:未能实例化[com.mycompany.cna.projects.fishmarket.ba