【mybatis】objectwrapper解读

简介

在 MyBatis 中,ObjectWrapper 是一个关键的接口,用于详细封装了对象的属性信息。ObjectWrapper 主要用于内部操作,它抽象了对象的属性操作,使得 MyBatis 能够统一处理原生类型、Bean 对象以及 Map 集合等。

类图展示

ObjectWrapper.png

主要功能

  1. 属性的获取与设置ObjectWrapper 提供了方法来获取和设置对象的属性值。这对于 MyBatis 在执行 SQL 语句时,动态地插入参数值或者将查询结果映射回对象是非常有用的。
  2. 集合操作的支持:对于 Map 类型或者集合类型的对象,ObjectWrapper 提供了方法来操作集合内的元素,包括获取指定键的值等。
  3. 复杂属性的处理ObjectWrapper 还能处理复杂的属性路径。例如,如果有一个属性路径是 someBean.somePropertyObjectWrapper 能够解析这个路径并获取或设置相应的属性值。

实现类

MyBatis 提供了几个 ObjectWrapper 的实现类,用于处理不同类型的对象:

  • **BeanWrapper**:用于处理 Java Bean 对象的包装器,通过反射机制访问对象的属性。
  • **MapWrapper**:用于处理 Map 类型对象的包装器,通过键值对来访问数据。
  • **CollectionWrapper**:尽管不直接实现 ObjectWrapper 接口,但 MyBatis 处理集合类型时有相关的机制,以支持集合的处理。

应用场景

ObjectWrapper 的设计主要是为了内部使用,以提供一种统一的方式来访问对象的属性,无论这些对象是普通的 Java Beans、Map 集合还是其他复杂的数据结构。这种机制极大地简化了 MyBatis 的参数映射和结果映射逻辑,使得开发者可以更加专注于 SQL 语句的编写,而不是数据的封装和解析过程。

在自定义类型处理器(Type Handler)或是高级映射配置时,了解 ObjectWrapper 的工作原理可以帮助开发者更好地控制 MyBatis 的行为,实现更加灵活和强大的数据操作。

ObjectWrapper 接口类的设计理念

封装性(Encapsulation)

ObjectWrapper 封装了对对象属性的操作,隐藏了具体的实现细节。这意味着,不论是操作 Java Bean、Map 还是其他任何复杂对象,对于使用者来说,都是通过一个统一的接口进行。这种封装性使得 MyBatis 的其余部分可以不用关心对象属性是如何被访问和修改的,从而降低了各个模块间的耦合度。

抽象性(Abstraction)

ObjectWrapper 作为一个高层次的抽象,定义了一套操作对象属性的通用方法。这种抽象使得 MyBatis 能够支持广泛的数据类型,而无需为每种数据类型编写特定的代码。通过抽象出一个统一的接口,MyBatis 可以轻松地扩展以支持新的对象类型,只需添加相应类型的 ObjectWrapper 实现即可。

单一职责原则(Single Responsibility Principle)

ObjectWrapper 的设计遵循了单一职责原则,即一个类应该只有一个引起变化的原因。ObjectWrapper 接口专注于对象属性的访问和操作,而不涉及其他逻辑,如 SQL 语句的构建、数据库连接的管理等。这使得 ObjectWrapper 及其实现类易于理解和维护。

开闭原则(Open/Closed Principle)

根据开闭原则,软件实体应该对扩展开放,对修改关闭。ObjectWrapper 接口的设计允许 MyBatis 在不修改已有代码的基础上扩展框架的功能。通过添加新的 ObjectWrapper 实现,可以支持新的数据类型或自定义的对象处理逻辑,而无需改动框架的核心部分。

策略模式(Strategy Pattern)

ObjectWrapper 的设计体现了策略模式的应用,其中 ObjectWrapper 接口定义了一组算法家族(在这里是对象属性的操作方法),而它的实现类则封装了这些算法的具体实现。这使得 ObjectWrapper 在运行时可以根据对象的类型选择合适的实现,从而改变对象属性的访问和操作行为。这种模式提高了代码的灵活性和可重用性。

BaseWrapper类解读

