亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

mapStruct java bean映射工具怎么用

發布時間:2021-10-19 15:42:56 來源:億速云 閱讀:131 作者:柒染 欄目:大數據

今天就跟大家聊聊有關mapStruct  java bean映射工具怎么用,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。

在一個成熟的工程中,尤其是現在的分布式系統中,應用與應用之間,還有單獨的應用細分模塊之后,DO 一般不會讓外部依賴,這時候需要在提供對外接口的模塊里放 DTO 用于對象傳輸,也即是 DO 對象對內,DTO對象對外,DTO 可以根據業務需要變更,并不需要映射 DO 的全部屬性。

這種 對象與對象之間的互相轉換,就需要有一個專門用來解決轉換問題的工具,畢竟每一個字段都 get/set 會很麻煩。

MapStruct 就是這樣的一個屬性映射工具,只需要定義一個 Mapper 接口,MapStruct 就會自動實現這個映射接口,避免了復雜繁瑣的映射實現。

一、工程中引入 maven 依賴

<properties>
    <mapstruct.version>1.2.0.Final</mapstruct.version>
</properties>

<dependencies>
    <dependency>
      <groupId>org.mapstruct</groupId>
      <artifactId>mapstruct-jdk8</artifactId>
      <version>${mapstruct.version}</version>
    </dependency>
    <dependency>
      <groupId>org.mapstruct</groupId>
      <artifactId>mapstruct-processor</artifactId>
      <version>${mapstruct.version}</version>
    </dependency>
</dependencies>

二、基本映射

這里定義兩個 DO 對象 Person 和 User,其中 user 是 Person 的一個屬性 ,一個 DTO 對象 PersonDTO。

JavaBean:

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Person {
    private Long id;
    private String name;
    private String email;
    private Date birthday;
    private User user;
}

@NoArgsConstructor
@AllArgsConstructor
@Data
public class User {
    private Integer age;
}

@NoArgsConstructor
@AllArgsConstructor
@Data
public class PersonDTO {
    private Long id;
    private String name;
    /**
     * 對應 Person.user.age
     */
    private Integer age;
    private String email;
    /**
     * 與 DO 里面的字段名稱(birthDay)不一致
     */
    private Date birth;
    /**
     * 對 DO 里面的字段(birthDay)進行拓展,dateFormat 的形式
     */
    private String birthDateFormat;
    /**
     * 對 DO 里面的字段(birthDay)進行拓展,expression 的形式
     */
    private String birthExpressionFormat;

}

寫一個 Mapper 接口 PersonConverter,其中兩個方法,一個是單實體映射,另一個是List映射。

若源對象屬性與目標對象屬性名字一致,會自動映射對應屬性,不一樣的需要指定,也可以用 format 轉成自己想要的類型,也支持表達式的方式,可以看到像 id、name、email這些名詞一致的我并沒有指定 source-target,而birthday-birth指定了,轉換格式的 birthDateFormat 加了dateFormat 或者 birthExpressionFormat 加了 expression,如果某個屬性你不想映射,可以加個 ignore=true。

MapSruct的Mapper(映射類):

@Mapper
public interface PersonConverter {
    PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);
    @Mappings({
        @Mapping(source = "birthday", target = "birth"),
        @Mapping(source = "birthday", target = "birthDateFormat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
        @Mapping(target = "birthExpressionFormat", expression = "java(org.apache.commons.lang3.time.DateFormatUtils.format(person.getBirthday(),\"yyyy-MM-dd HH:mm:ss\"))"),
        @Mapping(source = "user.age", target = "age"),
        @Mapping(target = "email", ignore = true)
    })
    PersonDTO domain2dto(Person person);

    List<PersonDTO> domain2dto(List<Person> people);
}

編譯MapStruct之后,手工編譯或者啟動 IDE 的時候 IDE 也會幫我們編譯, 會自動在 target/classes 下生成對應的實現類。

手工編譯命令
mvn compile

注意!!!下面這個 PersonConverterImpl 是自動生成的,不是自己寫的!

public class PersonConverterImpl implements PersonConverter {
    public PersonConverterImpl() {
    }

