如何开发一个mybatis扩展框架

如何开发一个mybatis扩展框架

都说官网是最好的入门。当你参考mybatis官网执行查询发现这样:

// try 执行完后会关闭 session 
try (SqlSession session = sqlSessionFactory.openSession()) {BlogMapper mapper = session.getMapper(BlogMapper.class);Blog blog = mapper.selectBlog(101);
}

如果你不关闭 SqlSession 会发现,执行几个后,连接池将会耗尽,因为你未关闭连接。

前提可参考这篇文章:https://lingkang.top/archives/tong-guo-dai-ma-jia-zai-mybatis-de-mapperxml

如果你要开发一个 mybatis 扩展框架,如何能反复调用呢?

如果你要开发一个 mybatis 扩展框架,如何能反复调用呢?
我们可以参考 mybatis-spring 框架源码,mybatis-spring 的SqlSessionTemplate 类实现了 mybatis 的 SqlSession 接口,在它构造函数中初始化了 SqlSessionFactory 代理处理 SqlSessionInterceptor
在这里插入图片描述

再查看代理实现 SqlSessionInterceptor.invoke,发现它会在执行完毕后关闭连接

在这里插入图片描述

基于代理 SqlSessionFactory 开发一个框架

基于这篇文章搭建的环境:https://lingkang.top/archives/tong-guo-dai-ma-jia-zai-mybatis-de-mapperxml

编写一个 SqlSession 代理处理