MyBatis 中的 BaseWrapper 类并不是直接暴露给终端用户的一个类,而是作为一个内部使用的基础类,提供了一些共通的功能和工具,供其子类如 BeanWrapperMapWrapperObjectWrapper 的实现类使用。BaseWrapper 主要是实现了 ObjectWrapper 接口的一些公共逻辑,以避免在每一个实现中重复相同的代码。它是一个抽象类,为处理对象属性的读取和设置提供了基础设施。

主要功能
  1. 属性表达式解析BaseWrapper 提供了解析复杂属性表达式的功能,例如嵌套属性和集合/数组元素的访问。这允许 MyBatis 在运行时动态地访问和修改对象的属性,即使这些属性是通过复杂的路径访问的。
  2. 通用属性访问:通过封装对反射 API 的调用,BaseWrapper 提供了一种相对简单的方式来读取和设置对象的属性值。这包括处理 Java Beans、Map 以及集合类型的对象。
  3. 缓存机制:为了提高性能,BaseWrapper 可能会实现一些缓存机制,例如缓存反射操作的结果(如方法、字段访问)。这样可以减少对相同属性的重复解析和访问开销。
  4. 类型转换和处理BaseWrapper 提供了类型转换的基础设施,以便在设置属性值时,能够将输入数据转换为目标属性的适当类型。这是通过 MyBatis 的类型处理器(TypeHandler)来实现的。
  5. 延迟加载支持:在一些情况下,BaseWrapper 可能会参与支持延迟加载(Lazy Loading)的逻辑,尽管这通常是在更高层次上处理的,但 BaseWrapper 提供的基础设施使得这种功能的实现变得可能。
应用场景

BaseWrapper 主要在 MyBatis 内部使用,作为一个工具类来支持更高层次的抽象,如 ObjectWrapper 的实现。它通过提供一组通用的工具和方法简化了对不同类型对象的操作,提高了 MyBatis 在处理复杂映射和动态 SQL 时的灵活性和效率。用户通常不需要直接与 BaseWrapper 交互,但理解其功能和作用可以帮助更好地理解 MyBatis 是如何在内部处理对象映射的。

类定义和构造函数
  • BaseWrapper 是一个抽象类,它实现了 ObjectWrapper 接口。
  • 它包含一个 protectedMetaObject 类型的成员变量 metaObjectMetaObject 是 MyBatis 中用于反射操作的核心类,提供了对对象属性的访问和修改功能。
  • 构造函数 BaseWrapper(MetaObject metaObject) 用于初始化 metaObject 成员变量。
方法解读
  • **resolveCollection(PropertyTokenizer prop, Object object)**** 方法**:用于处理集合对象。如果 PropertyTokenizername 属性为空字符串,表示直接返回输入对象;否则,通过 metaObject.getValue(prop.getName()) 获取属性值。这里的 PropertyTokenizer 是用于分析属性表达式的工具类。
  • **getCollectionValue(PropertyTokenizer prop, Object collection)**** 方法**:根据 PropertyTokenizer 中的索引,从集合对象中获取元素值。这个方法能够处理 MapList、数组以及基本类型数组(如 int[], char[] 等)。如果集合对象不是这些类型之一,则抛出 ReflectionException 异常。
  • **setCollectionValue(PropertyTokenizer prop, Object collection, Object value)**** 方法**:根据 PropertyTokenizer 中的索引,向集合对象中设置元素值。这个方法同样能够处理 MapList、数组以及基本类型数组。它根据集合的类型,将值 value 插入或替换到正确的位置。如果操作的目标不是这些集合类型之一,同样会抛出 ReflectionException 异常。

CollectionWrapper类解读

核心功能
  • 构造函数:接受一个 CustomCollection 类型的对象作为参数,并将其存储在 collection 成员变量中。这表明 CustomObjectWrapper 是专门为操作 CustomCollection 设计的。
  • **isCollection**** 方法**:返回 true,表明这个包装器封装的是一个集合对象。这是对 ObjectWrapper 接口的具体实现,指示 MyBatis 这个包装器处理的是集合类型的数据。
  • **add**** 方法和 **addAll** 方法**:这两个方法允许向 collection 成员变量中添加单个元素或多个元素。这表明 CustomObjectWrapper 提供了基本的集合操作功能,使得可以通过这个包装器修改底层集合。
未实现的方法

代码中有多个方法标记为 “Not Implemented”,包括 getsetfindPropertygetGetterNamesgetSetterNamesgetSetterTypegetGetterTypehasSetterhasGetterinstantiatePropertyValue。这些方法的空实现表明 CustomObjectWrapper 在当前形态下不支持这些操作。这可能是因为这些操作对于 CustomCollection 类型的数据不是必需的,或者开发者打算在未来根据需要实现它们。

设计意图

CustomObjectWrapper 的设计意图是提供一个机制,通过它 CustomCollection 类型的对象可以在 MyBatis 中使用,同时提供了一种方式来扩展 MyBatis 默认的对象包装行为。通过实现 ObjectWrapper 接口,CustomObjectWrapper 使得 MyBatis 能够对 CustomCollection 进行操作,如添加元素,而不必担心其他更复杂的属性操作。

使用场景

这种自定义包装器的一个潜在使用场景是在 MyBatis 的 ORM 映射中,当需要处理非标准集合类型时。例如,如果 CustomCollection 提供了一些特殊的行为或优化,那么使用 CustomObjectWrapper 可以确保这些特性能够在 MyBatis 操作中得到支持和利用。
总的来说,CustomObjectWrapper 提供了一个框架,用于将自定义集合类型集成到 MyBatis 中,尽管它需要进一步的实现来支持所有的 ObjectWrapper 接口方法。这种设计允许开发者根据特定需求定制 MyBatis 的行为,从而提高框架的灵活性和可用性。

MapWrapper类解读

这段代码定义了 类,它继承自 BaseWrapper 并实现了 ObjectWrapper 接口,专门用于处理 Java Map 类型的对象。MapWrapper 类提供了一系列操作,使得 MyBatis 能够通过反射机制访问和修改 Map 对象的内容。以下是对该类关键功能和方法的详细解释:

构造函数
  • MapWrapper(MetaObject metaObject, Map<String, Object> map):接受一个 MetaObject 和一个 Map<String, Object> 作为参数。metaObject 用于访问对象的元数据,map 是这个 MapWrapper 实例将要操作的 Map 对象。
方法实现
  • **get(PropertyTokenizer prop)**:如果属性名(prop)带有索引,则解析并返回集合中的相应元素;如果没有索引,则直接从 Map 中获取对应的值。
  • **set(PropertyTokenizer prop, Object value)**:如果属性名(prop)带有索引,则在集合中设置相应的元素;如果没有索引,则在 Map 中设置对应的值。
  • **findProperty(String name, boolean useCamelCaseMapping)**:直接返回属性名,因为 Map 的属性查找不需要转换或处理。
  • **getGetterNames()**** 和 ****getSetterNames()**:返回 Map 中所有键的数组,表示所有可用的getter和setter方法名。
  • **getSetterType(String name)**** 和 ****getGetterType(String name)**:返回给定属性名对应值的类型。如果 Map 中包含该属性,则返回其值的类类型;否则,默认为 Object 类型。
  • **hasSetter(String name)**hasGetter(String name)**:对于 Map 类型,理论上所有的属性名都可以有setter和getter,因为可以在 Map 中插入或查询任何键。
  • **instantiatePropertyValue(String name, PropertyTokenizer prop, ObjectFactory objectFactory)**:用于动态创建并初始化一个属性值。在这里,它创建了一个新的 HashMap 并将其设置为指定属性的值。
  • **isCollection()**:返回 false,因为 Map 不被视为 Collection 类型。
  • **add(Object element)**** 和 ****addAll(List<E> element)**:抛出 UnsupportedOperationException,因为对于 Map 类型的数据结构,单独添加元素的操作没有定义。
设计意图

MapWrapper 类的设计主要是为了让 MyBatis 能够更灵活地处理 Map 类型的对象。通过实现 ObjectWrapper 接口,它提供了一种标准化的方式来访问和修改 Map 中的数据,无论是单个值还是集合类型的元素。这种封装使得 MyBatis 在执行 SQL 操作时,能够方便地映射结果集到 Map,或者将 Map 中的数据用作查询的参数。

使用场景

在 MyBatis 中,MapWrapper 被用来处理那些需要动态查询参数或希望将查询结果映射到 Map 对象的场景。通过 MapWrapper,用户可以灵活地操作 Map,无需担心如何将数据库的列映射到 Map 的键上。这在处理动态查询或构建动态响应时尤其有用。

BeanWrapper类解读

这段代码定义了 BeanWrapper 类,它是 MyBatis 反射模块中的一个关键部分,用于封装和操作 Java Bean 对象。BeanWrapper 继承自 BaseWrapper 并实现了 ObjectWrapper 接口,提供了一系列方法来访问和修改 Java Bean 的属性。以下是对该类关键功能和方法的详细解释:

构造函数
  • BeanWrapper(MetaObject metaObject, Object object):构造函数接收一个 MetaObject 和一个 Java 对象。MetaObject 是 MyBatis 反射模块的核心,用于访问对象的元数据,而 object 是被封装的 Java Bean 对象。metaClass 是通过 MetaClass.forClass(object.getClass(), metaObject.getReflectorFactory()) 创建的,用于访问 Java Bean 的元数据,如属性的 getter 和 setter 方法。
主要方法
  • **get(PropertyTokenizer prop)**:根据 PropertyTokenizer 提供的属性名(可能包含索引或嵌套路径)获取属性值。如果属性名带有索引,则处理为集合或数组的访问;否则,通过 getBeanProperty 方法直接访问 Bean 的属性。
  • **set(PropertyTokenizer prop, Object value)**:根据 PropertyTokenizer 设置属性值。如果属性名带有索引,则处理为集合或数组的修改;否则,通过 setBeanProperty 方法修改 Bean 的属性。
  • **getBeanProperty**** 和 ****setBeanProperty**:这两个私有方法分别用于获取和设置 Java Bean 的属性值。它们通过 MetaClass 获取属性的 getter 或 setter Invoker,然后反射调用相应的方法。
  • 属性查找和类型获取方法:如 findPropertygetSetterTypegetGetterType 等方法,这些方法通过 MetaClass 实现,用于查找属性名、获取属性的类型等。
  • **hasSetter**** 和 ****hasGetter**:检查 Java Bean 是否有指定属性的 setter 或 getter 方法。
  • **instantiatePropertyValue**:如果需要,此方法用于实例化属性值。它通过 ObjectFactory 创建属性类型的新实例,并将其设置为属性值。
  • 集合操作相关方法isCollectionaddaddAll 方法在 BeanWrapper 中不支持,因为它封装的是单个 Java Bean 对象而非集合。
设计意图

BeanWrapper 的设计主要目的是封装对 Java Bean 对象的反射操作,提供统一的接口来访问和修改属性,支持嵌套属性和集合属性的操作。通过 MetaClass 和反射,BeanWrapper 能够动态地访问 Java Bean 的属性,这对于 MyBatis 在执行 SQL 语句时动态绑定参数值、映射查询结果到 Java 对象非常重要。

使用场景

在 MyBatis 的 ORM 映射过程中,BeanWrapper 被用于处理 Java Bean 类型的参数和结果对象。它允许 MyBatis 动态地访问和修改对象的属性,支持复杂的嵌套属性和集合属性的操作,从而使得 MyBatis 能够灵活地将数据库查询结果映射到 Java 对象,以及将 Java 对象作为查询参数。

CustomBeanWrapper类解读

类定义
  • CustomBeanWrapper 继承自 BeanWrapper 类,这意味着它继承了所有的公共方法和属性,使得可以覆盖(Override)或添加新的行为和功能。
构造函数
  • CustomBeanWrapper(MetaObject metaObject, Object object):构造函数接收两个参数:一个 MetaObject 和一个 Java 对象(object)。这与父类 BeanWrapper 的构造函数签名一致。在构造函数体中,它通过调用 super(metaObject, object) 将这些参数传递给父类的构造函数。
设计意图
  • 扩展 **BeanWrapper** 功能:虽然这个示例中 CustomBeanWrapper 没有实现任何新的功能或覆盖任何父类方法,实际使用时,你可以在这个类中添加新的方法或覆盖现有方法,以实现特定的行为或处理逻辑。例如,可以覆盖 getset 方法来添加日志记录、错误处理、属性值转换等自定义行为。
使用场景
  • 自定义对象包装器:如果你在使用 MyBatis 时有特殊需求,比如需要对某些 Java Bean 的属性访问或修改进行特殊处理,可以通过创建自定义的 BeanWrapper 来实现。这样可以保留 MyBatis 原有的映射和参数处理机制的同时,添加或修改特定的行为。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/756236.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue组件封装方案对比——v-if方式与内置component方式

近期在准备搭建一个通用组件库&#xff0c;而公司现有的各个系统也已有自己的组件库只是没抽离出来&#xff0c;但是目前有两套不同的组件封装方案&#xff0c;所以对于方案的选择比较困惑&#xff0c;于是对两种方式进行了对比&#xff0c;结合网上找到的一些开源组件库进行分…

抖音店铺规划运营管理计划数据分析工作表

【干货资料持续更新&#xff0c;以防走丢】 抖音店铺规划运营管理计划数据分析表 部分资料预览 资料部分是网络整理&#xff0c;仅供学习参考。 抖音小店运营规划工作表格&#xff08;完整资料包含以下内容&#xff09; 目录 1. 抖店运营管理决策表&#xff1a;该表格用于记…

三维指静脉生物识别成像设备设计和多视图验证研究

文章目录 三维指静脉生物识别成像设备设计和多视图验证研究总结摘要介绍多视角指静脉识别模型结构内容特征编码Transformer(CFET)主导特征选择模块(DFSM) 实验和结果数据集实施细节视角研究池化层的作用消融实验和SOTA方法比较 论文: Study of 3D Finger Vein Biometrics on I…

Linux——进程通信(三)命名管道

前言 我们在之前学习了匿名管道与匿名管道的应用——进程池&#xff0c;但是匿名管道的通信&#xff0c;需要有血缘关系的进程&#xff08;通过fork创建的进程们&#xff09;&#xff0c;如果我想让两个毫不相干的进程进行通信&#xff0c;可以采样命名管道的方式&#xff08;…

Go语言中的锁与管道的运用

目录 1.前言 2.锁解决方案 3.管道解决方案 4.总结 1.前言 在写H5小游戏的时候&#xff0c;由于需要对多个WebSocket连接进行增、删、查的管理和对已经建立连接的WebSocket通过服务端进行游戏数据交换的需求。于是定义了一个全局的map集合进行连接的管理&#xff0c;让所有…

80后深圳设计师原创设计 妙解中小学生午休难题

3月17日至21日&#xff0c;深圳国际智能家居博览会在宝安国际会展中心举办。智慧校园展区成为焦点&#xff0c;吸引了众多目光。智荟康科技展出的午休课桌椅产品&#xff0c;为解决中小学生“趴睡”问题而研发&#xff0c;创新实用&#xff0c;在智慧校园展区中备受好评。 &…

Leetcode 79. 单词搜索

心路历程&#xff1a; 做完这道题才发现是回溯&#xff0c;一开始想的是递归&#xff0c;判断完第i个字符后&#xff0c;只需要挨个判断第i1个字符在不在第i个字符的邻域。后来发现由于不能重复使用元素&#xff0c;所以需要维护一个visited列表&#xff0c;并且在遍历所有可能…

蓝桥杯---代分数

import java.util.Scanner;public class top4 {//全排列分数的那个题目//首先进行n个数的全排列//然后将这n个数字拆分为3个数字&#xff0c;即插入两个板子//然后判断等式是否成立&#xff08;判断条件就是在if里面去进行相关的判断是吗&#xff1f;&#xff1f;&#xff09;s…

Spring项目部署到linux上

目录 一、环境配置 1、数据准备 2、程序配置文件修改 二、打包项目 三、上传jar包到服务器 四、开放端口号 五、运行程序 六、查看日志 七、常见问题 1、服务未启动 2、端口号已被占用 3、端口未开放 一、环境配置 1、数据准备 需要先在linux环境下的数据库中创建…

Go语言之函数、方法、接口

一、函数 函数的基本语法&#xff1a; func 函数名&#xff08;形参列表&#xff09;&#xff08;返回值列表&#xff09; {执行语句...return 返回值列表 } 1.形参列表&#xff1a;表示函数的输入 2.函数中的语句&#xff1a;表示为了实现某一功能的代码块 3.函数可以有返回…

【Linux】进程排队的理解进程状态的表述僵尸进程和孤儿进程的理解

一、进程排队的理解 进程不是一直运行的&#xff0c;进程可能会在等待某种软硬件资源。即使把进程加载到CPU中&#xff0c;也不是一直会运行的。而进程排队&#xff0c;一定是在等待某种软硬件资源&#xff08;可以是CPU&#xff0c;键盘&#xff0c;磁盘&#xff0c;网卡等等设…

rabbitmq-spring-boot-start配置使用手册

rabbitmq-spring-boot-start配置使用手册 文章目录 1.yaml配置如下2.引入pom依赖如下2.1 引入项目resources下libs中的jar包依赖如下2.2引入maven私服依赖如下 3.启动类配置如下4.项目中测试发送消息如下5.项目中消费消息代码示例6.mq管理后台交换机队列创建及路由绑定关系如下…

深入探讨Python中的文件操作与文件IO操作【第141篇—Python实现】

&#x1f47d;发现宝藏 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 深入探讨Python中的文件操作与文件IO操作 在Python编程中&#xff0c;文件操作和文件IO操作…

ES集群和分片以及脑裂

文章目录 概要一、概念二、节点角色三、master节点脑裂四、参考 概要 在工作中不可避免会用到ES&#xff0c;而用到ES就不得使用其集群模式了。 单节点的话不得不面临两个重大缺陷&#xff1a;单点故障&#xff08;高可用&#xff09;和海量数据存储搜索。 ES通过集群模式解决…

JSR规范系列(6)——Jakarta EE 9 规范

Jakarta EE 9 规范 Jakarta EE 9 规范 JSR规范系列&#xff08;1&#xff09;——Java版本、JSR规范和JCP社区流程概述 JSR规范系列&#xff08;2&#xff09;——JavaSE规范、JavaEE规范、JSR规范全面整理——截止201908 JSR规范系列&#xff08;3&#xff09;——Java EE 6规…

● 647. 回文子串 ● 516.最长回文子序列 ● 动态规划总结篇

● 647. 回文子串 1.dp数组含义。 之前的题目&#xff0c;差不多都是求什么就怎么定义dp数组&#xff0c;最后返回dp的最后一个元素。但是这里如果定义一维数组dp[i]是[0,i]范围的回文子串的个数的话&#xff0c;怎么根据dp[i-1]得到dp[i]&#xff1f;发现很难找到递归关系…

Linux之gcc_makefile

一、提要 1. 预处理&#xff08;进行宏替换) 2. 编译&#xff08;生成汇编) 3. 汇编&#xff08;生成机器可识别代码&#xff09; 4. 链接&#xff08;生成可执行文件或库文件) 五六十年代&#xff0c;我们编程大多是二进制编程&#xff0c;也就是使用打孔纸带喂给机器 再往后&…

118.Qt入门,实现一个图片查看软件

需要用到的控件 QLabelQLineEditQPushButton 需要实现的功能 打开目录选择图片显示图片的名字显示图片 QLabel基本用法 void setText(const QString &);//设置文本QString text() const;//获取文本void setPixmap(const QPixmap &);设置大小 使用父类QWidget的方法设置…

窗口函数(sample database classicmodels _No.8 )

窗口函数&#xff08;sample database classicmodels _No.8 &#xff09; 准备工作&#xff0c;可以去下载 classicmodels 数据库具体如下 点击&#xff1a;classicmodels 也可以去 下面我的博客资源下载 https://download.csdn.net/download/tomxjc/88685970 文章目录 窗口函…

什么品牌洗地机清洁效果最好?洗地机品牌十大排名:前四名口碑公认

有使用过洗地机的朋友&#xff0c;相信对此都深有感触&#xff0c;洗地机的一洗一吸&#xff0c;清洁效果非常棒&#xff0c;地面的污渍、垃圾、粉尘都坚持不了几秒钟&#xff0c;分分钟可以让家里地面焕然一新&#xff0c;简直不要太香。但是&#xff0c;洗地机那么多&#xf…