踩坑建议

  • mapstruct 靠自动生成代码,所以mvn clean很重要,有问题时到生成的代码里看看
  • 官方源代码里的帮助 例子比百度有用

    常用注解

    @BeanMapping

    ```java

Configures the mapping between two bean types. Either resultType(), qualifiedBy() or nullValueMappingStrategy() must be specified. Example: Determining the result type // When result types have an inheritance relation, selecting either mapping method Mapping or factory method // BeanMapping can be become ambiguous. Parameter resultType() can be used. public class FruitFactory { public Apple createApple() { return new Apple(); } public Orange createOrange() { return new Orange(); } } @Mapper(uses = FruitFactory.class) public interface FruitMapper { @BeanMapping(resultType = Apple.class) Fruit toFruit(FruitDto fruitDto); }

// generates public class FruitMapperImpl implements FruitMapper { @Override public Fruit toFruit(FruitDto fruitDto) { Apple fruit = fruitFactory.createApple(); // … } }

  1. <a name="TXcLN"></a>
  2. ### @AfterMapping
  3. ```java
  4. Marks a method to be invoked at the end of a generated mapping method, right before the last return statement of the mapping method. The method can be implemented in an abstract mapper class, be declared in a type (class or interface) referenced in Mapper.uses(), or in a type used as @Context parameter in order to be used in a mapping method.
  5. The method invocation is only generated if the return type of the method (if non-void) is assignable to the return type of the mapping method and all parameters can be assigned by the available source, target or context parameters of the mapping method:
  6. A parameter annotated with @MappingTarget is populated with the target instance of the mapping.
  7. A parameter annotated with @TargetType is populated with the target type of the mapping.
  8. Parameters annotated with @Context are populated with the context parameters of the mapping method.
  9. Any other parameter is populated with a source parameter of the mapping.
  10. For non-void methods, the return value of the method invocation is returned as the result of the mapping method if it is not null.
  11. All after-mapping methods that can be applied to a mapping method will be used. @Qualifier / @Named can be used to filter the methods to use.
  12. The order of the method invocation is determined by their location of definition:
  13. Methods declared on @Context parameters, ordered by the parameter order.
  14. Methods implemented in the mapper itself.
  15. Methods from types referenced in Mapper.uses(), in the order of the type declaration in the annotation.
  16. Methods declared in one type are used after methods declared in their super-type
  17. Important: the order of methods declared within one type can not be guaranteed, as it depends on the compiler and the processing environment implementation.
  18. Example:
  19. @AfterMapping
  20. public void calledWithoutArgs() {
  21. // ...
  22. }
  23. @AfterMapping
  24. public void calledWithSourceAndTargetType(SourceEntity anySource, @TargetType Class<?> targetType) {
  25. // ...
  26. }
  27. @AfterMapping
  28. public void calledWithSourceAndTarget(Object anySource, @MappingTarget TargetDto target) {
  29. // ...
  30. }
  31. public abstract TargetDto toTargetDto(SourceEntity source);
  32. // generates:
  33. public TargetDto toTargetDto(SourceEntity source) {
  34. if ( source == null ) {
  35. return null;
  36. }
  37. TargetDto targetDto = new TargetDto();
  38. // actual mapping code
  39. calledWithoutArgs();
  40. calledWithSourceAndTargetType( source, TargetDto.class );
  41. calledWithSourceAndTarget( source, targetDto );
  42. return targetDto;
  43. }
  44. See Also:
  45. BeforeMapping, Context
  46. Author:
  47. Andreas Gudian

@Context // 数据共享

  1. @Mapper(componentModel="spring")
  2. public interface MyMapper {
  3. @Mapping(target="x",ignore = true)
  4. // other mappings
  5. Target map( Source source, @Context MyService service);
  6. @AfterMapping
  7. default void map( @MappingTarget Target.X target, Source.ID source, @Context MyService service) {
  8. target.set( service.findById( source.getId() ) );
  9. }
  10. }

参考

概述

  • DAO 与Service 层都是 返回 DO类型,与数据库表对应
  • controller 层 使用 mapstruct 对 转DO 类型到 VO 类型,分两种
    • DO VO 一一对应,
    • 多个 DO 聚合 转成一个VO
    • 例子 ```java //controller public CommonResult getPermissionInfo() { // 获得用户信息 SysUserDO user = userCoreService.getUser(getLoginUserId()); if (user == null) {
      1. return null;
      } // 获得角色列表 List roleList = roleService.getRolesFromCache(getLoginUserRoleIds()); // 获得菜单列表 List menuList = permissionService.getRoleMenusFromCache(
      1. getLoginUserRoleIds(), // 注意,基于登录的角色,因为后续的权限判断也是基于它
      2. SetUtils.asSet(MenuTypeEnum.DIR.getType(), MenuTypeEnum.MENU.getType(), MenuTypeEnum.BUTTON.getType()),
      3. SetUtils.asSet(CommonStatusEnum.ENABLE.getStatus()));
      // 拼接结果返回 return success(SysAuthConvert.INSTANCE.convert(user, roleList, menuList)); }

// convert

//… default SysAuthPermissionInfoRespVO convert(SysUserDO user, List roleList, List menuList) { return SysAuthPermissionInfoRespVO.builder() .user(SysAuthPermissionInfoRespVO.UserVO.builder().nickname(user.getNickname()).avatar(user.getAvatar()).build()) .roles(CollectionUtils.convertSet(roleList, SysRoleDO::getCode)) .permissions(CollectionUtils.convertSet(menuList, SysMenuDO::getPermission)) .build(); } //…

  1. <a name="WIJtn"></a>
  2. ### 使用@aftermapping进行MapStruct批量转换
  3. ```java
  4. public abstract CatUI convert(Cat cat);
  5. public abstract List<CatUI> convert(List<Cat> cats);
  6. @AfterMapping
  7. public void populateCatName(Cat cat, @MappingTarget CatUI catUI) {
  8. String name = _someRemoteService.getCatName(catUI.getId());
  9. catUI.setName(name);
  10. }
  11. @AfterMapping
  12. public void populateCatNames(List<Cat> cats, @MappingTarget List<CatUI> catUIs) {
  13. Map<Integer,String> idToNameMap = _someRemoteService.getCatNames(catUIs.stream().map((c) -> c.getId() ).collect(Collectors.toList());
  14. catUIs.forEach((c) -> c.setName(idToNameMap(c.getId())));
  15. }