import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cursor.Cursor;
import org.apache.ibatis.executor.BatchResult;
import org.apache.ibatis.session.*;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.sql.Connection;
import java.util.List;
import java.util.Map;/*** @Author lingkang* @Date 2024/2/29 9:25*/
@Slf4j
public class MySqlSession implements SqlSession {private SqlSessionFactory sqlSessionFactory;private ExecutorType executorType;private SqlSession sessionProxy;public MySqlSession(SqlSessionFactory sqlSessionFactory, ExecutorType executorType) {this.sqlSessionFactory = sqlSessionFactory;this.executorType = executorType;// 创建我们的代理,以扩展更多功能sessionProxy = (SqlSession) Proxy.newProxyInstance(getClass().getClassLoader(),new Class[]{SqlSession.class},new SqlSessionProxy());}@Overridepublic <T> T selectOne(String statement) {return sessionProxy.selectOne(statement);}@Overridepublic <T> T selectOne(String statement, Object parameter) {return sessionProxy.selectOne(statement, parameter);}@Overridepublic <E> List<E> selectList(String statement) {return sessionProxy.selectList(statement);}@Overridepublic <E> List<E> selectList(String statement, Object parameter) {return sessionProxy.selectList(statement, parameter);}@Overridepublic <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {return sessionProxy.selectList(statement, parameter, rowBounds);}@Overridepublic <K, V> Map<K, V> selectMap(String statement, String mapKey) {return sessionProxy.selectMap(statement, mapKey);}@Overridepublic <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey) {return sessionProxy.selectMap(statement, mapKey, mapKey);}@Overridepublic <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds) {return sessionProxy.selectMap(statement, mapKey, mapKey, rowBounds);}@Overridepublic <T> Cursor<T> selectCursor(String statement) {return sessionProxy.selectCursor(statement);}@Overridepublic <T> Cursor<T> selectCursor(String statement, Object parameter) {return sessionProxy.selectCursor(statement, parameter);}@Overridepublic <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds) {return sessionProxy.selectCursor(statement);}@Overridepublic void select(String statement, Object parameter, ResultHandler handler) {sessionProxy.select(statement, parameter, handler);}@Overridepublic void select(String statement, ResultHandler handler) {sessionProxy.select(statement, handler);}@Overridepublic void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler) {sessionProxy.select(statement, parameter, rowBounds, handler);}@Overridepublic int insert(String statement) {return sessionProxy.insert(statement);}@Overridepublic int insert(String statement, Object parameter) {return sessionProxy.insert(statement, parameter);}@Overridepublic int update(String statement) {return sessionProxy.update(statement);}@Overridepublic int update(String statement, Object parameter) {return sessionProxy.update(statement, parameter);}@Overridepublic int delete(String statement) {return sessionProxy.delete(statement);}@Overridepublic int delete(String statement, Object parameter) {return sessionProxy.delete(statement, parameter);}@Overridepublic void commit() {throw new UnsupportedOperationException("不支持的方法,已经交由 final-magic 管理事务");}@Overridepublic void commit(boolean force) {throw new UnsupportedOperationException("不支持的方法,已经交由 final-magic 管理事务");}@Overridepublic void rollback() {throw new UnsupportedOperationException("不支持的方法,已经交由 final-magic 管理事务");}@Overridepublic void rollback(boolean force) {throw new UnsupportedOperationException("不支持的方法,已经交由 final-magic 管理事务");}@Overridepublic List<BatchResult> flushStatements() {return sessionProxy.flushStatements();}@Overridepublic void close() {throw new UnsupportedOperationException("不支持的方法,已经交由 final-magic 管理连接");}@Overridepublic void clearCache() {sessionProxy.clearCache();}@Overridepublic Configuration getConfiguration() {// 从会话工厂中获取return sqlSessionFactory.getConfiguration();}@Overridepublic <T> T getMapper(Class<T> type) {return getConfiguration().getMapper(type, this);}@Overridepublic Connection getConnection() {return sessionProxy.getConnection();}private class SqlSessionProxy implements InvocationHandler {private int countNumber = 0;@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 例如创建时将 session 存储到线程变量中,线程处理结束就关闭此会话SqlSession session = sqlSessionFactory.openSession(executorType);countNumber++;log.info("获取会话");System.out.println("获取连接: " + countNumber);// 如果存在事务时,开启事务// session.getConnection().setAutoCommit(false);Object result = null;try {result = method.invoke(session, args);// 事务处理 如果不存在事务就提交操作// AOP 结束、 请求处理结束、提交事务} catch (Exception e) {// 事务处理 如果存在事务就要回滚// session.rollback();// log.info("事务回滚");throw new RuntimeException(e);} finally {// 判断是否存在事务,不存在就关闭连接session.close();countNumber--;System.out.println("关闭连接: " + countNumber);}return result;}}
}

调用

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.builder.xml.XMLMapperBuilder;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import top.lingkang.solonweb.mapper.UserMapper;import java.io.InputStream;/*** @author lingkang* Created by 2024/2/29*/
@Slf4j
public class Demo01 {public static boolean isOk = false;public static void main(String[] args) throws Exception {HikariConfig config = new HikariConfig();config.setJdbcUrl("jdbc:mysql://localhost:3306/test?useSSL=true&serverTimezone=UTC");config.setUsername("root");config.setPassword("123456");config.setMaximumPoolSize(3);HikariDataSource dataSource = new HikariDataSource(config);Configuration configuration = new Configuration();// 用for循环加载所有 xmlInputStream inputStream = Resources.getResourceAsStream("mapper/UserMapper.xml");XMLMapperBuilder mapperParser = new XMLMapperBuilder(inputStream, configuration, "mapper/UserMapper.xml",configuration.getSqlFragments());mapperParser.parse();// 配置TransactionFactory transactionFactory = new JdbcTransactionFactory();Environment environment = new Environment("dev", transactionFactory, dataSource);configuration.setEnvironment(environment);configuration.setMapUnderscoreToCamelCase(true);// 下划线转化驼峰SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);// 模拟aop生命周期,session可以存储到线程变量中,线程处理结束就关闭此会话MySqlSession session = new MySqlSession(sqlSessionFactory, null);UserMapper mapper = session.getMapper(UserMapper.class);System.out.println(mapper.selectAll());// 查询所有System.out.println(mapper.selectOne());System.out.println(mapper.selectOne());System.out.println(mapper.selectOne());System.out.println(mapper.selectOne());}}

输出如下

在这里插入图片描述
转自 https://lingkang.top/archives/ru-he-kai-fa-yi-mybatis-kuo-zhan-kuang-jia

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

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

相关文章

刷题第2天(中等题):LeetCode59--螺旋矩阵--考察模拟能力(边界条件处理)

LeetCode59: 给你一个正整数 n &#xff0c;生成一个包含 1 到 n2 所有元素&#xff0c;且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。 示例 1&#xff1a; 输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]]示例 2&#xff1a; 输入&#xff1a…

新产品推广先定位分析再选择推广渠道

营销是创业者最容易犯错的地方之一&#xff0c;一份完美的新品牌产品推广方案能够达到精准营销&#xff0c;减少不必要的资金浪费&#xff0c;提升产品的销量&#xff0c;那么如何做新品牌产品推广的方案&#xff1f;小马识途营销顾问建议对产品进行推广的时候&#xff0c;要在…

unity使用Registry类将指定内容写入注册表

遇到一个新需求&#xff0c;在exe执行初期把指定内容写入注册表&#xff0c;Playerprefs固然可以写入&#xff0c;但是小白不知道怎么利用Playerprefs写入DWORD类型的数据&#xff0c;因此使用了Registry类 一. 对注册表中键的访问 注册表中共可分为五类 一般在操作时&#…

CSS3详解

1.什么是CSS css的优势 1、内容和表现分离 2、网页结构表现统一&#xff0c;可以实现复用 3、样式十分的丰富 4、建议使用独立于html的css文件 5、利用SE0,容易被搜索引擎收录&#xff01; CSS的几种导入方法 内部式 <style>h1{color: red;}</style> 外部式 嵌…

Phoncent博客:探索AI写作与编程的无限可能

Phoncent博客&#xff0c;一个名为Phoncent的创新AIGC博客网站&#xff0c;于2023年诞生。它的创始人是庄泽峰&#xff0c;一个自媒体人和个人站长&#xff0c;他在网络营销推广领域有着丰富的经验。庄泽峰深知人工智能技术在内容创作和编程领域的潜力和创造力&#xff0c;因此…

javaWeb个人学习02

会话技术 会话: 用户打开浏览器,访问web服务器的资源,会话建立,直到有一方断开连接,会话结束.在一次会话中包含多次请求和响应 会话跟踪: 一种维护浏览器状态的方法,服务器需要识别多次请求是否来自于同一个浏览器,以便在同一次会话的多次请求之间共享数据 会话跟踪方案: …

【Ansys 2024 R1 】助力扩展AI支持的多物理场优势,重构用户体验

全新的用户体验将增强协作式工程环境&#xff0c;这不仅让强大的多物理场解决方案更便于访问&#xff0c;同时还可扩大由AI驱动的数字工程解决方案的优势。 主要亮点 ✔ Ansys现代化的设计语言不仅可提升用户体验&#xff08;UX&#xff09;&#xff0c;在整个Ansys多物理场产…

Mallox勒索病毒的最新威胁:如何恢复您的数据?

引言&#xff1a; 在当今数字化时代&#xff0c;网络安全威胁层出不穷&#xff0c;而勒索软件&#xff08;Ransomware&#xff09;是其中最为恶劣的一种形式之一。而.Mallox勒索病毒则是近期备受关注的一种勒索软件&#xff0c;其深受全球各地用户的困扰。那么&#xff0c;让我…

【C语言】linux内核ipoib模块 - ipoib_ib_handle_rx_wc

一、中文注释 // 定义一个处理InfiniBand接收完成工作请求的函数 static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) {// 通过网络设备获取私有数据结构struct ipoib_dev_priv *priv ipoib_priv(dev);// 获取工作请求ID&#xff0c;并屏蔽掉接收…

Python实现时间序列分析进行平稳性检验(ADF和KPSS)和差分去趋势(adfuller和kpss算法)项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档视频讲解&#xff09;&#xff0c;如需数据代码文档视频讲解可以直接到文章最后获取。 1.项目背景 时间序列分析中的平稳性检验是评估一个时间序列是否具有稳定的均值和方差。在经济学、金融学以及其他诸…

使用Git从其他分支merge个别文件

项目背景 产品经理&#xff1a;我们本次开发三个功能&#xff0c;列表页功能、详情页功能、系统消息功能&#xff0c;分两次上线&#xff0c;先上列表功能&#xff0c;再上详情页和系统消息。 小明&#xff1a;好的吧。 紧接着&#xff0c;小明就将本次需求分为2个分支&…

SpringBootWeb响应(黑马学习笔记)

前面我们学习过HTTP协议的交互方式&#xff1a;请求响应模式&#xff08;有请求就有响应&#xff09; 那么Controller程序呢&#xff0c;除了接收请求外&#xff0c;还可以进行响应。 ResponseBody 在我们前面所编写的controller方法中&#xff0c;都已经设置了响应数据。 c…