您的位置: 首页 - 站长

asp网站开发国内外现状岳阳新网网站建设有限公司

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

asp网站开发国内外现状,岳阳新网网站建设有限公司,编程网站免费中文版,打开百度一下网页版前言 在学习MyBatis源码文章中#xff0c;斗胆想将其讲明白#xff1b;故有此文章#xff0c;如有问题#xff0c;不吝指教#xff01; 注意#xff1a; 学习源码一定一定不要太关注代码的编写#xff0c;而是注意代码实现思想#xff1b; 通过设问方式来体现代码中的…前言 在学习MyBatis源码文章中斗胆想将其讲明白故有此文章如有问题不吝指教 注意 学习源码一定一定不要太关注代码的编写而是注意代码实现思想 通过设问方式来体现代码中的思想方法5W1H 源代码https://gitee.com/xbhog/mybatis-xbhoghttps://github.com/xbhog/mybatis-xbhog交个朋友欢迎star。 也可关注笔者公众号
回顾分析 上一局实现【简写Mybatis】02-注册机的实现以及SqlSession处理;主要是为了完善Mapper的注册方式以及SqlSession规范的流程 上一局的测试类如下在使用上还是比我们平常熟悉的Mybatis要差好多比如没有Mapper配置文件、Mapper映射文件、没有针对数据库操作等。 /*** Unit test for simple App./ public class AppTest extends TestCase {/** Rigourous Test :-)/public void testApp() {MapperRegistry mapperRegistry new MapperRegistry();mapperRegistry.addMapper(com.xbhog);DefaultSqlSessionFactory sqlSessionFactory new DefaultSqlSessionFactory(mapperRegistry);SqlSession sqlSession sqlSessionFactory.openSession();IUserDao user sqlSession.getMapper(IUserDao.class);String userName user.getUserName(xbhog);System.out.println(输出的信息userName);} }目的 XML的解析和读取封装XML数据封装配置类封装MapperRegistry和SqlSessionFactory设置统一入口封装Mapper文件中方法的执行操作 实现 XML的解析和读取 引入相关的Maven依赖 dependencygroupIdorg.dom4j/groupIdartifactIddom4j/artifactIdversion2.1.3/version /dependency dependencygroupIdcn.hutool/groupIdartifactIdhutool-all/artifactIdversion5.5.0/version /dependency解析的相关代码如下已有注释 // xml文件内容转换为字符串流 Reader reader ResourceUtil.getUtf8Reader(mybatis-config-datasource.xml);// 从字符串流中读取并创建XML Document对象 SAXReader saxReader new SAXReader(); Document document saxReader.read(new InputSource(reader));// 获取XML文档的根元素 Element rootElement document.getRootElement();// 获取根元素下的“mappers”子元素 Element mappersElement rootElement.element(mappers);// 遍历所有“mapper”子元素 ListElement mapperElements mappersElement.elements(mapper); for (Element mapperElement : mapperElements) {// 获取当前“mapper”元素的“resource”属性值String mapperResource mapperElement.attributeValue(resource);System.out.println(正在查看资源 mapperResource);// 依据“resource”属性加载对应的XML文件内容为字符串流Reader mapperReader ResourceUtil.getUtf8Reader(mapperResource);// 创建新的SAXReader实例以读取mapper文件中的XML内容SAXReader saxReaderForMapper new SAXReader();// 从mapper的字符串流中创建新的Document对象Document mapperDocument saxReaderForMapper.read(new InputSource(mapperReader));// 获取mapper文件的根元素Element mapperRootElement mapperDocument.getRootElement();// 遍历mapper文件中所有的“select”元素ListElement selectNodes mapperRootElement.elements(select);for (Element selectElement : selectNodes) {// 获取“select”元素的各个属性值String selectId selectElement.attributeValue(id);String parameterType selectElement.attributeValue(parameterType);String resultType selectElement.attributeValue(resultType);String sqlStatement selectElement.getText();// 输出“select”元素的属性及SQL语句System.out.println(相关SQL映射信息ID selectId 参数类型 parameterType 结果类型 resultType SQL语句 sqlStatement);} }作用是从一个主配置文件“mybatis-config-datasource.xml”中读取到多个mapper资源配置并逐个加载这些mapper资源文件。针对每个mapper文件进一步提取出其中所有的SQL select 映射定义包括其ID、参数类型、结果类型以及具体的SQL语句这里是将这些信息打印出来后续将保存到实体或者配置方便后续使用。 看下解析的效果 正在查看资源mapper/User_Mapper.xml 相关SQL映射信息IDqueryUserInfoById参数类型java.lang.Long结果类型com.xbhog.UserSQL语句SELECT id, userId, userHead, createTimeFROM userwhere id #{id}XML配置构建器 这部分采用建造者模式实现XML的配置该模式比较适合基本物料不变而其组合经常发生变化的场景核心目的是将复杂对象的构建过程与它的表示分离。 建造者分为一下几个角色 抽象建造者定义了创建产品对象的各个部分的方法比如零件或组件一般会有一个方法来获取最终的复杂产品。具体建造者实现了抽象建造者接口完成每个部分的具体构造和装配方法提供构造过程的具体实现。产品(复杂对象)是被构建的复杂对象包含了多个组成部件。具体建造者创建产品的各个部件并最终组合成完整的产品。 抽象建造者 按照上述的定义以及具体我们想实现的业务可以拆分成两个操作 初始化XML字符流转换成Doc供后续使用解析完的DOC实体类进行保存并且需要一个出口进行获得 public abstract class BaseBuilder {protected final Configuration configuration;public BaseBuilder(Configuration configuration) {this.configuration configuration;}//只保证外部能够获得所有的信息具体的配置在子类中赋值public Configuration getConfiguration() {return configuration;}}BaseBuilder提供了构建Configuration对象所需要的基本方法和属性并且也对其子类有着通用的构建逻辑。 建造者实现 初始化XML字符流转换Doc public XmlConfigBuilder(Reader reader) {//在处理XML配置文件中初始化Configurationsuper(new Configuration());// 2. dom4j 处理 xmlSAXReader saxReader new SAXReader();try {Document document saxReader.read(new InputSource(reader));root document.getRootElement();} catch (DocumentException e) {e.printStackTrace();} }初始化XML字符流在上一小节已经解决了在正常Myabtis中的Sql是有占位符或者拼接符并将相关元素的保存到mappedStatement(映射器语句类)中 映射类语句类的编写 /** author xbhog* describe: 用于封装MyBatis中映射SQL语句的相关信息包括配置信息、SQL类型、参数类型、结果类型、SQL语句以及动态参数映射等。* date 2024/3/2/ public class MappedStatement {/** 配置对象包含MyBatis运行所需的环境、数据库映射等全局配置信息。/private Configuration configuration;/** 映射ID唯一标识一个MappedStatement通常对应XML文件中的mappedStatement标签的id属性。/private String id;/** SQL命令类型如INSERT、UPDATE、SELECT或DELETE等。/private SqlCommandType sqlCommandType;/** 参数类型对应于传入SQL语句的参数类的全限定名。/private String parameterType;/** 结果类型对应于SQL查询结果映射到的Java类型的全限定名。/private String resultType;/** SQL语句可能是预编译的静态SQL或带有占位符的动态SQL。/private String sql;/** 动态参数映射集合键为参数的位置从0开始计数值为参数的名称。/private MapInteger, String parameter;/** 空构造器主要用于反射创建实例。/public MappedStatement() {}/** 内部静态嵌套类Builder遵循建造者设计模式用于构建MappedStatement实例。/public static class Builder {/** 储存待构建的MappedStatement对象引用。/private MappedStatement mappedStatement new MappedStatement();/** 初始化Builder对象并设置MappedStatement的所有必要属性。** param configuration MyBatis的全局配置对象* param id 映射ID* param sqlCommandType SQL命令类型* param parameterType 参数类型全限定名* param resultType 结果类型全限定名* param sql SQL语句* param parameter 动态参数映射集合/public Builder(Configuration configuration, String id, SqlCommandType sqlCommandType, String parameterType, String resultType, String sql, MapInteger, String parameter) {mappedStatement.configuration configuration;mappedStatement.id id;mappedStatement.sqlCommandType sqlCommandType;mappedStatement.parameterType parameterType;mappedStatement.resultType resultType;mappedStatement.sql sql;mappedStatement.parameter parameter;}/** 完成构建并返回MappedStatement实例同时进行必要的非空断言检查。** return 已经填充好所有必要属性的MappedStatement实例/public MappedStatement build() {assert mappedStatement.configuration ! null : Configuration must not be null!;assert mappedStatement.id ! null : ID must not be null!;return mappedStatement;}} }存储部分设置完成我们处理下select的操作 // 遍历所有“mapper”子元素 ListElement mapperElements mappers.elements(mapper); for (Element mapperElement : mapperElements) {……//命名空间String namespace mapperRootElement.attributeValue(namespace);// 遍历mapper文件中所有的“select”元素(暂时只有这一个操作)ListElement selectNodes mapperRootElement.elements(select);for (Element selectElement : selectNodes) {// 获取“select”元素的各个属性值String selectId selectElement.attributeValue(id);String parameterType selectElement.attributeValue(parameterType);String resultType selectElement.attributeValue(resultType);String sql selectElement.getText();MapInteger, String parameter new HashMap();Pattern pattern Pattern.compile((#\{(.?)}));Matcher matcher pattern.matcher(sql);for(int i 1; matcher.find(); i){String group1 matcher.group(1);String group2 matcher.group(2);log.info(匹配出来的信息为{}{}, group1, group2);parameter.put(i, group2);//替换占位符sql sql.replace(group1,?);}//获取全路径String msId namespace . selectId;//获取sql方法(select…..)String nodeName selectElement.getName();//替换保持大小写一致SqlCommandType sqlCommandType SqlCommandType.valueOf(nodeName.toUpperCase(Locale.ENGLISH));//保存MappedStatement mappedStatement new MappedStatement.Builder(configuration, msId,sqlCommandType, parameterType, resultType, sql, parameter).build();//配置文件设置()configuration.addMappedStatement(mappedStatement);}// 注册Mapper映射器configuration.addMapper(Class.forName(namespace)); }可以发现上述的代码中出来在XML的解析以及映射器属性的保存外还有新加的configuration类。在mybatis中Configuration是一个重量级的核心配置类几乎包含了Mybatis运行的所有的配置信息。 在正式Mybatis中Configuration的作用 存储全局配置信息如数据库连接信息driver、url、username、password、事务管理器设置、映射文件位置、自定义类型处理器、日志工厂等。管理映射资源存储并管理所有 mapper 标签对应的 MappedStatement 对象这些对象包含了SQL语句、参数类型、结果类型、动态SQL解析器等信息。(本次处理的重点)提供动态SQL解析基于Configuration对象MyBatis能解析包含动态元素的SQL语句。(本次处理的重点)支持延迟加载和缓存策略在Configuration中可以配置二级缓存、全局的缓存开关、延迟加载策略等。提供内置对象工厂Configuration对象维护了一个对象工厂用于在运行时创建诸如ParameterHandler、ResultSetHandler、StatementHandler等核心对象。 本节处理流程 这得看下SqlSessionFatoryBuilder入口类的实现 public class SqlSessionFactoryBuilder {public SqlSessionFactory build(Reader reader) {XMLConfigBuilder xmlConfigBuilder new XMLConfigBuilder(reader);return build(xmlConfigBuilder.parse());}public SqlSessionFactory build(Configuration config) {return new DefaultSqlSessionFactory(config);} }先说结论configuration类本身不是单例类相反是Mybatis通过 SqlSessionFactoryBuilder 来确保整个应用中只有一个 Configuration 实例Configuration在*SqlSessionFactoryBuilder构建阶段完成实例化的操作。 一旦 SqlSessionFactory 被创建SqlSessionFatoryBuilder 的使命就完成了之后 SqlSessionFactory 就会被用来创建 SqlSession 实例进而执行 SQL 语句、管理事务和进行其他数据库操作。由于 SqlSessionFatoryBuilder 的任务完成后就可以丢弃因此通常采取即用即抛的原则正是由于SqlSessionFatoryBuilder 的这种原则保证了Configuration 有了单例的特性。 Mapper文件中方法的执行操作封装 看下之前的invoke方法的实现 Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {if(Object.class.equals(method.getDeclaringClass())){return method.invoke(this,args);}else{//todo 具体接口实现的方式return sqlSession.selectOne(method.getName(), args);} }在上一局中我们在invoke方法中指定了sql的处理类型基本操作都知道肯定不会有一种类型为了读者能更好的理解这里先看下上一局和这一局代码的新旧流程对比。 对比范围 └─src ├─main │ └─java │  └─com │  └─xbhog │  ├─binding │  │ ├─MapperMethod.java(新增) │  │ ├─MapperProxy.java │  │ ├─MapperProxyFactory.java │  │ └─MapperRegistry.java 该流程处理代码流程不变细节地方会有Configuration处理详细请看代码操作。 变化比较大的是在MapperProxy中invoke方法的执行操作上 这个时序图是MapperMethod类流程 简单介绍下功能 在mapperMethod初始化前会先从methodCache中进行查询存在返回不存在构建完并返回类似于缓存。mapperMethod初始化内包含了SqlCommand指令的构建采用的模式还是建造者模式内置方法名和方法类型属性通过接口名和方法名从Configuration获取mappedStatements构建属性值。其他操作就是把crud进行分开判断并执行。 到此所有涉及到的操作都或多或少的写到了接下来进行测试。 测试 环境构建 │ └─test │ ├─java │ │ └─com │ │ └─xbhog │ │ AppTest.java │ │ IUserDao.java │ │ User.java │ │
│ └─resources │ │ mybatis-config-datasource.xml │ │
│ └─mapper │ User_Mapper.xml?xml version1.0 encodingUTF-8? !DOCTYPE configuration PUBLIC -//mybatis.org//DTD Config 3.0//ENhttp://mybatis.org/dtd/mybatis-3-config.dtdconfigurationmappersmapper resourcemapper/User_Mapper.xml//mappers/configurationmapper namespacecom.xbhog.IUserDaoselect idqueryUserInfoById parameterTypejava.lang.Long resultTypecom.xbhog.UserSELECT id, userId, userHead, createTimeFROM userwhere id #{id}/select/mapperpublic class AppTest extends TestCase {private Logger logger LoggerFactory.getLogger(AppTest.class);/
Rigourous Test :-)*/public void testApp() throws Exception {// 1. 从SqlSessionFactory中获取SqlSessionReader reader ResourceUtil.getUtf8Reader(mybatis-config-datasource.xml);SqlSessionFactory sqlSessionFactory new SqlSessionFactoryBuilder().build(reader);SqlSession sqlSession sqlSessionFactory.openSession();// 2. 获取映射器对象IUserDao userDao sqlSession.getMapper(IUserDao.class);// 3. 测试验证String res userDao.queryUserInfoById(10001);logger.info(测试结果{}, res);} }结果如下 正在查看资源mapper/User_Mapper.xml 11:55:58.436 [main] INFO c.xbhog.builder.xml.XmlConfigBuilder - 匹配出来的信息为#{id}id 11:55:58.456 [main] INFO com.xbhog.AppTest - 测试结果你被代理了方法com.xbhog.IUserDao.queryUserInfoById 入参[Ljava.lang.Object;71c7db30,待执行的SQl:SELECT id, userId, userHead, createTimeFROM userwhere id ?总结 整个流程大致是从配置文件出发经过 SqlSessionFactoryBuilder 和 XmlConfigBuilder 构建并填充 Configuration然后 Configuration 被用来创建 SqlSessionFactory进而生产 SqlSession同时Configuration 中还维护了所有 MappedStatement 以及 Mapper 相关的注册信息确保 SqlSession 在处理数据库操作请求时能够找到正确的映射关系并执行相应的方法。对于 Mapper 接口它们通过 MapperRegistry、MapperProxyFactory 和 MapperProxy 构成了一个面向接口编程的持久层访问机制。 类名类的作用SqlSessionFactoryBuilder这是一个工具类用于从配置信息如XML配置文件或预定义的Configuration对象构建SqlSessionFactory实例。它接收配置输入解析并验证配置然后创建并初始化SqlSessionFactory。SqlSessionFactory可以理解为SqlSession的工厂它持有MyBatis的核心配置信息由Configuration对象提供。每个MyBatis应用的核心就是SqlSessionFactory实例它负责创建SqlSession对象。SqlSessionFactory通常是线程安全的可以被多个线程共享并在整个应用生命周期内保持。SqlSession是MyBatis执行数据库操作的主要入口点它提供了CRUD增删改查等各种数据库操作方法。每个SqlSession对象都与一个数据库连接Connection关联且不是线程安全的通常在一个请求或操作范围内使用。Configuration这是MyBatis的全局配置容器它存储了所有关于MyBatis的行为配置、所有映射器的注册信息、数据源、事务管理器、类型处理器等配置。SqlSessionFactoryBuilder正是根据Configuration的信息来构建SqlSessionFactory。DefaultSqlSessionFactory这是SqlSessionFactory的一个具体实现类继承自SqlSessionFactory接口它包含了创建和管理SqlSession的实际逻辑。DefaultSqlSession这是SqlSession接口的默认实现它封装了对数据库的CRUD操作以及对MappedStatement的访问。SqlCommandType表示SQL命令的类型枚举包括INSERT、UPDATE、DELETE、SELECT等这是在MappedStatement中用来区分不同类型的SQL操作。MappedStatement表示一个已经映射好的SQL语句及其相关配置包括SQL类型、参数类型、结果类型、SQL语句本身以及可能的动态SQL节点和参数映射规则。XmlConfigBuilder用于解析MyBatis的XML配置文件将XML配置信息转换为Configuration对象。BaseBuilder在MyBatis中如果有多个Builder类有着相似的构建逻辑可能会定义一个基类BaseBuilder提取公共方法和属性不过这里并未明确提到它在MyBatis中的具体实现。MapperRegistry在MyBatis中MapperRegistry是一个注册和管理所有Mapper接口的地方它负责存储和查找Mapper接口对应的MapperProxy和MapperMethod。MapperMethod表示在Mapper接口中定义的某个方法的具体实现它封装了方法对应的SQL执行逻辑。MapperProxyMyBatis利用Java动态代理机制通过MapperProxy来实现代理Mapper接口的对象当调用Mapper接口方法时实际上是调用了MapperProxy中的方法从而执行SQL操作。MapperProxyFactory负责创建MapperProxy实例的工厂类它根据Mapper接口生成对应的动态代理对象使用户可以通过接口的方式来执行数据库操作而不是直接与SqlSession打交道。每次需要新的Mapper代理对象时都会通过MapperProxyFactory来创建。 学习参考 https://mp.weixin.qq.com/s/C_bb9f1Hr9aJAvbmrDHHig mybatis源码 AI大模型