@mapper注解的使用_优雅的对象转换解决方案-MapStruct使用进阶(二)

本文详细介绍了MapStruct在对象转换中的应用,包括属性名称相同时的自动转化、不同属性名的@Mapping注解映射、自定义转换方法、多对象转换为一个对象的多转一操作,以及如何更新Bean对象。同时,文章探讨了Mapper的获取方式,包括通过Mapper工厂和依赖注入,并解释了依赖注入的策略选择。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在 MapStruct 生成对应的实现类的时候, 有如下的几个情景。

1 属性名称相同,则进行转化

在实现类的时候, 如果属性名称相同, 则会进行对应的转化。这个在之前的文章代码中已经有所体现。 通过此种方式, 我们可以快速的编写出转换的方法。

源对象类

777dd63af9f14799cecdbca06109b39b.png

目标对象类

7f871675a6fc135e91c2c50137e2202e.png

转化类

1532af301bc3621fb9c4f16bb0106cf6.png

由于 Source 和 Target 需要转化的属性是完全相同的。因此, 在 Mapper 中, source2target 方法很快就可以编写出来了。 只需要确定入参和返回值即可。

2 属性名不相同, 可通过 @Mapping 注解进行指定转化。

属性名不相同, 在需要进行互相转化的时候, 则我们可以通过 @Mapping 注解来进行转化。

在上面的 Source 类中, 增加一个属性 totalCount

93c03aa0deceeff4bc68160169c12644.png

而对应的 Target 中, 定义的属性是 count。

36fc84251052cca842ca1022284de0e7.png

如果方法没做任何的改变, 那么,在转化的时候, 由于属性名称不相同, 会导致 count 属性没有值。

6cece61b653b171f08846c8b9bae9a11.png

这时候, 可以通过 @Mappimg 的方式进行映射。

0d89a4acabea2f87572a826ba60ffdfb.png

仅仅是在方法上面加了一行。再次允许测试程序。

455f9aaf0b8efe3fee9aa9d398782af2.png

3 Mapper 中使用自定义的转换

有时候, 对于某些类型, 无法通过代码生成器的形式来进行处理。 那么, 就需要自定义的方法来进行转换。 这时候, 我们可以在接口(同一个接口, 后续还有调用别的 Mapper 的方法)中定义默认方法(Java8及之后)。

在 Source 类中增加

e3a25aeabd9f4cd747131839451b04e4.png

对应的类

7dcc1bde41f7d92434cf6920757f977b.png

相应的, 在 Target 中

d15deab15834299f41c00dcdbf3ca0ed.png

对应的类

5fa9c1aafa3175d921ee7128015aab8c.png

然后在 SourceMapper 中添加方法及映射, 对应的方法更改后

569e76d45627a9039ac9e2132b3c31ba.png

进行测试

52b2c98374772f5d5e0f040b8fda1638.png

4 多转一

我们在实际的业务中少不了将多个对象转换成一个的场景。 MapStruct 当然也支持多转一的操作。

有 Address 和 Person 两个对象。

84109f7f4bf3e9678bb21c2d94443058.png

而在实际的使用时, 我们需要的是 DeliveryAddress 类

4162adf06ab9e7b6057da721a332152e.png

其对应的信息不仅仅来自一个类, 那么, 我们也可以通过配置来实现多到一的转换。

afe6495c7b1ee80c792f0772fa934b70.png

测试

4aaee2cafbdaeef326fd86faf4841f1e.png

在多对一转换时, 遵循以下几个原则

  1. 当多个对象中, 有其中一个为 null, 则会直接返回 null
  2. 如一对一转换一样, 属性通过名字来自动匹配。 因此, 名称和类型相同的不需要进行特殊处理
  3. 当多个原对象中,有相同名字的属性时,需要通过 @Mapping 注解来具体的指定, 以免出现歧义(不指定会报错)。 如上面的 description

属性也可以直接从传入的参数来赋值。

d01c08efd0285d61ef16669530ca6965.png

在上面的例子中, hn 直接赋值给 houseNumber。

5 更新 Bean 对象

有时候, 我们不是想返回一个新的 Bean 对象, 而是希望更新传入对象的一些属性。这个在实际的时候也会经常使用到。

在 AddressMapper 类中, 新增如下方法

f923a5a16cc4b291bcad291ab906304a.png

注解 @MappingTarget后面跟的对象会被更新。 以上的代码可以通过以下的测试。

fa53afb0b873554e8cb9f3ebae45fc22.png

6 获取 mapper

6.1 通过 Mapper 工厂获取

在上面的例子中, 我们都是通过 Mappers.getMapper(xxx.class) 的方式来进行对应 Mapper 的获取。 此种方法为通过 Mapper 工厂获取。

如果是此种方法, 约定俗成的是在接口内定义一个接口本身的实例 INSTANCE, 以方便获取对应的实例。

b32fcde3d80418bc82f0d331f302d692.png

这样在调用的时候, 我们就不需要在重复的去实例化对象了。类似下面

ca7d8cef3391a8650fa6e3fa6121d808.png

6.2 使用依赖注入

对于 Web 开发, 依赖注入应该很熟悉。 MapSturct 也支持使用依赖注入, 同时也推荐使用依赖注入。

值注入方式default默认的方式, 使用 Mappers.getMapper(Class) 来进行获取 MappercdiContexts and Dependency Injection. 使用此种方式, 需要使用 @Inject 来进行注入springSpring 的方式, 可以通过 @Autowired 来进行注入jsr330生成的 Mapper 中, 使用 @javax.inject.Named 和 @Singleton 注解, 通过 @Inject 来注入

6.3 依赖注入策略

可以选择是通过构造方法或者属性注入, 默认是属性注入。

74fed3c832f5025cf47c7930b88aefe2.png

类似如此使用

243b1ce91446f723f7c08faa50699d7c.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值