string转换bigdecimal_使用MapStruct处理恼人的bean转换
煩人的Bean 轉換
對于代碼中 JavaBean之間的轉換, 一直是困擾我很久的事情。在開發的時候我看到業務代碼之間有很多的 JavaBean 之間的相互轉化, 非常的影響觀感, 卻又不得不存在。我后來想的一個辦法就是通過反射, 或者自己寫很多的轉換器。
第一種通過反射的方法確實比較方便, 但是現在無論是 BeanUtils, BeanCopier 等在使用反射的時候都會影響到性能。雖然我們可以進行反射信息的緩存來提高性能。但是像這種的話, 需要類型和名稱都一樣才會進行映射, 有很多時候, 由于不同的團隊之間使用的名詞不一樣, 還是需要很多的手動 set/get 等功能。
第二種的話就是會很浪費時間, 而且在添加新的字段的時候也要進行方法的修改。不過, 由于不需要進行反射, 其性能是很高的。
MapStruct 帶來的改變
MapSturct 是一個生成 類型安全, 高性能且無依賴的 JavaBean 映射代碼的注解處理器(annotation processor)。
抓一下重點:
從字面的理解, 我們可以知道, 該工具可以幫我們實現 JavaBean 之間的轉換, 通過注解的方式。
同時, 作為一個工具類,相比于手寫, 其應該具有便捷, 不容易出錯的特點。
MapStruct 入門
引入依賴
? org.mapstruct? mapstruct-jdk8? 1.3.1.Final? org.mapstruct? mapstruct-processor? 1.3.1.Final我現在在對接一個系統,傳過來的是支付信息PayInfo。后面數據庫存的是TExpensesRecords消費記錄。我需要進行bean的轉換。如果我一點點的寫get/set真是太煩人了,無腦的體力勞動。
甚至中間還牽涉了很多類型轉換,嵌套之類的繁瑣操作,而我們想要的只是建立它們之間的映射關系而已。有沒有一種通用的映射工具來幫我們搞定這一切。當然有而且還不少。有人說apache的BeanUtil.copyProperties可以實現,但是性能差而且容易出異常,很多規范嚴禁使用這種途徑。以下是對幾種對象映射框架的對比,大多數情況下 MapStruct 性能最高。原理類似于lombok ,MapStruct都是在編譯期進行實現,而且基于Getter、Setter,沒有使用反射所以一般不存在運行時性能問題。
測試
我現在有兩個類
一個是接口VO類
@Data@ApiModel("支付信息")public class PayInfo {? @ApiModelProperty("支付碼")? private String payCode;? @ApiModelProperty("總金額")? private String totalMoney;? @ApiModelProperty("菜品")? private List foods;? @ApiModelProperty(value = "服務商id")? private String serviceId;? @ApiModelProperty(value = "服務商名稱")? private String serviceName;? @ApiModelProperty(value = "餐廳編號")? private String restaurantCode;? @ApiModelProperty(value = "餐廳名稱")? private String restaurantName;? @ApiModelProperty(value = "機器號")? private String machineCode;? @ApiModelProperty(value = "消費類型(1:食堂用餐、2:網點消費、3:自助販賣機消費)")? private String expensesType;}一個是數據庫DO類
@Data@ApiModel(value ="TExpensesRecords", description="消費記錄表")public class TExpensesRecords implements Serializable {? @ApiModelProperty(value = "")? private Integer id;? @ApiModelProperty(value = "交易流水號(隨便生成唯一編號)")? private String tradeId;? @ApiModelProperty(value = "員工號")? private String userCode;? @ApiModelProperty(value = "服務商id")? private String serviceId;? @ApiModelProperty(value = "服務商名稱")? private String serviceName;? @ApiModelProperty(value = "餐廳編號")? private String restaurantCode;? @ApiModelProperty(value = "餐廳名稱")? private String restaurantName;? @ApiModelProperty(value = "機器號")? private String machineCode;? @ApiModelProperty(value = "消費類型(1:食堂用餐、2:網點消費、3:自助販賣機消費)")? private String expensesType;? @ApiModelProperty(value = "消費金額")? private BigDecimal amount;? @ApiModelProperty(value = "消費時間")? private LocalDateTime expensesDate;可以看到,他們有一些屬性是同名的。
我們一步步來寫。
先寫一個轉換接口
寫一個測試類
@Testpublic void payInfo2ExpenseRecord() throws Exception {? PayInfo payInfo = new PayInfo();? payInfo.setPayCode("20200513_01471111_120_40_1589359038744");? payInfo.setTotalMoney("39.3");? payInfo.setServiceId("001");? payInfo.setServiceName("服務商A");? payInfo.setRestaurantCode("A001");? payInfo.setRestaurantName("餐廳A");? payInfo.setMachineCode("M001");? payInfo.setExpensesType("1");? TExpensesRecords tExpensesRecords =? ? ? ? ? PayInfoMapper.INSTANCE.payInfo2ExpenseRecord(payInfo);? log.info(tExpensesRecords.toString());}可以看到,大部分相同名字的屬性已經完成轉換。但是名字不一致的,需要我們單獨配置下。
處理不同名的屬性
代碼也很好理解,就是將源的payCode字段映射到目標的tradeId字段
看下測試結果
TExpensesRecords(id=null, tradeId=20200513_01471111_120_40_1589359038744, userCode=null, serviceId=001, serviceName=服務商A, restaurantCode=A001, restaurantName=餐廳A, machineCode=M001, expensesType=1, amount=39.3, expensesDate=null)tradeId映射成功。而且totalMoney是String,映射成BigDecimal的amount也成功了
原理
原理類似于lombok ,MapStruct都是在編譯期對接口進行實現,而且基于Getter、Setter,沒有使用反射所以一般不存在運行時性能問題。 類型不同,會自動進行轉換。
Spring 注入的方式
上面的例子是默認的方式
? PayInfoMapper INSTANCE = Mappers.getMapper(PayInfoMapper.class);在正常的項目中,一般和spring整合使用
就是在 @Mapper 后面加入 componentModel="spring"
在用到的地方就可以使用@Autowired注入了
注解說明
@Mapper 只有在接口加上這個注解, MapStruct 才會去實現該接口? @Mapper 里有個 componentModel 屬性,主要是指定實現類的類型,一般用到兩個? default:默認,可以通過 Mappers.getMapper(Class) 方式獲取實例對象? spring:在接口的實現類上自動添加注解 @Component,可通過 @Autowired 方式注入@Mapping:屬性映射,若源對象屬性與目標對象名字一致,會自動映射對應屬性? source:源屬性? target:目標屬性? dateFormat:String 到 Date 日期之間相互轉換,通過 SimpleDateFormat,該值為 SimpleDateFormat ? ? ? ? ? ? 的日期格式? ignore: 忽略這個字段@Mappings:配置多個@Mapping@MappingTarget 用于更新已有對象@InheritConfiguration 用于繼承配置高級使用
多對一
類型轉換
總結
以上是生活随笔為你收集整理的string转换bigdecimal_使用MapStruct处理恼人的bean转换的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 如何快速转换一维表与二维表? Excel
- 下一篇: rgb fusion检测不到显卡_买不到