MapStruct的基本使用及注意事项

MapStruct简介:

  • mapstruct是一种 实体类 映射框架,能够通过Java注解将一个实体类的属性安全地赋值给另一个实体类。有了mapstruct,只需要定义一个映射器接口,声明需要映射的方法,在编译过程中,mapstruct会自动生成该接口的实现类,实现将源对象映射到目标对象的效果。总结来说就是能将一个实体类的各种值安全的赋给另一个实体类,在开发中,使用它可以省去很多不需要的代码!
下面给出阿里巴巴java开发规范里对POJO的相关定义:
1. POJO Plain Ordinary Java Object ): 在本规约中,POJO 专指只有 setter/getter/toString 的 简单类,包括 DO/DTO/BO/VO 等。
2. DO Data Object ):阿里巴巴专指数据库表一一对应的 POJO 类。此对象与数据库表结构一 一对应,通过 DAO 层向上传输数据源对象。
3. DTO Data Transfer Object ):数据传输对象,Service 或 Manager 向外传输的对象。
4. BO Business Object ):业务对象,可以由 Service 层输出的封装业务逻辑的对象。
5. Query :数据查询对象,各层接收上层的查询请求。注意超过 2 个参数的查询封装,禁止使用 Map 类来传输。
6. VO View Object ):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。
7. AO Application Object ): 阿里巴巴专指 Application Object,即在 Service 层上,极为贴近 业务的复用代码。

      相信真正有过按照一定开发规范开发项目的人对这些一定不陌生,我们需要进行繁琐的实体类的转换,而MapStruct的左右就是简化这一操作的,省去重复的无用代码。 

MapStruct使用:

  接下来用一个小示例来说明MapStruct基本的使用:

1.导入依赖:

这里我把lombok的依赖也写出来,就是给大家避免踩坑,因为mapstruct会跟lombok产生版本冲突甚至致使项目无法正常运行,建议大家直接采用示例代码进行操作。

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-jdk8</artifactId>
            <version>1.2.0.Final</version>
        </dependency>
        <dependency>
            <groupId>org.mapstruct</groupId>
            <artifactId>mapstruct-processor</artifactId>
            <version>1.2.0.Final</version>
        </dependency>
2.编写相关POJO
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Brand {

    @TableId(type = IdType.AUTO)
    private long id;
    private String brandName;
    private String companyName;
    private long ordered;
    private String description;
    private long status;

}

编写DTO

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BrandDTO {

    private String brandName;
    private String companyName;
    private String description;
    private long status;
}

编写VO

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BrandVO {
    private String brandName;
    private String companyName;
    private String description;
    private String status;
}
 3.编写转换接口

 请注意!!!这里的@Mapper和@Mappings、@Named注解都是org.mapstruct包下的。

@Mapping注解可以映射不同字段,其中source设置待转换的字段名,target设置转换的目标字段名。

@Named注解可以设置不同类型对象的具体转换规则,例如这里在DTO中获取的是long类型,而VO显示为字符串类型,这里就是用了@Named注解绑定方法进行转换,搭配@Mapping注解中的qulifiedByName属性使用,就可以完成转换规则设置了。

可以直接设置对应集合类型的转换,MapStruct会同时调用单类型的转换方法完成转换(强中强)!

@Mapper
public interface BrandConvert {

    BrandConvert mapper = Mappers.getMapper(BrandConvert.class);

    @Mappings({
            @Mapping(source = "brandName",target = "brandName"),
            @Mapping(source = "companyName",target = "companyName"),
            @Mapping(source = "description",target = "description"),
            @Mapping(source = "status",target = "status",qualifiedByName = "convertstatus")
    })
    BrandVO dto2vo(BrandDTO brandDTO);

    @Mappings({
            @Mapping(source = "brandName",target = "brandName"),
            @Mapping(source = "companyName",target = "companyName"),
            @Mapping(source = "description",target = "description"),
            @Mapping(source = "status",target = "status")
    })
    BrandDTO entity2dto(Brand brand);

    List<BrandVO> list2vo(List<BrandDTO> list);

    List<BrandDTO> list2dto(List<Brand> list);

    @Named("convertstatus")
    default String convertStatus(long status){
        if (status==1)
            return BrandStatusEnum.SAFE.getDescription();
        else return BrandStatusEnum.IN_DANGER.getDescription();
    }
}
 4.Service实现类:
@Slf4j
@Service
public class BrandServiceImpl extends ServiceImpl<BrandMapper, Brand> implements BrandService {
    @Override
    public BrandDTO getBrandById(Integer id) {
        QueryWrapper<Brand> wrapper = new QueryWrapper<>();
        wrapper.eq("id", id);
        Brand brand = getOne(wrapper);
        BrandDTO brandDTO = BrandConvert.mapper.entity2dto(brand);
        log.info("查询了id为" + id + "的商标信息:商标为" + brandDTO.getBrandName() + "所属公司为" + brandDTO.getCompanyName());
        return brandDTO;
    }

