以下笔记是我看完视频之后总结整理的,部分较为基础的知识点也做了补充,如有问题欢迎沟通。

任务一:自定义持久层框架

1.1 JDBC回顾及问题分析

JDBC问题分析:

问题 解决方案
1 数据库配置信息存在硬编码 使用配置文件
2 频繁创建释放数据库连接 使用连接池
3 SQL语句、设置参数、获取结果参数存在硬编码问题 使用配置文件
4 手动封装返回结果集,较为繁琐 使用反射、内省

注意:虽然有两个配置文件,但不建议放到一个文件中,因为一个是经常修改的,一个是几乎不变的,而且逻辑上也不合理,只不过可以通过特殊方式不用手动加载每一个xml文件,具体见1.3.2 sqlMapConfig.xml详解

1.2 自定义持久层框架思路分析

使用端:(项目)引入自定义持久层框架的jar包

提供两部分配置信息:数据库配置信息、SQL配置信息(SQL语句、参数类型、返回值类型)

  1. sqlMapConfig.xml:存放数据库配置信息
  2. mapper.xml:存放sql配置信息

自定义框架层本身:(工程)本质就是对JDBC代码进行封装

  1. 加载配置文件:根据配置文件路径,加载配置文件成字节输入流,存储在内存中

    创建Resource类,方法:InputStream getResourceAsStream(String path)
  2. 创建两个JavaBean(容器对象),存放的就是配置文件解析出来的内容

    Configuration:核心配置类,存放sqlMapConfig.xml解析出来的内容

    MapperStatement:映射配置类,存放mapper.xml解析出来的内容
  3. 解析配置文件:dom4j

    创建类:SqlSessionFactoryBuilder包含方法build(InputStream in)主要做两件事:

    3.1 使用dom4j解析配置文件,将解析出来的内容封装到容器对象中

    3.2 创建sqlSessionFactory对象,生产SqlSession,即会话对象(增删改查都封装在这里),这里用到了工厂模式,降低程序间的耦合(不直接new一个SqlSession)
  4. 创建SqlSessionFactory接口及实现类DefaultSqlSessionFactory,方法openSession()用以生产sqlSession
  5. 创建SqlSession接口及实现类DefaultSession,定义对数据库的CRUD操作(selectList、selectOne、update……)
  6. 创建Executor接口及实现类SimpleExecutor实现类,query(Configuration,MapperStatement,MapperStatement,Object... params)方法,执行的就是JDBC代码

1.3 IPersistence_Test编写

IPersistence_Test可以认为是使用端,首先完成使用端编写,相对比较简单,要做的就是编写配置文件以及引入jar包

两类配置文件:

sqlMapConfig.xml : 写数据库连接相关的配置信息

XXXMapper.xml : (比如UserMapper.xml) 写特定模块(比如用户模块)的语句信息

1.3.1 XXXMapper.xml详解

XXXMapper.xml中主要完成以下功能:

  1. 配置真正需要在MySql里面执行的sql语句
  2. 实现特定语句的定位,也就是需要给sql一个特定标识,即statementId
  3. 指定返回结果的封装类型
  4. 指定传入参数的类型

但是这么写只能操作user表,假设有了product表,那么都使用selectList就无法确定使用的究竟是哪一个语句,所以要添加命名空间namespace

<mapper namespace="user">
<!--sql的唯一标识:namespace.id来组成,statementId--> <!--为了能定位到特定的select语句,就要给一个id-->
<!--resultType代表了想要封装的实体,所以就要通过反射从相应路径下获取对应实体及属性-->
<select id="selectList" resultType="com.jlgl.pojo.User">
select * from user
</select> <!--这条sql语句执行的时候是需要参数的-->
<!--多个参数传递,要有面向对象的思想,把多个对象封装到某个实体-->
<!--
User user=new User();
user.setId();
user.setUsername();
-->
<!--所以参数也需要通过反射获取对应实体及属性-->
<!--为了把对应的属性赋值到对应的占位符上,就要把?改成自定义占位符-->
<select id="selectOne" resultType="com.jlgl.pojo.User" paramterType="com.jlgl.pojo.User">
select * from user where id =#{id} and username = #{username}
</select> </mapper>

1.3.2 sqlMapConfig.xml详解

为了Resource加载xml文件时只加载一次,就需要把mapper.xml也存放进来,需要mapper.xml的全路径

<configuration>

    <!--数据库配置信息-->
<dataSource>
<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
<property name="jdbcUrl" value="jdbc:mysql://120.48.8.213:3306/audio_2020"></property>
<property name="username" value="root"></property>
<property name="password" value="root1028*1"></property>
</dataSource> <!--为了Resource加载xml文件时只加载一次,就需要把mapper.xml也存放进来,需要mapper.xml的全路径-->
<mapper resource="UserMapper.xml"></mapper> </configuration>

