有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java修复了在具有相同方法类型的@Qualifier上为映射属性错误找到的不明确映射方法

我使用MapStruct 1.3.1得到了“mapping from map”的不明确映射错误。决赛

@Mapper( uses = MappingUtil.class )
public interface SourceTargetMapper {

    SourceTargetMapper MAPPER = Mappers.getMapper( SourceTargetMapper.class );

    @Mapping(source = "map", target = "aProperty", qualifiedBy = A.class )
    @Mapping(source = "map", target = "bProperty", qualifiedBy = B.class )
    Target toTarget(Map<String,Map<String, Object>> map);
}


public class MappingUtil {

  @Qualifier
  @Target(ElementType.METHOD)
  @Retention(RetentionPolicy.CLASS)
  public @interface A {
  }

  @Qualifier
  @Target(ElementType.METHOD)
  @Retention(RetentionPolicy.CLASS)
  public @interface B {
  }

  @A
  public String abc(Map<String,Map<String, Object>> in) {
     return (String) in.get("first_key").get("a_second_key");
  }

  @B
  public String xyz(Map<String,Map<String, Object>> in) {
     return (String) in.get("first_key").get("b_second_key");
  }

}

当我将@A或@B更改为其他类型时,错误消失了

  @B
  public int xyz(Map<String,Map<String, Object>> in) {
     return (int) in.get("first_key").get("b_second_key");
  }

我错过了什么?{a2}使用了相同类型的两个方法,因此这不应该是一个问题

编辑:Mapstruct 4.1.2上的相同问题。决赛


共 (2) 个答案

  1. # 1 楼答案

    限定符的实现不正确。下面是link,它展示了如何在映射不明确的情况下使用限定符实现自定义映射

    下面是如何基于限定符创建自定义映射的简短代码版本:

    @Qualifier
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.CLASS)
    public @interface Translator {
    }
    
    @Qualifier
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.CLASS)
    public @interface A {
    }
    
    @Qualifier
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.CLASS)
    public @interface B {
    }
    
    @Translator
    public class MappingUtil {
        @A
        public String abc(Map<String,Map<String, Object>> in) {
            return (String) in.get("first_key").get("a_second_key");
        }
    
        @B
        public String xyz(Map<String,Map<String, Object>> in) {
            return (String) in.get("first_key").get("b_second_key");
        }
    }
    
    @Mapper( uses = MappingUtil.class )
    public interface SourceTargetMapper {
    
        SourceTargetMapper MAPPER = Mappers.getMapper( SourceTargetMapper.class );
    
        @Mapping(source = "map", target = "aProperty", qualifiedBy = { Translator.class, A.class } )
        @Mapping(source = "map", target = "bProperty", qualifiedBy = { Translator.class, B.class } )
        Target toTarget(Map<String,Map<String, Object>> map);
    }
    

    备选方案:

    如果不想创建单独的实用程序类,可以使用qualifiedByName。下面是它的示例代码:

    @Mapper
    public interface SourceTargetMapper {
    
        SourceTargetMapper MAPPER = Mappers.getMapper( SourceTargetMapper.class );
    
        @Mapping(source = "map", target = "aProperty", qualifiedByName= "abc" )
        @Mapping(source = "map", target = "bProperty", qualifiedByName= "xyz" )
        Target toTarget(Map<String,Map<String, Object>> map);
    
        @Named("abc")
        default String abc(Map<String,Map<String, Object>> in) {
            // return whatever need to return
        }
    
        @Named("xyz")
        default String xyz(Map<String,Map<String, Object>> in) {
            // return whatever need to return
        }
    }
    
  2. # 2 楼答案

    在使用1.4.2时,这似乎是正确的。最终的但是,在1.5.0中。Beta1由于新引入了映射到Bean的映射,这不再有效。我们正在调查如何解决这个问题

    但是,有一种替代解决方案可以使其正常工作:

    @Mapper( uses = MappingUtil.class )
    public interface SourceTargetMapper {
    
        SourceTargetMapper MAPPER = Mappers.getMapper( SourceTargetMapper.class );
    
        @Mapping(source = "first_property", target = "aProperty", qualifiedBy = A.class )
        @Mapping(source = "first_property", target = "bProperty", qualifiedBy = B.class )
        Target toTarget(Map<String,Map<String, Object>> map);
    }
    
    
    public class MappingUtil {
    
      @Qualifier
      @Target(ElementType.METHOD)
      @Retention(RetentionPolicy.CLASS)
      public @interface A {
      }
    
      @Qualifier
      @Target(ElementType.METHOD)
      @Retention(RetentionPolicy.CLASS)
      public @interface B {
      }
    
      @A
      public String abc(Map<String, Object> in) {
         return (String) in.get("a_second_key");
      }
    
      @B
      public String xyz(Map<String, Object> in) {
         return (String) in.get("b_second_key");
      }
    
    }
    

    注意MappingUtil中签名的更改和Mapping#source中的更改