溫馨提示×

溫馨提示×

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

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

分析mybatis中@Mapper注解的componentModel屬性

發(fā)布時間:2021-11-04 15:54:24 來源:億速云 閱讀:920 作者:iii 欄目:web開發(fā)

本篇內(nèi)容主要講解“分析mybatis中@Mapper注解的componentModel屬性”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學(xué)習(xí)“分析mybatis中@Mapper注解的componentModel屬性”吧!

一、準(zhǔn)備工作

1.1、了解@Mapper 注解

從 mybatis3.4.0 開始加入的 @Mapper 注解,目的就是為了不再寫mapper映射文件。

我們只需要在 dao 層定義的接口上使用注解就可以實現(xiàn)sql語句的編寫,例如:

@Select("select * from user where name = #{name}") public User find(String name);

如上就是一個簡單的使用,雖然簡單,但也確實體現(xiàn)出了這個注解的優(yōu)越性,至少少寫了一個xml文件。

所以我就只是想說下 @Mapper 注解的  componentModel 屬性,componentModel 屬性用于指定自動生成的接口實現(xiàn)類的組件類型,這個屬性支持四個值:

  • default: 這是默認(rèn)的情況,mapstruct 不使用任何組件類型,  可以通過Mappers.getMapper(Class)方式獲取自動生成的實例對象。

  • cdi: the generated mapper is an application-scoped CDI bean and can be  retrieved via @Inject

  • spring: 生成的實現(xiàn)類上面會自動添加一個@Component注解,可以通過Spring的 @Autowired方式進(jìn)行注入

  • jsr330: 生成的實現(xiàn)類上會添加@javax.inject.Named 和@Singleton注解,可以通過 @Inject注解獲取

1.2、依賴包

首先需要把依賴包導(dǎo)入,主要由兩個包組成:

  • org.mapstruct:mapstruct:包含了一些必要的注解,例如@Mapping。r若我們使用的JDK版本高于1.8,當(dāng)我們在pom里面導(dǎo)入依賴時候,建議使用坐標(biāo)是:org.mapstruct:mapstruct-jdk8,這可以幫助我們利用一些Java8的新特性。

  • org.mapstruct:mapstruct-processor:注解處理器,根據(jù)注解自動生成mapper的實現(xiàn)。

<dependency>         <groupId>org.mapstruct</groupId>         <!-- jdk8以下就使用mapstruct -->         <artifactId>mapstruct-jdk8</artifactId>         <version>1.2.0.Final</version>     </dependency>     <dependency>         <groupId>org.mapstruct</groupId>         <artifactId>mapstruct-processor</artifactId>         <version>1.2.0.Final</version>     </dependency>

好了,準(zhǔn)備工作做完了,接下來我們就看看巧媳婦兒巧在什么地方吧。

二、先簡單玩一把

2.1、定義實體類以及被映射類

// 實體類 @Data @NoArgsConstructor @AllArgsConstructor @Builder public class User {     private Integer id;     private String name;     private String createTime;     private LocalDateTime updateTime; }  // 被映射類VO1:和實體類一模一樣 @Data @NoArgsConstructor @AllArgsConstructor @Builder public class UserVO1 {     private Integer id;     private String name;     private String createTime;     private LocalDateTime updateTime; }  // 被映射類VO1:比實體類少一個字段 @Data @NoArgsConstructor @AllArgsConstructor @Builder public class UserVO2 {     private Integer id;     private String name;     private String createTime;  }

2.2、定義接口:

當(dāng)實體類和被映射對象屬性相同或者被映射對象屬性值少幾個時:

@Mapper(componentModel = "spring") public interface UserCovertBasic {     UserCovertBasic INSTANCE = Mappers.getMapper(UserCovertBasic.class);      /**      * 字段數(shù)量類型數(shù)量相同,利用工具BeanUtils也可以實現(xiàn)類似效果      * @param source      * @return      */     UserVO1 toConvertVO1(User source);     User fromConvertEntity1(UserVO1 userVO1);      /**      * 字段數(shù)量類型相同,數(shù)量少:僅能讓多的轉(zhuǎn)換成少的,故沒有fromConvertEntity2      * @param source      * @return      */     UserVO2 toConvertVO2(User source); }