1.4 Resources类定义

自定义持久层框架本质上就是利用dom4j技术,对使用端写好的xml文件进行分析,然后封装到配置类中,最终配置类被层层传递到Executor的query方法中执行JDBC代码

Resources类里面定义一个方法,目的是将配置文件加载成字节输入流,存储在内存中

1.5 容器对象定义

容器对象:MapperStatement和Configuration,这两个容器对象存放的就是配置文件解析出来的内容

MapperStatement作用是从xxxMapper里面读取内容,所以xxxMapper的各个属性都需要被存储在MapperStatement对应的类属性

Configuration作用是存放的就是sqlMapConfig的内容,其实就是数据库配置信息

1.6 解析核心配置文件sqlMapConfig

如前所述,解析核心配置文件需要两步:

3. 解析配置文件:dom4j
创建类:SqlSessionFactoryBuilder包含方法build(InputStream in)主要做两件事:
3.1 使用dom4j解析配置文件,将解析出来的内容封装到容器对象中
3.2 创建sqlSessionFactory对象,生产SqlSession,即会话对象(增删改查都封装在这里),这里用到了工厂模式,降低程序间的耦合(不直接new一个SqlSession)

首先是使用dom4j解析配置文件,具体是使用XMLConfigBuilder.parseConfig(InputStream in)实现的

将sqlMapConfig.xml生成Configuration

1.7 解析映射配置文件mapper.xml

在XMLConfigBuilder里面,调用XMLMapperBuilder的parse方法,读取XXXMapper.xml生成MapperStatement,并将其放入到Configuration的mapperStatementMap里面

1.8 会话对象sqlSession类定义

在回话对象中,使用Configuration里面储存的转换后的配置文件信息,完成与数据库的连接及数据获取操作

1.9 会话对象sqlSession方法定义

以selectList()为例,需要执行以下三步:

1 初始化Executor对象
2 获取Comfiguration里面存的xxxMapper.xml转换后的MapperStatement
3 执行Executor的query方法

1.10 查询对象query方法定义

一共需要执行六步:

1 注册驱动,获取连接
2 获取sql语句,然后转换sql语句,此时需要配置标记解析器来对占位符的解析处理工作(这里直接用了Mybatis的代码)
3 获取预处理对象:preparedStatement
4 设置参数
5 执行sql
6 封装返回结果集

注意:

在mapper.xml配置时,不直接写成?的原因是,为了能够将根据属性名直接获取传入对象的对应属性

面向对象的思想,将参数封装成对象,再返回,具体见buildParameterMapping,不是将String类型的content直接放入List,而是转换成了ParameterMapping对象放入List

1.11 参数设置实现

使用反射,根据参数名称,获取实体对象的属性值,然后获取对象中的具体参数值

1.12 封装返回结果集实现

使用反射或者内省,根据数据库表和实体的对应关系,完成封装

1.13 Client端运行测试

如何使用IPErsistence框架:

首先将IPersistence类打包,然后在IPersistence_test的pom引入包即可

UML类图(重要,需要好好理解):

1.14 功能扩展——getMapper方法实现

自定义持久层框架存在的问题:

1 代码重复。Dao层加载配置文件、获取SqlSessionFactory、生产sqlSession对象存在代码重复
2 硬编码问题。硬编码了statementId

解决思路:

不要Dao的实现类,使用代理模式实现Dao层接口的代理实现类

具体步骤:

1 在SqlSession创建getMappper,并在DefaultSession重写
3 在Client端直接调用

1.15 功能扩展——动态代理invoke方法实现

注意:不论如何简洁、优化,最终还是要执行底层的方法

xxxMapper.xml文件的规范要遵守,namespace要和接口全限定名一致,方法名也要和接口方法名一致

原因:

invoke方法中是没有办法获取statementId的(前面采用的方式是硬编码写进去的),但是可以通过接口全限定名.方法名即namespace.id,就组装出了statementId

