概述
- MapStruct 可以将某几种类型的对象映射为另外一种类型,如将多个 DO(业务实体对象) 对象转换为 DTO(数据传输对象)
- 使用方式也很简单,定义一个映射接口,声明映射方法,配上注解,MapSturct 就会实现此接口
使用例子
添加依赖包
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-jdk8</artifactId>
<version>1.1.0.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.1.0.Final</version>
<scope>provided</scope>
</dependency>
假设我们有以下两张表,并插入两条数据
--商品类型信息表
CREATE TABLE `good_types` (
`tgt_id` int(11) NOT NULL AUTO_INCREMENT,
`tgt_name` varchar(30) DEFAULT NULL,
`tgt_is_show` int(1) DEFAULT NULL,
`tgt_order` int(255) DEFAULT NULL,
PRIMARY KEY (`tgt_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
--商品基本信息表
CREATE TABLE `good_infos` (
`tg_id` int(11) NOT NULL AUTO_INCREMENT,
`tg_type_id` int(11) DEFAULT NULL,
`tg_title` varchar(30) DEFAULT NULL,
`tg_price` decimal(8,2) DEFAULT NULL,
`tg_order` int(2) DEFAULT NULL,
PRIMARY KEY (`tg_id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
INSERT INTO `good_types` VALUES ('1', '青菜', '1', '1');
INSERT INTO `good_infos` VALUES ('1', '1', '芹菜', '12.40', '1');
创建DO(商品信息和商品类型)对象
----------商品信息----------
@Entity
@Table(name = "good_infos")
@Data
public class GoodInfo {
@Id
@Column(name = "tg_id")
private Long id;
@Column(name = "tg_title")
private String title;
@Column(name = "tg_price")
private double price;
@Column(name = "tg_order")
private int order;
@Column(name = "tg_type_id")
private Long typeId;
}
----------商品类型----------
@Entity
@Table(name = "good_types")
@Data
public class GoodType {
@Id
@Column(name = "tgt_id")
private Long id;
@Column(name = "tgt_name")
private String name;
@Column(name = "tgt_is_show")
private int show;
@Column(name = "tgt_order")
private int order;
}
创建 JPA 接口
----------商品信息JPA----------
public interface GoodInfoRepository extends JpaRepository<GoodInfo,Long> {}
----------商品类型JPA----------
public interface GoodTypeRepository extends JpaRepository<GoodType,Long> {}
创建 DTO(数据传输) 对象
@Data
public class GoodInfoDTO {
//商品编号
private String goodId;
//商品名称
private String goodName;
//商品价格
private double goodPrice;
//类型名称
private String typeName;
}
创建 Mapper,Mapper 接口是用来映射的,我们定义好 Mapper 后 MapStruct 就会帮我们实现该接口
@Mapper(componentModel = "spring")
public interface GoodInfoMapper {
@Mappings({
@Mapping(source = "type.name",target = "typeName"),
@Mapping(source = "good.id",target = "goodId"),
@Mapping(source = "good.title",target = "goodName"),
@Mapping(source = "good.price",target = "goodPrice")
})
GoodInfoDTO fromGoodInfoDTO(GoodInfo good, GoodType type);
}
可查看 Mapper 的实现,在 target/generated-sources/annotations 目录下查看 Mapper 的实现类 运行测试,创建一个Controller,通过 JPA 查询出商品信息和商品类型后通过 Mapper 接口的方法完成映射
@RestController
public class GoodInfoController {
@Autowired
private GoodInfoRepository goodInfoRepository;
@Autowired
private GoodTypeRepository goodTypeRepository;
@Autowired
private GoodInfoMapper goodInfoMapper;
@RequestMapping(value = "/detail/{id}")
public GoodInfoDTO details(@PathVariable("id")Long id){
GoodInfo goodInfo = goodInfoRepository.findOne(id);
GoodType goodType = goodTypeRepository.findOne(goodInfo.getId());
return goodInfoMapper.fromGoodInfoDTO(goodInfo,goodType);
}
}
MapStruct注解
- @Mapper:注解在接口、类上,这样 MapStruct 才会去实现该接口
- componentModel:该属性用于指定实现类的类型,有几个属性:
- default:默认,不使用任何组建类型,可以通过Mappers.getMapper(Class) 方式获取实例对象
- spring:在实现类上注解 @Component,可通过 @Autowired 方式注入
- jsr330:实现类上添加@javax.inject.Named 和@Singleton注解,可以通过 @Inject注解获取。
- componentModel:该属性用于指定实现类的类型,有几个属性:
- @Mappings:配置多个@Mapping
- @Mapping:配置属性映射,若源对象属性与目标对象名字一致,会自动映射对应属性
- source:源属性、target:目标属性
- dateFormat:可将 String 到 Date 日期之间相互转换,通过 SimpleDateFormat,该值为 SimpleDateFormat 的日期格式