广告
返回顶部
首页 > 资讯 > 前端开发 > node.js >分析mybatis中@Mapper注解的componentModel属性
  • 140
分享到

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

2024-04-02 19:04:59 140人浏览 泡泡鱼
摘要

本篇内容主要讲解“分析mybatis中@Mapper注解的componentModel属性”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析mybatis中@M

本篇内容主要讲解“分析mybatis中@Mapper注解的componentModel属性”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析mybatis中@Mapper注解的componentModel属性”吧!

一、准备工作

1.1、了解@Mapper 注解

从 mybatis3.4.0 开始加入的 @Mapper 注解,目的就是为了不再写mapper映射文件。

我们只需要在 dao 层定义的接口上使用注解就可以实现sql语句的编写,例如:

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

如上就是一个简单的使用,虽然简单,但也确实体现出了这个注解的优越性,至少少写了一个xml文件。

所以我就只是想说下 @Mapper 注解的  componentModel 属性,componentModel 属性用于指定自动生成的接口实现类的组件类型,这个属性支持四个值:

  • default: 这是默认的情况,mapstruct 不使用任何组件类型,  可以通过Mappers.getMapper(Class)方式获取自动生成的实例对象。

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

  • spring: 生成的实现类上面会自动添加一个@Component注解,可以通过Spring的 @Autowired方式进行注入

  • jsr330: 生成的实现类上会添加@javax.inject.Named 和@Singleton注解,可以通过 @Inject注解获取

1.2、依赖包

首先需要把依赖包导入,主要由两个包组成:

  • org.mapstruct:mapstruct:包含了一些必要的注解,例如@Mapping。r若我们使用的jdk版本高于1.8,当我们在pom里面导入依赖时候,建议使用坐标是:org.mapstruct:mapstruct-jdk8,这可以帮助我们利用一些Java8的新特性。

  • org.mapstruct:mapstruct-processor:注解处理器,根据注解自动生成mapper的实现。

<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>

好了,准备工作做完了,接下来我们就看看巧媳妇儿巧在什么地方吧。

二、先简单玩一把

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、定义接口:

当实体类和被映射对象属性相同或者被映射对象属性值少几个时:

@Mapper(componentModel = "spring") public interface UserCovertBasic {     UserCovertBasic INSTANCE = Mappers.getMapper(UserCovertBasic.class);           UserVO1 toConvertVO1(User source);     User fromConvertEntity1(UserVO1 userVO1);           UserVO2 toConvertVO2(User source); }

从上面的代码可以看出:接口中声明了一个成员变量INSTANCE,母的是让客户端可以访问 Mapper 接口的实现。

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转换回实体类user:" + UserCovertBasic.INSTANCE.fromConvertEntity1(userVO1));         // 输出转换结果         objectList.add("userVO2:" + " | " + UserCovertBasic.INSTANCE.toConvertVO2(user));         // 使用BeanUtils         UserVO2 userVO22 = new UserVO2();         BeanUtils.copyProperties(user, userVO22);         objectList.add("userVO22:" + " | " + userVO22);          return objectList;     } }

2.4、查看编译结果

通过IDE的反编译功能查看编译后自动生成 UserCovertBasic  的实现类 UserCovertBasicImpl ,内容如下:

@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、浏览器查看结果

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

好了,一个流程就走完了,是不是感觉贼简单呢?

而且呀,阿粉温馨提醒:如果是要转换一个集合的话,只需要把这里的实体类换成集合就行了,例如:

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

三、不简单的情况

上面已经把整个流程都给过了一遍了,相信大家对 mapstruct  也有了一个基础的了解了,所以接下来的情况我们就不展示全部代码了,毕竟篇幅也有限,所以就直接上关键代码(因为不关键的和上面内容一样,哈哈)

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 指定的表达式内容如下:

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的反编译功能查看编译后的实现类,结果是这样子的:

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

从图中我们可以看到,编译时使用了expression中定义的表达式对目标字段 createTime 进行了转换;然后你还会发现 updateTime  字段也被自动从 LocalDateTime 类型转换成了 String 类型。

阿粉小结:

当字段类型不一致时,以下的类型之间是  mapstruct 自动进行类型转换的:

1、基本类型及其他们对应的包装类型。此时 mapstruct 会自动进行拆装箱。不需要人为的处理

2、基本类型的包装类型和string类型之间

除此之外的类型转换我们可以通过定义表达式来进行指定转换。

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的反编译功能查看编译后的实现类,编译后的结果是这样子的:

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

小结:

当字段名不一致时,通过使用 @Mappings 注解指定对应关系,编译后即可实现对应字段的赋值。

很明显, mapstruct  通过读取我们配置的字段名对应关系,帮我们把它们赋值在了相对应的位置上,可以说是相当优秀了,但这也仅仅是优秀,而更秀的还请继续往下看:

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开发工程师"),     DB("001", "数据库管理员"),     linux("002", "Linux运维员");          private String value;     private String title;  }

那么我们定义的接口还是照常定义,不会受到它是枚举就有所变化:

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

通过IDE的反编译功能查看编译后的实现类,编译后的结果是这样子的:

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