【笔记】拉勾Java工程师高薪训练营-第一阶段 开源框架源码解析-模块一 持久层框架涉及实现及MyBatis源码分析-任务一:自定义持久层框架的更多相关文章

  1. Java工程师高薪训练营-第一阶段 开源框架源码解析-模块一 持久层框架涉及实现及MyBatis源码分析-任务一:自定义持久层框架

    目录 任务一:自定义持久层框架 1.1 JDBC回顾及问题分析 1.2 自定义持久层框架思路分析 1.3 IPersistence_Test编写 1.3.1 XXXMapper.xml详解 1.3.2 ...

  2. Java面试题_第一阶段(static、final、面向对象、多线程、集合、String、同步、接口、GC、JVM)

    1.1 简述static和final的用法? static:修饰属性,方法,代码块 (1)静态属性:也可叫类变量  类名.属性名  来访问 (共有的类变量与对象无关,只和类有关) 注意:类中的实例变量 ...

  3. java工程师_基础_阶段一_HTML笔记篇

    一.了解HTML语言 html:超文本标记语言. 二.HTML整体结构<html> <head> </head> <body> </body> ...

  4. java课堂测试2第一阶段:方法运用

    package test2; import java.util.*; public class Test2 { public static int generateRandom(int fanwei) ...

  5. 死磕 java同步系列之CyclicBarrier源码解析——有图有真相

    问题 (1)CyclicBarrier是什么? (2)CyclicBarrier具有什么特性? (3)CyclicBarrier与CountDownLatch的对比? 简介 CyclicBarrier ...

  6. 死磕 java同步系列之Phaser源码解析

    问题 (1)Phaser是什么? (2)Phaser具有哪些特性? (3)Phaser相对于CyclicBarrier和CountDownLatch的优势? 简介 Phaser,翻译为阶段,它适用于这 ...

  7. 死磕 java同步系列之Semaphore源码解析

    问题 (1)Semaphore是什么? (2)Semaphore具有哪些特性? (3)Semaphore通常使用在什么场景中? (4)Semaphore的许可次数是否可以动态增减? (5)Semaph ...

  8. 死磕 java同步系列之ReentrantReadWriteLock源码解析

    问题 (1)读写锁是什么? (2)读写锁具有哪些特性? (3)ReentrantReadWriteLock是怎么实现读写锁的? (4)如何使用ReentrantReadWriteLock实现高效安全的 ...

  9. Java高薪训练营(对标阿里P7,限时分享)

    某钩Java高薪训练营(部分,持续更新) 下载地址 防止网盘和谐多次补链修改,公众号回复「训练营」自提.

随机推荐

  1. List移除另外一个list的时候报错,java.lang.UnsupportedOperationException

    问题 编写代码的时候,使用Mybatis-plus分页查询返回的list,移除自己new的ArrayList报错 根据异常信息,发现mybatis-plus分页查询返回的list底层并没有实现remo ...

  2. id+is+深浅co'p'y

    day06 一.id.is 关键字:id #唯一的,如果id相同,说明2个变量指向同一个地址,就是变量一==变量二 注意:id相同值一定相同,值相同但是id不一定相同(不同代码块的值相同,他们就像太阳 ...

  3. 解决VMware无法共享ubuntu虚拟机文件

    1.错误信息:无法更新运行时文件夹共享状态:在客户机操作系统内装载共享文件夹文件系统时出错 2.检查vmware tool是否正确安装 lsmod | grep vmhgfs modprobe vmh ...

  4. ubuntu下vi不能正常使用的解决方法

    现象 ubuntu中vi在编辑状态下方向键不能用,还有回格键不能删除等我们平时习惯的一些键都不能使用. 原因 ubuntu预装的是vim tiny版本,需要的是vim full版本. 方案 $sudo ...

  5. filebeat7.5 日志

    百度网盘 提取码: 6cvu 解压 tar -zxvf filebeat-7.5.0-linux-x86_64.tar.gz mv filebeat-7.5.0-linux-x86_64 /usr/l ...

  6. 3.QOpenGLWidget-通过着色器来渲染渐变三角形

    在上章2.通过QOpenGLWidget绘制三角形,我们学习绘制三角形还是单色的,本章将为三角形每个顶点着色.   1.着色器描述 着色器的开头总是要声明版本,接着是输入和输出变量.uniform和m ...

  7. 【Azure微服务 Service Fabric 】如何转移Service Fabric集群中的种子节点(Seed Node)

    注意:在对Service Fabric的节点做操作之前,请务必确认是否是种子节点(Seed Node)且当前节点的数量是否与SF的持久层要求的数量一致. 可靠性级别是 Service Fabric 群 ...

  8. ps命令没有显示路径找到命令真实路径

    top发现某程序占用大量资源,但ps查看看不到程序真实路径,查找真实路径. ps aux |grep COMMAND 找到PID ls /proc/ 里边有很多数字文件夹,找到PID相应的文件夹进去看 ...

  9. Qt中的Q_OBJECT作用, 以及信号槽

    自定义类时, 如果需要使用Qt框架提供的信号槽机制, 必须满足以下两个条件: 第一:该类必须是QObject类的子类或者间接子类. 其次:在定义类时, 首行必须加上宏Q_OBJECT class My ...

  10. Java 中的 3 个双引号是什么语法?Java 15 刷新你的认知!

    Java 中的 3 个双引号 """ 是什么语法? 这是 Java 15 新出的,刷新你的认知! 一.前言 在 Java 15 的推出的时候,Text Blocks 正式 ...