    public PersonDTO domain2dto(Person person) {
        if (person == null) {
            return null;
        } else {
            PersonDTO personDTO = new PersonDTO();
            personDTO.setBirth(person.getBirthday());
            if (person.getBirthday() != null) {
                personDTO.setBirthDateFormat((new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(person.getBirthday()));
            }

            Integer age = this.personUserAge(person);
            if (age != null) {
                personDTO.setAge(age);
            }

            personDTO.setId(person.getId());
            personDTO.setName(person.getName());
            personDTO.setBirthExpressionFormat(DateFormatUtils.format(person.getBirthday(), "yyyy-MM-dd HH:mm:ss"));
            return personDTO;
        }
    }

    public List<PersonDTO> domain2dto(List<Person> people) {
        if (people == null) {
            return null;
        } else {
            List<PersonDTO> list = new ArrayList(people.size());
            Iterator var3 = people.iterator();

            while(var3.hasNext()) {
                Person person = (Person)var3.next();
                list.add(this.domain2dto(person));
            }

            return list;
        }
    }

    private Integer personUserAge(Person person) {
        if (person == null) {
            return null;
        } else {
            User user = person.getUser();
            if (user == null) {
                return null;
            } else {
                Integer age = user.getAge();
                return age == null ? null : age;
            }
        }
    }
}

寫一個單元測試類 PersonConverterTest 測試一下,看看效果。

public class PersonConverterTest {
    @Test
    public void test() {
        Person person = new Person(1L,"zhige","zhige.me@gmail.com",new Date(),new User(1));
        PersonDTO personDTO = PersonConverter.INSTANCE.domain2dto(person);
        assertNotNull(personDTO);
        assertEquals(personDTO.getId(), person.getId());
        assertEquals(personDTO.getName(), person.getName());
        assertEquals(personDTO.getBirth(), person.getBirthday());
        String format = DateFormatUtils.format(personDTO.getBirth(), "yyyy-MM-dd HH:mm:ss");
        assertEquals(personDTO.getBirthDateFormat(),format);
        assertEquals(personDTO.getBirthExpressionFormat(),format);

        List<Person> people = new ArrayList<>();
        people.add(person);
        List<PersonDTO> personDTOs = PersonConverter.INSTANCE.domain2dto(people);
        assertNotNull(personDTOs);
    }
}

三、多對一

MapStruct 可以將幾種類型的對象映射為另外一種類型,比如將多個 DO 對象轉換為 DTO。

例子:

  • 兩個 DO 對象 Item 和 Sku,一個 DTO 對象 SkuDTO

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Item {
    private Long id;
    private String title;
}

@NoArgsConstructor
@AllArgsConstructor
@Data
public class Sku {
    private Long id;
    private String code;
    private Integer price;
}

@NoArgsConstructor
@AllArgsConstructor
@Data
public class SkuDTO {
    private Long skuId;
    private String skuCode;
    private Integer skuPrice;
    private Long itemId;
    private String itemName;
}
  • 創建 ItemConverter(映射)接口,MapStruct 就會自動實現該接口。

@Mapper
public interface ItemConverter {
    ItemConverter INSTANCE = Mappers.getMapper(ItemConverter.class);

