掃二維碼與項目經(jīng)理溝通
我們在微信上24小時期待你的聲音
解答本文疑問/技術咨詢/運營咨詢/技術建議/互聯(lián)網(wǎng)交流
大家在開發(fā)中,最讓人頭疼的就是:對象之間的拷貝,前端的VO和數(shù)據(jù)庫的Entity不一致!

創(chuàng)新互聯(lián)建站專注于廣東企業(yè)網(wǎng)站建設,自適應網(wǎng)站建設,成都做商城網(wǎng)站。廣東網(wǎng)站建設公司,為廣東等地區(qū)提供建站服務。全流程按需策劃,專業(yè)設計,全程項目跟蹤,創(chuàng)新互聯(lián)建站專業(yè)和態(tài)度為您提供的服務
性能最好的就是手動set,主要是枯燥且無技術含量,不僅耗費大量時間而且很容易出錯;
所以我們要成為優(yōu)秀的程序員,要多借助輪子,開發(fā)效率事半功倍,開發(fā)技能也是增長不少!
如果系統(tǒng)性能沒有要求,怎么實現(xiàn)都是好的,但是我們要有追求哈,追求高質(zhì)量!
每個東西都有存在的價值,不要捧一踩一哈!
MapStruct是基于JSR 269的Java注釋處理器,用于生成類型安全的 Bean 映射類。
您所要做的就是定義一個映射器接口,該接口聲明任何所需的映射方法。在編譯過程中,MapStruct將生成此接口的實現(xiàn)。此實現(xiàn)使用純 Java 方法調(diào)用在源對象和目標對象之間進行映射,即無反射或類似內(nèi)容。
與手動編寫映射代碼相比,MapStruct通過生成繁瑣且容易出錯的代碼來節(jié)省時間。遵循配置方法的約定,MapStruct使用合理的默認值,但在配置或?qū)崿F(xiàn)特殊行為時會步入歧途。
與動態(tài)映射框架相比,MapStruct具有以下優(yōu)點:
性能圖大家可以看一下:
@Mapper將接口標記為映射接口對于源對象和目標對象中具有不同名稱的屬性,可以使用注釋來配置名稱:@Mapping按照約定,接口聲明一個成員Mappers INSTANCE,為客戶端提供對映射器實現(xiàn)的訪問。下面我們來具體使用!
這里使用最新的,如果引入了lombok可能會有問題,就是他們倆都是在編譯期運行的,mapstruct如果比lombok先執(zhí)行,就會找不到get、set方法,所以會有問題,官網(wǎng)已經(jīng)有了解決方案!現(xiàn)在是啟動不會報錯!
org.mapstruct
mapstruct
1.5.3.Final
org.projectlombok
lombok
1.18.24
我們需要加上依賴:
org.mapstruct
mapstruct-processor
1.5.3.Final
java: No property named "name" exists in source parameter(s).
Type "UserVO" has no properties.
官網(wǎng)解決文章地址:https://mapstruct.org/faq/#Can-I-use-MapStruct-together-with-Project-Lombok。
org.apache.maven.plugins
maven-compiler-plugin
3.8.1
1.8
1.8
org.mapstruct
mapstruct-processor
1.5.3.Final
org.projectlombok
lombok
1.18.24
org.projectlombok
lombok-mapstruct-binding
0.2.0
用戶表:
@Data
public class User {
private Integer id;
private String username;
private Integer age;
}
前端用戶VO:
@Data
public class UserVO {
private Integer id;
private String name;
private Integer age;
}
我們創(chuàng)建接口進行兩個對象之間的映射:
import com.example.demo.mapstruct.entity.User;
import com.example.demo.mapstruct.entity.UserVO;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
/**
* @author wangzhenjun
* @date 2023/1/28 16:05
*/
@Mapper
public interface UserMapper {
UserMapper INSTANCE = Mappers.getMapper(UserMapper.class);
@Mapping(source ="name",target = "username")
User userVOToUser(UserVO userVO);
}
屬性多了可以嵌套:
@Mappings({
@Mapping(source ="name",target = "username"),
@Mapping(source ="name1",target = "username1")
})也可以:
@Mapping(source ="name",target = "username")
@Mapping(source ="name1",target = "username1")
編寫測試類:
@SpringBootTest
class DemoApplicationTests {
@Test
void demoMapstruct(){
UserVO userVO = new UserVO(1,"小紅",18);
User user = UserMapper.INSTANCE.userVOToUser(userVO);
System.out.println(user);
}
}
我們看到拷貝沒有任何問題!
我們看看是怎么實現(xiàn)的:
mapstruct會在編譯期自動生成實現(xiàn)類去幫助我們?nèi)ベx值,不指定默認策略,名稱一致進行copy!不一致可以按上面的進行指定,不指定則不會有set方法!
下面進行多個源參數(shù)的映射方法演示:
我們把user類加上一個字段:
private BigDecimal score;
新增加一個Score類:
@Data
@AllArgsConstructor
public class Score {
private Integer studentId;
private BigDecimal score;
}
調(diào)整上面的UserMapper接口:
@Mappings({
@Mapping(source ="userVO.name",target = "username"),
@Mapping(source ="score.score",target = "score")
})
User userVOToUser(UserVO userVO, Score score);測試代碼:
UserVO userVO = new UserVO(1,"小紅",18);
Score score = new Score(1,new BigDecimal(100));
User user = UserMapper.INSTANCE.userVOToUser(userVO,score);
System.out.println(user);
結果顯示正常:
我們在來看一個企業(yè)級能夠用得上的,就是自定義方法,然后進行賦值:
場景:一個商品有長寬高,我們把長寬高從cm變?yōu)閙!
還有很多String轉(zhuǎn)Integer、Float等等,都是按照下面這種自定義方法去實現(xiàn)!
VO和對象都是一樣的哈!
@Data
@AllArgsConstructor
public class ProductVO {
private Integer id;
private String name;
private BigDecimal length;
private BigDecimal width;
private BigDecimal high;
}
看清楚,別導錯包了!
qualifiedByName:指定自定義方法的名稱。
@Named("cmToM"):起別名,不使用找不到方法。
可以寫一起,也可以整一個工具類里寫方法,在這里進行引用!如果是使用spring,我們可以把接口作為bean進行注入調(diào)用(推薦)加上參數(shù)即可開啟:
?@Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
/**
* @author wangzhenjun
* @date 2023/1/28 17:13
*/
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING)
public interface ProductMapper {
@Mapping(source = "length",target = "length",qualifiedByName = "cmToM")
@Mapping(source = "width",target = "width",qualifiedByName = "cmToM")
@Mapping(source = "high",target = "high",qualifiedByName = "cmToM")
Product productVOToPrduct(ProductVO productVO);
@Named("cmToM")
default BigDecimal cmToM (BigDecimal oldValue){
if (oldValue == null) {
return BigDecimal.ZERO;
}
return oldValue.divide(new BigDecimal("100"));
}
}
測試:
@SpringBootTest
class DemoApplicationTests {
@Autowired
private ProductMapper productMapper;
@Test
void demoMapstruct(){
ProductVO productVO = new ProductVO(1,"美麗家園地板",new BigDecimal(100),new BigDecimal(50),new BigDecimal(8));
Product product = productMapper.productVOToProduct(productVO);
System.out.println(product);
}
}
完美轉(zhuǎn)化!
在實戰(zhàn)一個LocalDateTime、String相互轉(zhuǎn)化的,后面大家可以去官網(wǎng)文檔去找你需要的:
在剛剛的商品類加個字段:
private String createdAt;
VO里也加上一個:
private LocalDateTime createdAt;
編寫個轉(zhuǎn)化類:
這里交給spring管理了,因為ProductMapper也交給spring管理,不加的話會找不到此類!
@Component
public class LocalDateTimeMapper {
public String asString(LocalDateTime date) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
return date != null ? date.format(formatter): null;
}
public LocalDateTime asLocalDateTime(String date) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
return date != null ? LocalDateTime.parse(date,formatter) : null;
}
}
ProductMapper修改一下:
uses = LocalDateTimeMapper.class使用咱們上面寫的類即可!
@Mapper(componentModel = MappingConstants.ComponentModel.SPRING,uses = LocalDateTimeMapper.class)
public interface ProductMapper {
@Mapping(source = "length",target = "length",qualifiedByName = "cmToM")
@Mapping(source = "width",target = "width",qualifiedByName = "cmToM")
@Mapping(source = "high",target = "high",qualifiedByName = "cmToM")
Product productVOToProduct(ProductVO productVO);
@Named("cmToM")
default BigDecimal cmToM (BigDecimal oldValue){
if (oldValue == null) {
return BigDecimal.ZERO;
}
return oldValue.divide(new BigDecimal("100"));
}
}
測試一下:
ProductVO productVO = new ProductVO(1,"美麗家園地板",
new BigDecimal(100),new BigDecimal(50),
new BigDecimal(8), LocalDateTime.now());
Product product = productMapper.productVOToProduct(productVO);
System.out.println(product);
完美轉(zhuǎn)化:

我們在微信上24小時期待你的聲音
解答本文疑問/技術咨詢/運營咨詢/技術建議/互聯(lián)網(wǎng)交流