当前位置: 首页 > news >正文

MyBatisr如何模拟生成Mapper代理对象

MyBatis操作数据库使用Mapper接口和XML SQL定义,并没有创建接口实现类,MyBatis如何为Mapper接口生成代理对象的,MyBatis使用JDK proxy或Cglib生成一个代理对象,在org.apache.ibatis.session.SqlSession方法中扫描Mapper和XML完成对数据库操作。

本例通过两种方式演示MyBatis生成代理工作原理,
一是按照MyBatis规范设计Mapper接口和XML定义,自定义代理生成类MapperProxy,使用SqlSession触发方法。

TestMapper.xml<?xml version="1.0"encoding="UTF-8"?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.hk.mapper.TestMapper"><resultMap id="UserMap"type="com.hk.entity.UserInfo"><result column="id"property="id"/><result column="name"property="name"/><result column="login_id"property="loginId"/><result column="pwd"property="pwd"/><result column="version"property="version"/><result column="status"property="status"/><result column="org_name"property="orgName"/></resultMap><select id="getUserList"parameterType="String"resultType="com.hk.entity.UserInfo">select u.* from user u</select></mapper>TestMapper.javapackagecom.hk.mybatis;importcom.baomidou.mybatisplus.core.conditions.Wrapper;importcom.baomidou.mybatisplus.core.mapper.BaseMapper;importcom.baomidou.mybatisplus.core.metadata.IPage;importcom.baomidou.mybatisplus.core.toolkit.Constants;importcom.hk.entity.UserInfo;importorg.apache.ibatis.annotations.Mapper;importorg.apache.ibatis.annotations.Param;importjava.util.List;publicinterfaceTestMapperextendsBaseMapper<UserInfo>{publicList<UserInfo>getUserList();publicList<UserInfo>getUserByName(@Param("name")Stringname);}MapperProxy.javapackagecom.hk.mybatis;importorg.apache.ibatis.session.SqlSession;importjava.io.Serializable;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.sql.*;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;publicclassMapperProxy<T>implementsInvocationHandler,Serializable{privatestaticfinallongserialVersionUID=-6424540398559729838L;privateSqlSessionsqlSession;privatefinalClass<T>mapperInterface;publicMapperProxy(SqlSessionsqlSession,Class<T>mapperInterface){this.sqlSession=sqlSession;this.mapperInterface=mapperInterface;}@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{if(Object.class.equals(method.getDeclaringClass())){// Object 提供的toString、hashCode等不需要代理执行returnmethod.invoke(this,args);}else{returnsqlSession.selectList(method.getName(),args);// 代理映射最终执行是 SqlSession}}}MapperProxyFactory.javapackagecom.hk.mybatis;importorg.apache.ibatis.session.SqlSession;importjava.lang.reflect.Proxy;importjava.util.Map;publicclassMapperProxyFactory<T>{privatefinalClass<T>mapperInterface;publicMapperProxyFactory(Class<T>mapperInterface){this.mapperInterface=mapperInterface;}publicTnewInstance(SqlSessionsqlSession){finalMapperProxy<T>mapperProxy=newMapperProxy<>(sqlSession,mapperInterface);// 注意:接口在扫描时通过ClassScanner.scanPackage()加载为了一个Java类return(T)Proxy.newProxyInstance(mapperInterface.getClassLoader(),newClass[]{mapperInterface},mapperProxy);// 传入类加载器、接口的类对象,代理目标类,创建 JDK 动态代理对象}}MapperProxyFactoryTest.javapackagecom.hk.mybatis;importcom.hk.Starter;importcom.hk.entity.UserInfo;importcom.hk.mapper.UserMapper;importorg.apache.ibatis.session.SqlSessionFactory;importorg.junit.Test;importorg.junit.runner.RunWith;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.test.context.junit4.SpringRunner;importjava.util.HashMap;importjava.util.List;importjava.util.Map;@RunWith(SpringRunner.class)@SpringBootTest(webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT,classes=Starter.class)publicclassMapperProxyFactoryTest{@AutowiredprivateSqlSessionFactorysqlSessionFactory;@Testpublicvoidtest_MapperProxyFactory(){MapperProxyFactory<TestMapper>factory=newMapperProxyFactory<>(TestMapper.class);Map<String,String>xmlMap=newHashMap<>();// 模拟 SqlSessionTestMapperuserDao=factory.newInstance(sqlSessionFactory.openSession());List<UserInfo>list=userDao.getUserList();System.out.println(list);}}