    @Override
    public List<BrandDTO> getAllBrands() {
        List<Brand> brands = list();
        List<BrandDTO> brandDTOS = BrandConvert.mapper.list2dto(brands);
        log.info("查询了当前全商标的信息");
        return brandDTOS;
    }
}
5.Controller:
@CrossOrigin
@RestController
@RequestMapping("/brand")
public class BrandQueryController {
    @Autowired
    private BrandService brandService;

    @GetMapping("/getbyid")
    public BrandVO getBrandByID(@RequestParam("id")int id){
        BrandDTO brandById = brandService.getBrandById(id);
        return BrandConvert.mapper.dto2vo(brandById);
    }

    @GetMapping("/getallbrands")
    public List<BrandVO> getAllBrands(){
        List<BrandDTO> allBrands = brandService.getAllBrands();
        ArrayList<BrandVO> brandVOS = new ArrayList<>();
        return BrandConvert.mapper.list2vo(allBrands);
    }


}
6.代码运行测试:

我这里是直接IDEA的插件测试的接口,是可以正常运行并且直接转换成功的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在使用struct时,需要注意以下几点: 1. 定义在函数内部的结构体只在该函数内部有效,对外不可见。 2. 结构体内部的成员可以是任何数据类型,包括基本数据类型、结构体、指针等。 3. 结构体成员的访问方式有两种:使用“.”操作符或使用“->”操作符(当成员是指针类型时)。 4. 结构体可以进行初始化,可以使用“{}”进行初始化,也可以使用“=”进行初始化。 5. 结构体可以作为函数的参数或返回值。 6. 结构体可以嵌套定义,即在结构体的成员中定义另一个结构体。 7. 结构体可以使用typedef进行重命名,方便使用。 8. 在使用结构体时,需要注意结构体内存对齐的问题,避免出现内存浪费或程序崩溃等问题。 总之,在使用struct时需要了解其特点和使用方法,才能更好地发挥其作用。 ### 回答2: struct是一种用于定义自定义数据类型的关键字。在使用struct时,有一些注意事项需要注意。 首先,struct定义的数据类型是用户自定义的,因此在命名时应该遵循一定的命名规范,以便于其他人理解。通常,使用大驼峰命名法,将每个单词的首字母大写,并且不使用下划线。 其次,struct定义的数据类型可以包含多个成员变量,每个成员变量可以有不同的数据类型。在使用struct时,我们可以通过"."来访问结构体中的成员变量,但是需要注意成员变量的访问权限,私有成员变量需要通过get/set方法进行访问。 另外,struct定义的数据类型需要在使用之前进行声明。因此,如果需要在struct中引用自身类型,可以使用指针或者使用typedef来解决。 此外,struct还可以包含函数指针,用于实现面向对象的功能。通过将函数指针作为成员变量,可以将一组相关的操作组织在一起,并且可以根据实际需要动态指定具体的操作函数。 最后,struct定义的数据类型可以通过多种方式使用,可以作为函数参数、返回值、变量等进行传递和使用。由于struct占用的内存空间比较大,如果需要在函数内部使用struct变量,可以考虑使用指针传递,以减少内存开销。 总之,使用struct时,需要注意命名规范、成员变量的访问权限、类型声明的顺序、函数指针的使用以及内存开销的问题。只有正确地使用和理解struct,才能发挥其强大的功能和灵活性。 ### 回答3: 使用struct时需要注意以下几点: 1. 结构体的成员应该按照自然对齐原则进行排列,即成员的起始地址应该是其大小的整数倍。 2. 结构体的大小应该是其成员大小的倍数,并且大多数编译器会在结构体的末尾添加一些填充字节以满足对齐要求。 3. 可以使用#pragma pack(n)指令来设置结构体的对齐方式,其中n表示对齐的字节数。不过,在设置对齐方式时需要注意是否会影响程序的性能和便携性。 4. 结构体的初始化可以使用类似于数组的初始化方式,即在大括号中按顺序初始化成员,如果未初始化的成员将被自动赋值为0。 5. 结构体可以包含各种类型的数据成员,如整型、浮点型、字符型等,并且可以包含其他结构体或指针类型的成员。 6. 可以通过.运算符来访问结构体的成员,也可以通过结构体指针和->运算符来访问结构体的成员。 7. 结构体可以作为函数的参数和返回值,可以按值传递或传递指针。 8. 结构体的大小和成员的顺序可能会受到编译器和操作系统的限制,因此在不同的平台上可能会有所不同。 9. 结构体可以通过typedef关键字定义别名,以方便使用。 10. 在使用结构体时,应注意成员的命名,应该具有描述性并且易于理解,有助于提高代码的可读性和可维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值