    @Mappings({
            @Mapping(source = "sku.id",target = "skuId"),
            @Mapping(source = "sku.code",target = "skuCode"),
            @Mapping(source = "sku.price",target = "skuPrice"),
            @Mapping(source = "item.id",target = "itemId"),
            @Mapping(source = "item.title",target = "itemName")
    })
    SkuDTO domain2dto(Item item, Sku sku);
}
  • 創建測試類,講 Item 和 Sku 兩個 DO對象,映射成一個 DTO 對象 SkuDTO

public class ItemConverterTest {
    @Test
    public void test() {
        Item item = new Item(1L, "iPhone X");
        Sku sku = new Sku(2L, "phone12345", 1000000);
        SkuDTO skuDTO = ItemConverter.INSTANCE.domain2dto(item, sku);
        assertNotNull(skuDTO);
        assertEquals(skuDTO.getSkuId(),sku.getId());
        assertEquals(skuDTO.getSkuCode(),sku.getCode());
        assertEquals(skuDTO.getSkuPrice(),sku.getPrice());
        assertEquals(skuDTO.getItemId(),item.getId());
        assertEquals(skuDTO.getItemName(),item.getTitle());
    }
}

四、可以添加自定義方法

// 形式如下 
default PersonDTO personToPersonDTO(Person person) {
    //hand-written mapping logic
}

// 比如在 PersonConverter 里面加入如下
default Boolean convert2Bool(Integer value) {
    if (value == null || value < 1) {
        return Boolean.FALSE;
    } else {
        return Boolean.TRUE;
    }
}

default Integer convert2Int(Boolean value) {
    if (value == null) {
        return null;
    }
    if (Boolean.TRUE.equals(value)) {
        return 1;
    }
    return 0;
}
// 測試類 PersonConverterTest 加入
assertTrue(PersonConverter.INSTANCE.convert2Bool(1));
assertEquals((int)PersonConverter.INSTANCE.convert2Int(true),1);

五、Spring 注入的方式

// 剛才一直寫的例子是默認的方式
PersonConverter INSTANCE = Mappers.getMapper(PersonConverter.class);

還有一種常用的方式,是和常用的框架 Spring 結合,在 @Mapper 后面加入 componentModel="spring"。

@Mapper(componentModel="spring")
public interface PersonConverter {
    @Mappings({
        @Mapping(source = "birthday", target = "birth"),
        @Mapping(source = "birthday", target = "birthDateFormat", dateFormat = "yyyy-MM-dd HH:mm:ss"),
        @Mapping(target = "birthExpressionFormat", expression = "java(org.apache.commons.lang3.time.DateFormatUtils.format(person.getBirthday(),\"yyyy-MM-dd HH:mm:ss\"))"),
        @Mapping(source = "user.age", target = "age"),
        @Mapping(target = "email", ignore = true)
    })
    PersonDTO domain2dto(Person person);
}

這時候測試類改一下,我用的 spring boot 的形式。

@RunWith(SpringRunner.class)
@SpringBootTest(classes = BaseTestConfiguration.class)
public class PersonConverterTest {
    //這里把轉換器裝配進來
    @Autowired
    private PersonConverter personConverter;
    @Test
    public void test() {
        Person person = new Person(1L,"zhige","zhige.me@gmail.com",new Date(),new User(1));
        PersonDTO personDTO = personConverter.domain2dto(person);

        assertNotNull(personDTO);
        assertEquals(personDTO.getId(), person.getId());
        assertEquals(personDTO.getName(), person.getName());
        assertEquals(personDTO.getBirth(), person.getBirthday());
        String format = DateFormatUtils.format(personDTO.getBirth(), "yyyy-MM-dd HH:mm:ss");
        assertEquals(personDTO.getBirthDateFormat(),format);
        assertEquals(personDTO.getBirthExpressionFormat(),format);

    }
}

六、MapStruct 注解的關鍵詞

@Mapper 只有在接口加上這個注解, MapStruct 才會去實現該接口
    @Mapper 里有個 componentModel 屬性,主要是指定實現類的類型,一般用到兩個
    default:默認,可以通過 Mappers.getMapper(Class) 方式獲取實例對象
    spring:在接口的實現類上自動添加注解 @Component,可通過 @Autowired 方式注入
@Mapping:屬性映射,若源對象屬性與目標對象名字一致,會自動映射對應屬性
    source:源屬性
    target:目標屬性
    dateFormat:String 到 Date 日期之間相互轉換,通過 SimpleDateFormat,該值為 SimpleDateFormat              的日期格式
    ignore: 忽略這個字段
@Mappings:配置多個@Mapping
@MappingTarget 用于更新已有對象
@InheritConfiguration 用于繼承配置

看完上述內容,你們對mapStruct  java bean映射工具怎么用有進一步的了解嗎?如果還想了解更多知識或者相關內容,請關注億速云行業資訊頻道,感謝大家的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

敦煌市| 巴里| 周口市| 花垣县| 潢川县| 南通市| 团风县| 潜山县| 盈江县| 永定县| 毕节市| 盐山县| 临颍县| 山东| 嘉定区| 崇左市| 庆元县| 邵阳市| 叙永县| 称多县| 包头市| 河津市| 木里| 泾阳县| 威信县| 湄潭县| 漯河市| 扶沟县| 扶绥县| 丹东市| 延川县| 当涂县| 安龙县| 宿迁市| 土默特右旗| 磴口县| 青阳县| 威信县| 原平市| 高要市| 潼关县|