很明显, mapstruct  通过枚举类型的内容,帮我们把枚举类型转换成字符串,并给type赋值,可谓是小心使得万年船啊。

到此,相信大家对“分析mybatis中@Mapper注解的componentModel属性”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: 分析mybatis中@Mapper注解的componentModel属性

本文链接: https://www.lsjlt.com/news/85105.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • 分析mybatis中@Mapper注解的componentModel属性
    本篇内容主要讲解“分析mybatis中@Mapper注解的componentModel属性”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“分析mybatis中@M...
    99+
    2022-10-19
  • MyBatis通用Mapper@Table注解使用的注意点分析
    本篇内容介绍了“MyBatis通用Mapper@Table注解使用的注意点分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!MyBatis通...
    99+
    2023-06-21
  • 原理分析Java Mybatis中的Mapper
    目录准备1.pom文件2.user类-数据库3.实体类4.dao 层5.Mapper 文件源码分析1.断点2.查看源码总结准备 1.pom文件 <dependencies&g...
    99+
    2022-11-12
  • MyBatis中Mapper生效的示例分析
    小编给大家分享一下MyBatis中Mapper生效的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、MyBatis基本使用一切都从最简单的开始,所以先来...
    99+
    2023-06-20
  • MyBatis中Mapper的注入问题详解
    在 SpringBoot 体系中,MyBatis 对 Mapper 的注入常见的方式我知道的有 2 种: 1、@MapperScan MapperScan 类是 mybatis-sp...
    99+
    2022-11-12
  • MyBatis Mapper中的通用example举例分析
    本篇内容介绍了“MyBatis Mapper中的通用example举例分析”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!MyBatis通用M...
    99+
    2023-06-22
  • mybatis属性的示例分析
    这篇文章给大家分享的是有关mybatis属性的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。前言MyBatis是基于“数据库结构不可控”的思想建立的,也就是我们希望数据库...
    99+
    2022-10-18
  • 如何进行Java Mybatis中的Mapper原理分析
    如何进行Java Mybatis中的Mapper原理分析,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。准备1.pom文件 <depen...
    99+
    2023-06-26
  • 解析 MyBatis 中 Mapper 生效的来龙去脉
    目录一、MyBatis基本使用1.1 编写配置文件1.2 编写Mapper接口及测试方法1.3 结果二、源码分析2.1 通过配置文件构建出 SqlSessionFactory2.2 ...
    99+
    2022-11-12
  • Mybatis Mapper中多参数方法不使用@param注解报错的解决
    目录问题描述寻求解决方案寻找原因拓展延伸在使用低版本的Mybatis的时候,Mapper中的方法如果有多个参数时需要使用@param注解,才能在对应xml的sql语句中使用参数名称获...
    99+
    2022-11-12
  • 详解MyBatis中column属性的总结
    在MyBatis的映射中有column这么一个属性,我一直以为它映射的是数据库表中的列名,但经过学习发现他似乎映射的是SQL语句中的列名,或者说是查询结果所得到的表的列名。 下面我们...
    99+
    2022-11-13
  • Spring注解驱动开发之属性赋值的示例分析
    这篇文章给大家分享的是有关Spring注解驱动开发之属性赋值的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。一、@Value注解在Person的属性上使用@Value注解指定注入值public ...
    99+
    2023-06-15
  • Mybatis中resultMap的Colum和property属性详解
    目录resultMap的Colum和property属性1: resultMap标签2:使用情况2.1 简单查询2.2 一对一2.3 一对多resultMap对column和prop...
    99+
    2022-11-12
  • vuex中的state属性解析
    目录state属性介绍state的使用扩展vuex的State单一状态树在Vue组件中获得 Vuex 状态mapState辅助函数state属性介绍 state属性是Vuex中用于存...
    99+
    2022-11-13
  • mybatis中注解与xml配置的对应关系和对比分析
    注解与xml配置的对应关系 mybatis中注解就是简单不需要写配置文件,适合简单的数据处理,理解起来比较容易,不动态生成SQL时候可以用用。 需要绑定,有些时候不如配置文件,配置文...
    99+
    2022-11-12
  • 分析HTML5中download属性的应用
    本篇内容介绍了“分析HTML5中download属性的应用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!&...
    99+
    2022-10-19
  • canvas中globalCompositeOperation属性的示例分析
    这篇文章给大家分享的是有关canvas中globalCompositeOperation属性的示例分析的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。说明最早知道 canvas 的 globalCompositeO...
    99+
    2023-06-14
  • React中ref属性的示例分析
    这篇文章主要介绍了React中ref属性的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。概述首先,Refs 和 ref 是两个概念,Refs 是 React 提供的可...
    99+
    2023-06-15
  • Spring中Transactional属性的示例分析
    小编给大家分享一下Spring中Transactional属性的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!一、Transactional声明式事务管理...
    99+
    2023-06-15
  • C#中属性和特性的示例分析
    这篇文章主要介绍C#中属性和特性的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!首先要说的是,可能一些刚接触C#的朋友常常容易把属性(Property)跟特性(Attribute)弄混淆,其实这是两种不同的东...
    99+
    2023-06-17
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作