從上面的代碼可以看出:接口中聲明了一個成員變量INSTANCE,母的是讓客戶端可以訪問 Mapper 接口的實現(xiàn)。

2.3、使用

@RestController public class TestController {      @GetMapping("convert")     public Object convertEntity() {         User user = User.builder()                 .id(1)                 .name("張三")                 .createTime("2020-04-01 11:05:07")                 .updateTime(LocalDateTime.now())                 .build();         List<Object> objectList = new ArrayList<>();          objectList.add(user);          // 使用mapstruct         UserVO1 userVO1 = UserCovertBasic.INSTANCE.toConvertVO1(user);         objectList.add("userVO1:" + UserCovertBasic.INSTANCE.toConvertVO1(user));         objectList.add("userVO1轉(zhuǎn)換回實體類user:" + UserCovertBasic.INSTANCE.fromConvertEntity1(userVO1));         // 輸出轉(zhuǎn)換結(jié)果         objectList.add("userVO2:" + " | " + UserCovertBasic.INSTANCE.toConvertVO2(user));         // 使用BeanUtils         UserVO2 userVO22 = new UserVO2();         BeanUtils.copyProperties(user, userVO22);         objectList.add("userVO22:" + " | " + userVO22);          return objectList;     } }

2.4、查看編譯結(jié)果

通過IDE的反編譯功能查看編譯后自動生成 UserCovertBasic  的實現(xiàn)類 UserCovertBasicImpl ,內(nèi)容如下:

@Component public class UserCovertBasicImpl implements UserCovertBasic {     public UserCovertBasicImpl() {     }      public UserVO1 toConvertVO1(User source) {         if (source == null) {             return null;         } else {             UserVO1 userVO1 = new UserVO1();             userVO1.setId(source.getId());             userVO1.setName(source.getName());             userVO1.setCreateTime(source.getCreateTime());             userVO1.setUpdateTime(source.getUpdateTime());             return userVO1;         }     }      public User fromConvertEntity1(UserVO1 userVO1) {         if (userVO1 == null) {             return null;         } else {             User user = new User();             user.setId(userVO1.getId());             user.setName(userVO1.getName());             user.setCreateTime(userVO1.getCreateTime());             user.setUpdateTime(userVO1.getUpdateTime());             return user;         }     }      public UserVO2 toConvertVO2(User source) {         if (source == null) {             return null;         } else {             UserVO2 userVO2 = new UserVO2();             userVO2.setId(source.getId());             userVO2.setName(source.getName());             userVO2.setCreateTime(source.getCreateTime());             return userVO2;         }     } }

2.5、瀏覽器查看結(jié)果

分析mybatis中@Mapper注解的componentModel屬性

好了,一個流程就走完了,是不是感覺賊簡單呢?

而且呀,阿粉溫馨提醒:如果是要轉(zhuǎn)換一個集合的話,只需要把這里的實體類換成集合就行了,例如:

List<UserVO1> toConvertVOList(List<User> source);

三、不簡單的情況

上面已經(jīng)把整個流程都給過了一遍了,相信大家對 mapstruct  也有了一個基礎(chǔ)的了解了,所以接下來的情況我們就不展示全部代碼了,畢竟篇幅也有限,所以就直接上關(guān)鍵代碼(因為不關(guān)鍵的和上面內(nèi)容一樣,哈哈)

3.1、類型不一致

實體類我們還是沿用 User;被映射對象 UserVO3 改為:

@Data @NoArgsConstructor @AllArgsConstructor @Builder public class UserVO3 {     private String id;     private String name;     // 實體類該屬性是String     private LocalDateTime createTime;     // 實體類該屬性是LocalDateTime     private String updateTime; }

那么我們定義的接口就要稍稍修改一下了:

@Mappings({             @Mapping(target = "createTime", expression = "java(com.java.mmzsblog.util.DateTransform.strToDate(source.getCreateTime()))"),     })     UserVO3 toConvertVO3(User source);      User fromConvertEntity3(UserVO3 userVO3);

上面 expression 指定的表達(dá)式內(nèi)容如下:

public class DateTransform {     public static LocalDateTime strToDate(String str){         DateTimeFormatter df = DateTimeFormatter.ofPattern("yyy-MM-dd HH:mm:ss");         return LocalDateTime.parse("2018-01-12 17:07:05",df);     }  }

通過IDE的反編譯功能查看編譯后的實現(xiàn)類,結(jié)果是這樣子的:

分析mybatis中@Mapper注解的componentModel屬性

從圖中我們可以看到,編譯時使用了expression中定義的表達(dá)式對目標(biāo)字段 createTime 進(jìn)行了轉(zhuǎn)換;然后你還會發(fā)現(xiàn) updateTime  字段也被自動從 LocalDateTime 類型轉(zhuǎn)換成了 String 類型。

阿粉小結(jié):

當(dāng)字段類型不一致時,以下的類型之間是  mapstruct 自動進(jìn)行類型轉(zhuǎn)換的:

1、基本類型及其他們對應(yīng)的包裝類型。此時 mapstruct 會自動進(jìn)行拆裝箱。不需要人為的處理

2、基本類型的包裝類型和string類型之間

除此之外的類型轉(zhuǎn)換我們可以通過定義表達(dá)式來進(jìn)行指定轉(zhuǎn)換。

3.2、字段名不一致

實體類我們還是沿用 User;被映射對象 UserVO4 改為:

@Data @NoArgsConstructor @AllArgsConstructor @Builder public class UserVO4 {     // 實體類該屬性名是id     private String userId;     // 實體類該屬性名是name     private String userName;     private String createTime;     private String updateTime; }

那么我們定義的接口就要稍稍修改一下了:

@Mappings({             @Mapping(source = "id", target = "userId"),             @Mapping(source = "name", target = "userName")     })     UserVO4 toConvertVO(User source);          User fromConvertEntity(UserVO4 userVO4);

通過IDE的反編譯功能查看編譯后的實現(xiàn)類,編譯后的結(jié)果是這樣子的:

分析mybatis中@Mapper注解的componentModel屬性

小結(jié):

當(dāng)字段名不一致時,通過使用 @Mappings 注解指定對應(yīng)關(guān)系,編譯后即可實現(xiàn)對應(yīng)字段的賦值。

很明顯, mapstruct  通過讀取我們配置的字段名對應(yīng)關(guān)系,幫我們把它們賦值在了相對應(yīng)的位置上,可以說是相當(dāng)優(yōu)秀了,但這也僅僅是優(yōu)秀,而更秀的還請繼續(xù)往下看:

3.3、屬性是枚舉類型

實體類我們還是改用 UserEnum:

@Data @NoArgsConstructor @AllArgsConstructor @Builder public class UserEnum {     private Integer id;     private String name;     private UserTypeEnum userTypeEnum; }

被映射對象 UserVO5 改為:

@Data @NoArgsConstructor @AllArgsConstructor @Builder public class UserVO5 {     private Integer id;     private String name;     private String type; }

枚舉對象是:

@Getter @AllArgsConstructor public enum UserTypeEnum {     Java("000", "Java開發(fā)工程師"),     DB("001", "數(shù)據(jù)庫管理員"),     LINUX("002", "Linux運維員");          private String value;     private String title;  }

那么我們定義的接口還是照常定義,不會受到它是枚舉就有所變化:

@Mapping(source = "userTypeEnum", target = "type")     UserVO5 toConvertVO5(UserEnum source);      UserEnum fromConvertEntity5(UserVO5 userVO5);

通過IDE的反編譯功能查看編譯后的實現(xiàn)類,編譯后的結(jié)果是這樣子的:

分析mybatis中@Mapper注解的componentModel屬性

很明顯, mapstruct  通過枚舉類型的內(nèi)容,幫我們把枚舉類型轉(zhuǎn)換成字符串,并給type賦值,可謂是小心使得萬年船啊。

到此,相信大家對“分析mybatis中@Mapper注解的componentModel屬性”有了更深的了解,不妨來實際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI