Mybatis框架之模板方法模式 (Template Method Pattern)
MyBatis 中也使用到了 模板方法模式 (Template Method Pattern),主要体现在 执行 SQL 语句的流程控制 上。模板方法模式允许 MyBatis 定义数据库操作的标准流程,并允许子类或特定实现类去实现某些步骤。这种模式使得 MyBatis 能够在处理不同类型的 SQL 操作(如查询、插入、更新、删除)时保持整体流程的一致性,同时具备灵活性去处理每种操作的具体细节。
1. 什么是模板方法模式 (Template Method Pattern)?
模板方法模式 是一种行为设计模式,它定义了一个操作中的算法骨架,而将某些步骤的实现延迟到子类中。通过这种方式,模板方法模式允许子类在不改变算法结构的前提下重新定义算法中的某些步骤。
模板方法模式的特点:
- 算法骨架:定义操作的基本步骤,且步骤的执行顺序是固定的。
- 延迟实现:某些具体步骤的实现被延迟到子类中,允许子类提供自己的实现。
- 代码复用:通过抽象类实现通用的逻辑,从而减少重复代码。
2. MyBatis 中模板方法模式的应用
在 MyBatis 中,模板方法模式的主要应用场景是 执行 SQL 语句的核心流程。MyBatis 使用模板方法模式来定义执行 SQL 的标准流程(如查询、插入、更新、删除),并允许不同的 Mapper 操作去实现各自的 SQL 逻辑。
MyBatis 的 Executor 类及其子类是模板方法模式的典型实现。Executor 是 MyBatis 中执行 SQL 语句的核心组件,通过模板方法模式来管理数据库操作的整个流程。
3. MyBatis 模板方法模式的实现流程
3.1 Executor 接口和 BaseExecutor 类
Executor接口:定义了 MyBatis 中执行操作的通用方法,如query、update等。BaseExecutor类:实现了Executor接口中的模板方法,同时定义了操作的标准流程。- 例如:查询时,
BaseExecutor定义了一个通用的查询模板方法,包含缓存检查、执行查询、缓存结果等步骤。
- 例如:查询时,
3.2 MyBatis 中模板方法的核心逻辑
以 查询操作 为例,MyBatis 中的查询操作遵循以下模板方法流程:
- 检查是否启用 一级缓存。
- 如果缓存命中,则直接返回缓存结果。
- 否则,调用子类的方法执行数据库查询。
- 将查询结果存入一级缓存。
- 返回查询结果。
4. 实际代码示例
为了更好地理解 MyBatis 中的模板方法模式,下面以 MyBatis 的 Executor 机制为例进行讲解。
4.1 Executor 接口
public interface Executor {// 查询方法<E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler);// 更新方法(包括插入、更新、删除)int update(MappedStatement ms, Object parameter);// 关闭 Executorvoid close();
}
4.2 BaseExecutor 抽象类(模板方法模式的核心)
public abstract class BaseExecutor implements Executor {private Cache localCache = new Cache();@Overridepublic <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) {// Step 1: 先从一级缓存中查找List<E> list = localCache.getObject(ms.getId());if (list != null) {return list; // 如果缓存命中,则直接返回}// Step 2: 缓存未命中,执行数据库查询list = doQuery(ms, parameter, rowBounds, resultHandler);// Step 3: 将结果存入一级缓存localCache.putObject(ms.getId(), list);return list; // 返回查询结果}// 定义了一个抽象方法,由子类实现具体的查询逻辑protected abstract <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler);
}
4.3 SimpleExecutor 子类(实现具体查询操作)
public class SimpleExecutor extends BaseExecutor {@Overrideprotected <E> List<E> doQuery(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) {// 这里是执行具体的 SQL 查询逻辑StatementHandler handler = new StatementHandler();return handler.query(ms, parameter, rowBounds, resultHandler);}
}
5. 模板方法模式在 MyBatis 中的执行流程
- 用户通过 MyBatis
SqlSession调用 Mapper 接口的查询方法。 SqlSession调用Executor.query()方法。Executor.query()方法在BaseExecutor中被定义,它遵循以下流程:- 检查一级缓存是否命中。
- 如果缓存未命中,则调用
doQuery()方法。 doQuery()方法在SimpleExecutor中实现,负责执行真正的 SQL 查询。- 将查询结果存入缓存,并返回给用户。
6. 模板方法模式的优势
- 代码复用:模板方法模式在
BaseExecutor中封装了通用的查询流程,使得不同的Executor子类可以复用这些逻辑。 - 解耦和扩展性:通过定义抽象方法(如
doQuery()),模板方法模式允许子类实现自己的具体逻辑,而不必改变整体流程。 - 一致性:模板方法确保了所有的查询操作都遵循相同的流程,提高了一致性。
7. 模板方法模式的不足
- 继承的局限:由于模板方法模式依赖于继承,所有的子类都必须是抽象类的子类,这限制了类的灵活性。
- 增加复杂度:模板方法模式可能会增加类的层次和复杂度,尤其是在流程较为复杂的情况下。
8. 总结
MyBatis 中的模板方法模式主要体现在 Executor 的设计上,通过定义标准化的数据库操作流程(如查询和更新),确保不同的执行器遵循一致的操作步骤。模板方法模式使 MyBatis 能够有效地复用代码,并通过子类灵活地实现特定操作。这种设计不仅提高了代码的可维护性和可读性,还增强了系统的扩展性。
相关文章:
Mybatis框架之模板方法模式 (Template Method Pattern)
MyBatis 中也使用到了 模板方法模式 (Template Method Pattern),主要体现在 执行 SQL 语句的流程控制 上。模板方法模式允许 MyBatis 定义数据库操作的标准流程,并允许子类或特定实现类去实现某些步骤。这种模式使得 MyBatis 能够在处理不同类型的 SQL 操…...
【进阶系列】python简单爬虫实例
python有一个很强大的功能就是爬取网页的信息,这里是CNBlogs 网站,我们将以此网站为实例,爬取指定个页面的大标题内容。代码如下: 首先是导入库: # 导入所需的库 import requests # 用于发送HTTP请求 from bs4 impor…...
️虚拟机配置NAT和Bridge模式
虚拟机的网络配置 桥接 通过使用物理机网卡 具有单独ip NAT 把物理机为路由器进行上网 NAT模式: 所谓nat模式,就是虚拟系统会通过宿主机的网络来访问外网,而这里的宿主机相当于有两个网卡,一个是真实网卡,一个是虚拟…...
解决Spring Boot整合Redis时的连接问题
前言 在使用Spring Boot整合Redis的过程中,经常会遇到连接问题,尤其是当Redis服务部署在远程服务器上时。 问题描述 当你尝试连接到Redis服务器时,可能会遇到以下错误: org.springframework.data.redis.connection.PoolExcept…...
109. UE5 GAS RPG 实现检查点的存档功能
在这一篇文章里,我们接着实现存档的功能,保存当前玩家的生成位置,游戏里有很多中方式去实现玩家的位置存储,这里我们采用检查点的方式,当玩家接触到当前检查点后,我们可以通过检查点进行保存玩家的状态&…...
springboot005基于springboot学生心理咨询评估系统得设计与实现。
项目描述 临近学期结束,还是毕业设计,你还在做java程序网络编程,期末作业,老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下,你想解决的问…...
ESC算法/逃生:一种基于人群疏散行为的优化方法
文章介绍了一种有用的算法,称为逃生或逃生算法(ESC),受人群疏散行为的启发,用于解决现实世界的案例和基准问题。ESC算法模拟了疏散过程中人群的行为,其中人群在探索阶段被分为平静、羊群和恐慌组࿰…...
构建安全的数据库环境:群晖NAS安装MySQL和phpMyAdmin详细步骤
文章目录 前言1. 安装MySQL2. 安装phpMyAdmin3. 修改User表4. 本地测试连接MySQL5. 安装cpolar内网穿透6. 配置MySQL公网访问地址7. 配置MySQL固定公网地址8. 配置phpMyAdmin公网地址9. 配置phpmyadmin固定公网地址 前言 本文将详细讲解如何在群晖NAS上安装MySQL及其数据库管理…...
【人工智能】深入理解图神经网络(GNN):用Python实现社交网络节点分类与分子结构分析
解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 图神经网络(Graph Neural Network, GNN)是近年来在深度学习领域迅速发展的新兴方向,主要用于处理图结构数据。GNN在社交网络分析、化学分…...
Qt 日志文件的滚动写入
Qt 日志文件的滚动写入 flyfish 日志文件的滚动写入功能。在日志文件达到10MB时创建新的日志文件,并且在总日志文件大小达到10GB时开始覆盖最早的日志文件 以监控一个文件夹的写日志为例 日志文件创建与管理 初始化日志文件:在FileMonitor类的构造函…...
【c语言】数据包捕获和分析工具
请解释一下数据包捕获和分析工具(如Wireshark)的工作原理和用途。 数据包捕获和分析工具,如Wireshark(前身为Ethereal),是一种网络协议分析软件,它允许用户实时监控、抓取并分析计算机网络中的网…...
移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——14.哈希(2)(模拟实现)
1.概念介绍 1.1开散列 开散列(Open Hashing),也叫链地址法,是一种解决哈希冲突的方法。每个哈希表槽位保存一个链表,所有散列到同一位置的元素都存储在该链表中。当插入元素发生冲突时,将新元素添加到相应…...
请描述一下JVM(Java虚拟机)的生命周期及其对应用程序性能的影响
1、请描述一下JVM(Java虚拟机)的生命周期及其对应用程序性能的影响。 JVM(Java虚拟机)的生命周期主要涉及以下几个阶段:加载、验证、准备、解析、执行、卸载。每个阶段都有其特定的作用和影响。 加载:JVM…...
展会邀约|加速科技与您相约IC China 2024!
第二十一届中国国际半导体博览会( IC China 2024)将于 2024 年11月18日—11月20日在北京国家会议中心举行。加速科技将携高性能测试机ST2500EX、ST2500E、eATE及全系测试解决方案亮相E2馆B150展位。博览会期间,将同期举办"半导体产业前沿…...
鸿蒙中服务卡片数据的获取和渲染
1. 2.在卡片中使用LocalStorageProp接受传递的数据 LocalStorageProp("configNewsHead") configNewsHeadLocal: ConfigNewsHeadInfoItem[] [] 注意:LocalStorageProp括号中的为第一步图片2中的键 3.第一次在服务卡片的第一个卡片中可能会获取不到数据…...
运维篇-修复centos7无法下载docker问题
修复centos7无法下载docker问题 1、安装docker时报错2、docker无法下载镜像 1、安装docker时报错 linux的centos系统,安装docker时会报错 –> Finished Dependency Resolution Error: Package: glibc-2.17-307.el7.1.i686 (base) Requires: glibc-common 2.17…...
【论文阅读】WaDec: Decompiling WebAssembly Using Large Language Model
论文阅读笔记:WaDec: Decompiling WebAssembly Using Large Language Model 1. 来源出处 论文标题: WaDec: Decompiling WebAssembly Using Large Language Model作者: Xinyu She, Yanjie Zhao, Haoyu Wang会议: 39th IEEE/ACM International Conference on Automated Softwar…...
redis类型介绍
1. 字符串(String): • 简介:最基础的数据类型,可以存储任何形式的字符串,包括文本数据和数字数据。 • 常用操作:SET、GET、INCR、DECR等。 2. 列表(List): …...
kubernetes如何配置默认存储
如果不想每次都创建PV,希望k8s集群中能够配置号默认存储,然后根据你的PVC自动创建PV,就需要安装一个默认存储,也就是storageclass 什么是storageclass Kubernetes提供了一套可以自动创建PV的机制,即:Dyna…...
【微服务】Spring AI 使用详解
目录 一、前言 二、Spring AI 概述 2.1 什么是Spring AI 2.2 Spring AI 特点 2.3 Spring AI 带来的便利 2.4 Spring AI 应用领域 2.4.1 聊天模型 2.4.2 文本到图像模型 2.4.3 音频转文本 2.4.4 嵌入大模型使用 2.4.5 矢量数据库支持 2.4.6 数据工程ETL框架 三、Sp…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
04-初识css
一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
【HTML-16】深入理解HTML中的块元素与行内元素
HTML元素根据其显示特性可以分为两大类:块元素(Block-level Elements)和行内元素(Inline Elements)。理解这两者的区别对于构建良好的网页布局至关重要。本文将全面解析这两种元素的特性、区别以及实际应用场景。 1. 块元素(Block-level Elements) 1.1 基本特性 …...
Java入门学习详细版(一)
大家好,Java 学习是一个系统学习的过程,核心原则就是“理论 实践 坚持”,并且需循序渐进,不可过于着急,本篇文章推出的这份详细入门学习资料将带大家从零基础开始,逐步掌握 Java 的核心概念和编程技能。 …...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
Mysql8 忘记密码重置,以及问题解决
1.使用免密登录 找到配置MySQL文件,我的文件路径是/etc/mysql/my.cnf,有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...
Linux 中如何提取压缩文件 ?
Linux 是一种流行的开源操作系统,它提供了许多工具来管理、压缩和解压缩文件。压缩文件有助于节省存储空间,使数据传输更快。本指南将向您展示如何在 Linux 中提取不同类型的压缩文件。 1. Unpacking ZIP Files ZIP 文件是非常常见的,要在 …...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
Leetcode33( 搜索旋转排序数组)
题目表述 整数数组 nums 按升序排列,数组中的值 互不相同 。 在传递给函数之前,nums 在预先未知的某个下标 k(0 < k < nums.length)上进行了 旋转,使数组变为 [nums[k], nums[k1], …, nums[n-1], nums[0], nu…...