二是模拟代理类,自定义SQL操作,绕开SqlSession

MapperProxy.javapackagecom.hk.mybatis;importorg.apache.ibatis.session.SqlSession;importjava.io.Serializable;importjava.lang.reflect.InvocationHandler;importjava.lang.reflect.Method;importjava.sql.*;importjava.util.ArrayList;importjava.util.HashMap;importjava.util.List;importjava.util.Map;publicclassMapperProxy<T>implementsInvocationHandler,Serializable{privatestaticfinallongserialVersionUID=-6424540398559729838L;privateSqlSessionsqlSession;privatefinalClass<T>mapperInterface;privateMap<String,String>xmlMap;publicMapperProxy(SqlSessionsqlSession,Class<T>mapperInterface,Map<String,String>xmlMap){this.sqlSession=sqlSession;this.mapperInterface=mapperInterface;this.xmlMap=xmlMap;}@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{if(Object.class.equals(method.getDeclaringClass())){// Object 提供的toString、hashCode等不需要代理执行returnmethod.invoke(this,args);}else{Stringsql=xmlMap.get(method.getName());returnexecuteSql(sqlSession.getConnection(),sql);//return sqlSession.selectList(method.getName(), args); // 代理映射最终执行是 SqlSession}}publicObjectexecuteSql(Connectionconn,Stringsql)throwsThrowable{Listrtn=newArrayList();Statementstat=conn.createStatement();ResultSetrs=stat.executeQuery(sql);ResultSetMetaDatarsmd=rs.getMetaData();intcols=rsmd.getColumnCount();while(rs.next()){Mapm=newHashMap();for(inti=1;i<=cols;i++){StringcolName=rsmd.getColumnName(i);StringcolVal=rs.getString(colName);m.put(colName,colVal);}rtn.add(m);}returnrtn.toArray();}}MapperProxyFactory.javapackagecom.hk.mybatis;importorg.apache.ibatis.session.SqlSession;importjava.lang.reflect.Proxy;importjava.util.Map;publicclassMapperProxyFactory<T>{privatefinalClass<T>mapperInterface;publicMapperProxyFactory(Class<T>mapperInterface){this.mapperInterface=mapperInterface;}publicTnewInstance(SqlSessionsqlSession,Map<String,String>xmlMap){finalMapperProxy<T>mapperProxy=newMapperProxy<>(sqlSession,mapperInterface,xmlMap);// 注意:接口在扫描时通过ClassScanner.scanPackage()加载为了一个Java类return(T)Proxy.newProxyInstance(mapperInterface.getClassLoader(),newClass[]{mapperInterface},mapperProxy);// 传入类加载器、接口的类对象,代理目标类,创建 JDK 动态代理对象}}TestMapper.javapackagecom.hk.mybatis;importcom.baomidou.mybatisplus.core.conditions.Wrapper;importcom.baomidou.mybatisplus.core.mapper.BaseMapper;importcom.baomidou.mybatisplus.core.metadata.IPage;importcom.baomidou.mybatisplus.core.toolkit.Constants;importcom.hk.entity.UserInfo;importorg.apache.ibatis.annotations.Mapper;importorg.apache.ibatis.annotations.Param;importjava.util.List;publicinterfaceTestMapperextendsBaseMapper<UserInfo>{publicObjectgetUserList();publicObjectgetUserByName(@Param("name")Stringname);}MapperProxyFactoryTest.javapackagecom.hk.mybatis;importcom.hk.Starter;importcom.hk.entity.UserInfo;importcom.hk.mapper.UserMapper;importorg.apache.ibatis.session.SqlSessionFactory;importorg.junit.Test;importorg.junit.runner.RunWith;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;importorg.springframework.test.context.junit4.SpringRunner;importjava.util.HashMap;importjava.util.List;importjava.util.Map;@RunWith(SpringRunner.class)@SpringBootTest(webEnvironment=SpringBootTest.WebEnvironment.RANDOM_PORT,classes=Starter.class)publicclassMapperProxyFactoryTest{@AutowiredprivateSqlSessionFactorysqlSessionFactory;@Testpublicvoidtest_MapperProxyFactory(){MapperProxyFactory<TestMapper>factory=newMapperProxyFactory<>(TestMapper.class);Map<String,String>xmlMap=newHashMap<>();// 模拟 SqlSessionxmlMap.put("getUserList","select u.* from user u");xmlMap.put("getUserByLoginId","模拟执行 Mapper.xml 中 SQL 语句的操作:查询用户信息");TestMapperuserDao=factory.newInstance(sqlSessionFactory.openSession(),xmlMap);Objectobj=userDao.getUserList();Object[]userDim=(Object[])obj;for(introw=0;row<userDim.length;row++){Mapmap=(Map)userDim[row];System.out.println(map);}}}
http://www.jsqmd.com/news/570891/

相关文章:

  • Windows 11系统优化指南:基于Win11Debloat的一站式性能调校方案
  • STC89C52抢答器DIY避坑指南:从万能板焊接调试到常见故障排查(蜂鸣器不响、按键失灵)
  • 虚拟显示技术多场景适配指南:从驱动配置到性能优化的完整实践
  • 新手告别visio下载困惑,快马AI带你零代码入门流程图设计
  • HTML基本标签的用法第二弹
  • 革新性AI图像引擎:Qwen-Image-Edit-Rapid-AIO全方位应用指南
  • 18-SpringBootLoader原理
  • 千问3.5-2B与Dify平台结合:无需编码快速搭建AI应用
  • 从计算器到编译器:浅谈后缀表达式(逆波兰)在C++实际项目中的应用场景
  • 连云港查找财产线索服务哪家价格便宜 - 工业品牌热点
  • 思源宋体TTF字体终极指南:7种样式免费商用,新手也能快速上手
  • 4种Windows运行Android应用方案测评:轻量工具如何重塑跨平台体验
  • Go Routine 调度器负载均衡机制
  • 【JavaWeb学习 | 第22篇】文件上传下载与 Excel 导入导出
  • 调查财产线索哪家专业,连云港地区有靠谱的吗 - 工业推荐榜
  • 如何高效使用猫抓cat-catch:5个关键技巧完全指南
  • Windows系统性能优化全景指南:从问题诊断到持续优化
  • postman接口自动化如何进行参数化
  • 嵌入式设备OTA升级,如何用RSA-3072和Ed25519给固件‘验明正身’?
  • 轻量级投资决策中枢:TrafficMonitor股票插件的创新实践
  • 巴旦木脱青皮的设计【solidworks三维、cad图纸、论文、答辩稿】
  • 说说连云港强制执行律师费用,多少钱才合理? - myqiye
  • 如何快速掌握Vitest:让前端测试效率提升10倍的终极指南
  • 群晖7.X系统下SSH双重验证(OTP)的故障排查与关闭指南
  • 360误杀Go程序?教你设置专属安全编译目录(附各杀毒软件信任区设置图解)
  • 5分钟掌握:如何用这款免费工具让Windows飞起来?
  • 【完整源码+数据集+部署教程】儿童与成人目标检测系统源码分享[一条龙教学YOLOV8标注好的数据集一键训练_70+全套改进创新点发刊_Web前端展示]
  • HSTracker:macOS炉石传说智能追踪器的终极指南
  • Vanilla论坛布局系统详解:灵活定制你的社区页面结构
  • 从零到一:NS2网络模拟器实战部署与场景构建指南