MyBatis认识
一、定义
MyBatis是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java Objects,普通老式 Java 对象)为数据库中的记录。
官网:https://mybatis.org/mybatis-3/zh_CN/index.html
二、核心概念
1、SqlSessionFactoryBuilder
2、SqlSessionFactory
3、SqlSession
4、插件
(1)定义
MyBatis允许通过使用插件在映射语句执行过程中的某一点进行拦截。
默认情况下,MyBatis允许使用插件来拦截的方法调用有:
A、Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)(执行器拦截器)
允许拦截和自定义MyBatis执行器的行为。例如,可以添加缓存、日志记录或审计功能到执行器中。这些拦截器可以在MyBatis执行的不同阶段扩展或修改其行为。您可以通过实现MyBatis提供的相应接口并在MyBatis配置文件中进行配置来实现这些拦截器
B、ParameterHandler (getParameterObject, setParameters)(参数拦截器)
允许在将参数设置到SQL语句之前修改或验证它们。例如,可以对作为参数传递的敏感信息进行加密或解密。
C、ResultSetHandler (handleResultSets, handleOutputParameters)(结果集拦截器)
可以在将结果集返回给应用程序之前修改或分析它们。例如,可以对结果集数据进行转换或执行额外的计算。
D、StatementHandler (prepare, parameterize, batch, update, query)(语句拦截器)
可以在SQL语句执行之前修改或增强它们。例如,可以向WHERE子句添加额外的条件或记录执行的语句。分页等
(2)自定义插件
在MyBatis中,只需实现 Interceptor 接口,并指定想要拦截的方法签名即可对某个方法进行拦截。
A、Executor方法的拦截
示例代码:对query执行过程的拦截
@Intercepts({@Signature(type= Executor.class,method="query",args={MappedStatement.class, Object.class,RowBounds.class, ResultHandler.class })})
public class QueryExecutorPlugin implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 执行query方法Object obj=invocation.proceed();// 修改执行结果List<Object> list= JSONUtil.parseArray(obj);list.add(new Category().setName("测试插件1"));return list;}@Overridepublic Object plugin(Object target) {// 包装目标对象的:包装:为目标对象创建一个代理对象return Interceptor.super.plugin(target);}@Overridepublic void setProperties(Properties properties) {// 将插件注册时的property属性设置进来Interceptor.super.setProperties(properties);}
}
B、StatementHandler方法的拦截
示例代码:对sql语句的修改
@Intercepts({@Signature(type = StatementHandler.class,method ="prepare",args = {Connection.class,Integer.class})})
public class StatementPlugin implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {StatementHandler statementHandler= PluginUtils.realTarget(invocation.getTarget());MetaObject metaObject= SystemMetaObject.forObject(statementHandler);BoundSql boundSql= (BoundSql) metaObject.getValue("delegate.boundSql");String originSql=boundSql.getSql();System.out.println("原始sql:"+originSql);// 对原始sql进行改写metaObject.setValue("delegate.boundSql.sql",originSql.replace("?","8888888"));return invocation.proceed();}
}
或者
@Intercepts({@Signature(type = StatementHandler.class,method ="prepare",args = {Connection.class,Integer.class})})
public class StatementPlugin implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {StatementHandler statementHandler= (StatementHandler) invocation.getTarget();BoundSql boundSql= statementHandler.getBoundSql();String originSql=boundSql.getSql();System.out.println("原始sql:"+originSql);// 直接对原始sql进行改写ReflectUtil.setFieldValue(boundSql,"sql",originSql.replace("?","9878948"));return invocation.proceed();}
}
C、ParameterHandler方法的拦截
@Intercepts({@Signature(type = ParameterHandler.class, method = "setParameters", args = PreparedStatement.class)})
public class ParameterPlugin implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 修改参数值return null;}
}
D、ResultSetHandler方法的拦截
@Intercepts({@Signature(type = ResultSetHandler.class, method = "handleResultSets", args = Statement.class)})
public class ResultSetPlugin implements Interceptor {@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 修改结果集return null;}
}
E、测试
a、添加插件
public class MyBatisConfig {@Beanpublic SqlSessionFactory sqlSessionFactory(){DriverManagerDataSource dataSource=new DriverManagerDataSource();dataSource.setUrl("jdbc:mysql://xxx:xxx/xxx?characterEncoding=utf-8&useSSL=false");dataSource.setUsername("xxx");dataSource.setPassword("xxx");dataSource.setDriverClassName("com.mysql.jdbc.Driver");TransactionFactory transactionFactory = new JdbcTransactionFactory();Environment environment = new Environment("development", transactionFactory, dataSource);org.apache.ibatis.session.Configuration config=new org.apache.ibatis.session.Configuration(environment);config.addMapper(CategoryMapper.class);// 添加插件config.addInterceptor(new QueryExecutorPlugin());config.addInterceptor(new ParameterPlugin());config.addInterceptor(new StatementPlugin());return new SqlSessionFactoryBuilder().build(config);}
}
b、测试代码
public class TestMyBatis {public static void main(String[] args) {AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(MyBatisConfig.class);SqlSessionFactory factory= (SqlSessionFactory) context.getBean("sqlSessionFactory");try(SqlSession sqlSession=factory.openSession()){CategoryMapper categoryMapper=sqlSession.getMapper(CategoryMapper.class);categoryMapper.insert(new Category().setName("222222"));List<Category> list=categoryMapper.selectList();System.out.println(JSONUtil.toJsonPrettyStr(list));sqlSession.commit();// 默认mybatis是不会自动提交的,需要手动自动提交修改才会生效}}
}
5、类型转换器TypeHandler
(1)常用的TypeHandler
(2)自定义TypeHandler
可以通过继承BaseTypeHandler来自定义TypeHandler
三、使用
1、Spring使用MyBatis
(0)数据库中已存在category表
(1)引入依赖
<!-- mybatis依赖 --><dependency><groupId>org.mybatis</groupId><artifactId>mybatis</artifactId><version>3.5.16</version></dependency>
(2)编写配置类MyBatisConfig
@ComponentScan(basePackages = "org.example.mybatis")
@Configuration
public class MyBatisConfig {@Beanpublic SqlSessionFactory sqlSessionFactory(){DriverManagerDataSource dataSource=new DriverManagerDataSource();dataSource.setUrl("jdbc:mysql://xxx:xxx/xxx?characterEncoding=utf-8&useSSL=false");dataSource.setUsername("xxx");dataSource.setPassword("xxx");dataSource.setDriverClassName("com.mysql.jdbc.Driver");TransactionFactory transactionFactory = new JdbcTransactionFactory();Environment environment = new Environment("development", transactionFactory, dataSource);org.apache.ibatis.session.Configuration config=new org.apache.ibatis.session.Configuration(environment);config.addMapper(CategoryMapper.class);return new SqlSessionFactoryBuilder().build(config);}
}
(3)编写测试类
public class TestMyBatis {public static void main(String[] args) {AnnotationConfigApplicationContext context=new AnnotationConfigApplicationContext(MyBatisConfig.class);SqlSessionFactory factory= (SqlSessionFactory) context.getBean("sqlSessionFactory");try(SqlSession sqlSession=factory.openSession()){CategoryMapper categoryMapper=sqlSession.getMapper(CategoryMapper.class);categoryMapper.insert(new Category().setName("222222"));List<Category> list=categoryMapper.selectList();System.out.println(JSONUtil.toJsonPrettyStr(list));sqlSession.commit();// 默认mybatis是不会自动提交的,需要手动自动提交修改才会生效}}
}
四、原理
五、关于MyBatisPlus
1、定义
MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
2、特性
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 CRUD 操作,更有强大的条件构造器,满足各类使用需求
- 支持 Lambda 形式调用:通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错
- 支持主键自动生成:支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题
- 支持 ActiveRecord 模式:支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作
- 支持自定义全局通用操作:支持全局通用方法注入( Write once, use anywhere )
- 内置代码生成器:采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用
- 内置分页插件:基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询
- 分页插件支持多种数据库:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库
- 内置性能分析插件:可输出 SQL 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询
- 内置全局拦截插件:提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作
相关文章:

MyBatis认识
一、定义 MyBatis是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参数和获取结果集的工作。MyBatis 可以通过简单的 XML 或注解来配置和映射原始类型、接口和 Java POJO(Plain Old Java O…...

【WEEK11】 【DAY6】Employee Management System Part 7【English Version】
2024.5.11 Saturday Continued from 【WEEK11】 【DAY5】Employee Management System Part 6【English Version】 Contents 10.8. Delete and 404 Handling10.8.1. Modify list.html10.8.2. Modify EmployeeController.java10.8.3. Restart10.8.4. 404 Page Handling10.8.4.1. …...

【52】Camunda8-Zeebe核心引擎-Clustering与流程生命周期
Clustering集群 Zeebe本质是作为一个brokers集群运行,形成一个点对点网络。在这个网络中,所有brokers的功能与服务都相同,没有单点故障。 Gossip协议 Zeebe实现了gossip协议,并借此知悉哪些broker当前是集群的一部分。 集群使用…...

从零开始的软件测试学习之旅(八)jmeter线程组参数化及函数学习
jmeter线程组参数化及函数学习 Jmeter基础基本使用流程组件与元件 线程组线程的执行方式Jmeter组件执行顺序 常见属性设置查看结果数的作用域举例 Jmeter参数化实现方式1.用户定义参数2.用户参数3.函数4.csv数据文件设置 每日复习 Jmeter基础 基本使用流程 启动项目案例 启动…...

图文并茂:解析Spring Boot Controller返回图片的三种方式
欢迎来到我的博客,代码的世界里,每一行都是一个故事 图文并茂:解析Spring Boot Controller返回图片的三种方式 前言使用Base64编码返回图片使用byte数组返回图片使用Resource对象返回图片图片格式转换与性能对比 前言 在互联网的世界里&…...
问题处理记录 | 表输出报错 Packet for query is too large (5,214,153 > 4,194,304).
这个错误是由于MySQL服务器接收到的查询数据包太大而引起的。具体来说,错误消息中提到的数据包大小为5,214,153字节,而MySQL服务器默认只接受最大为4,194,304字节的数据包。 要解决这个问题,你可以尝试通过修改MySQL服务器的配置来增大max_a…...

数据结构_栈和队列(Stack Queue)
✨✨所属专栏:数据结构✨✨ ✨✨作者主页:嶔某✨✨ 栈: 代码:function/数据结构_栈/stack.c 钦某/c-language-learning - 码云 - 开源中国 (gitee.com)https://gitee.com/wang-qin928/c-language-learning/blob/master/function/…...

基于docker 的elasticsearch冷热分离及生命周期管理
文章目录 冷热集群架构的应用场景冷热集群架构的优势冷热集群架构实战搭建集群 索引生命周期管理认识索引生命周期索引生命周期管理的历史演变索引生命周期管理的基础知识Rollover:滚动索引 冷热集群架构的应用场景 某客户的线上业务场景如下:系统每天增…...

pikachu靶场(xss通关教程)
(注:若复制注入代码攻击无效,请手动输入注入语句,在英文输入法下) 反射型xss(get型) 1.打开网站 发现有个框,然后我们在框中输入一个“1”进行测试, 可以看到提交的数据在url处有显示…...

实验0.0 Visual Studio 2022安装指南
Visual Studio 2022 是一个功能强大的开发工具,对于计算机专业的学生来说,它不仅可以帮助你完成学业项目,还能为你将来的职业生涯打下坚实的基础。通过学习和使用 Visual Studio,你将能够更高效地开发软件,并在编程领域…...
数据结构之----线性表
线性表分为 顺序存储结构 和 链式存储结构 线性表的顺序存储结构: 线性表的顺序存储结构,指的是用一段地址连续的存储单元依次存储线性表的数据元素。 1,顺序表的结构: #define MAXSIZE 20 typedef int El…...
thinkphp5.1 模型auto
在ThinkPHP5.1中,模型的自动完成功能可以通过在模型类中定义auto属性来实现。这个属性是一个数组,包含了需要自动填充的字段和对应的处理规则。 以下是一个简单的例子,展示了如何在ThinkPHP5.1的模型中使用自动完成功能: <?…...

企业微信创建应用(一)
登录到企业微信后台管理(https://work.weixin.qq.com/)进入自建应用(应用管理-应用-创建应用) 3.查看参数AgentId和 Secret 4.企业微信查看效果...

Cosmo Bunny Girl
可爱的宇宙兔女郎的3D模型。用额外的骨骼装配到Humanoid上,Apple混合了形状。完全模块化,包括不带衣服的身体。 技术细节 内置,包括URP和HDRP PDF。还包括关于如何启用URP和HDRP的说明。 LOD 0:面:40076,tris 76694,verts 44783 装配了Humanoid。添加到Humanoid中的其他…...

初始化linux数据盘(3TB)分区-格式化-挂载目录
场景说明:某云给我们服务器加载了一块3TB的硬盘扩容(没有直接扩,原因是原来的盘做的是mbr(什么年代了,谁干的)的分区,最大识别2TB) 确认磁盘 输入命令lsblk 查看数据盘信息 &#…...
NFS网络文件系统的应用
1.配置2台服务器要求如下: a)服务器1: 主机名:user-server.timinglee.org ip地址: 172.25.254.100 [rootserver100 桌面]# hostnamectl hostname user-server.timinglee.org [rootserver100 桌面]# ifconfig eth0: fl…...

AttributeError: module ‘PIL.Image‘ has no attribute ‘ANTIALIAS‘
问题描述 修改图片大小的时候,代码报错:AttributeError: module PIL.Image has no attribute ANTIALIAS 解决方案 在pillow的10.0.0版本中,ANTIALIAS方法被删除了。 方法1:修改版本(不推荐) pip instal…...

进程的共享主存通信实验
进程的共享主存通信 【预备知识】 共享存储区为进程提供了直接通过主存进行通信的有效手段,不像消息缓冲机制那样需要系统提供缓冲,也不像pipe机制那样需要事先建立一个特殊文件,而是由通信双方直接访问某些共享虚拟储存空间。在Linux中&…...

深度缓冲技术在AI去衣中的神奇作用
引言: 随着人工智能技术的飞速发展,其在图形处理和视觉领域的应用日益增多。AI去衣技术便是其中一个颇具争议但又技术上引人入胜的话题。今天,我们将深入探讨一项关键技术——深度缓冲(Depth Buffering),它…...

能效?性能?一个关于Windows下使用openssl speed进行速度测试的诡异问题
问题描述 最近的某个软件用到了openssl,所以就想着测试一下速度。我的电脑是惠普的,CPU是AMD Ryzen 7 PRO 6850HS,系统是Win11。我使用openssl自带的speed测试加密/解密的速度,命令大致如下: openssl speed -evp aes…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
spring:实例工厂方法获取bean
spring处理使用静态工厂方法获取bean实例,也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下: 定义实例工厂类(Java代码),定义实例工厂(xml),定义调用实例工厂ÿ…...

如何应对敏捷转型中的团队阻力
应对敏捷转型中的团队阻力需要明确沟通敏捷转型目的、提升团队参与感、提供充分的培训与支持、逐步推进敏捷实践、建立清晰的奖励和反馈机制。其中,明确沟通敏捷转型目的尤为关键,团队成员只有清晰理解转型背后的原因和利益,才能降低对变化的…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...

恶补电源:1.电桥
一、元器件的选择 搜索并选择电桥,再multisim中选择FWB,就有各种型号的电桥: 电桥是用来干嘛的呢? 它是一个由四个二极管搭成的“桥梁”形状的电路,用来把交流电(AC)变成直流电(DC)。…...

STM32标准库-ADC数模转换器
文章目录 一、ADC1.1简介1. 2逐次逼近型ADC1.3ADC框图1.4ADC基本结构1.4.1 信号 “上车点”:输入模块(GPIO、温度、V_REFINT)1.4.2 信号 “调度站”:多路开关1.4.3 信号 “加工厂”:ADC 转换器(规则组 注入…...
node.js的初步学习
那什么是node.js呢? 和JavaScript又是什么关系呢? node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说, 需要在node.js的环境上进行当JavaScript作为前端开发语言来说,需要在浏览器的环境上进行 Node.js 可…...
boost::filesystem::path文件路径使用详解和示例
boost::filesystem::path 是 Boost 库中用于跨平台操作文件路径的类,封装了路径的拼接、分割、提取、判断等常用功能。下面是对它的使用详解,包括常用接口与完整示例。 1. 引入头文件与命名空间 #include <boost/filesystem.hpp> namespace fs b…...

麒麟系统使用-进行.NET开发
文章目录 前言一、搭建dotnet环境1.获取相关资源2.配置dotnet 二、使用dotnet三、其他说明总结 前言 麒麟系统的内核是基于linux的,如果需要进行.NET开发,则需要安装特定的应用。由于NET Framework 是仅适用于 Windows 版本的 .NET,所以要进…...