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

Audio_J 2020-11-10 13:39:00
java 工程师 工程 拉勾 高薪


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

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
版权声明
本文为[Audio_J]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/ArvinB/p/13953311.html

  1. 【计算机网络 12(1),尚学堂马士兵Java视频教程
  2. 【程序猿历程,史上最全的Java面试题集锦在这里
  3. 【程序猿历程(1),Javaweb视频教程百度云
  4. Notes on MySQL 45 lectures (1-7)
  5. [computer network 12 (1), Shang Xuetang Ma soldier java video tutorial
  6. The most complete collection of Java interview questions in history is here
  7. [process of program ape (1), JavaWeb video tutorial, baidu cloud
  8. Notes on MySQL 45 lectures (1-7)
  9. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  10. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  11. 精进 Spring Boot 03:Spring Boot 的配置文件和配置管理,以及用三种方式读取配置文件
  12. Refined spring boot 03: spring boot configuration files and configuration management, and reading configuration files in three ways
  13. 【递归,Java传智播客笔记
  14. [recursion, Java intelligence podcast notes
  15. [adhere to painting for 386 days] the beginning of spring of 24 solar terms
  16. K8S系列第八篇(Service、EndPoints以及高可用kubeadm部署)
  17. K8s Series Part 8 (service, endpoints and high availability kubeadm deployment)
  18. 【重识 HTML (3),350道Java面试真题分享
  19. 【重识 HTML (2),Java并发编程必会的多线程你竟然还不会
  20. 【重识 HTML (1),二本Java小菜鸟4面字节跳动被秒成渣渣
  21. [re recognize HTML (3) and share 350 real Java interview questions
  22. [re recognize HTML (2). Multithreading is a must for Java Concurrent Programming. How dare you not
  23. [re recognize HTML (1), two Java rookies' 4-sided bytes beat and become slag in seconds
  24. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  25. RPC 1: how to develop RPC framework from scratch
  26. 造轮子系列之RPC 1:如何从零开始开发RPC框架
  27. RPC 1: how to develop RPC framework from scratch
  28. 一次性捋清楚吧,对乱糟糟的,Spring事务扩展机制
  29. 一文彻底弄懂如何选择抽象类还是接口,连续四年百度Java岗必问面试题
  30. Redis常用命令
  31. 一双拖鞋引发的血案,狂神说Java系列笔记
  32. 一、mysql基础安装
  33. 一位程序员的独白:尽管我一生坎坷,Java框架面试基础
  34. Clear it all at once. For the messy, spring transaction extension mechanism
  35. A thorough understanding of how to choose abstract classes or interfaces, baidu Java post must ask interview questions for four consecutive years
  36. Redis common commands
  37. A pair of slippers triggered the murder, crazy God said java series notes
  38. 1、 MySQL basic installation
  39. Monologue of a programmer: despite my ups and downs in my life, Java framework is the foundation of interview
  40. 【大厂面试】三面三问Spring循环依赖,请一定要把这篇看完(建议收藏)
  41. 一线互联网企业中,springboot入门项目
  42. 一篇文带你入门SSM框架Spring开发,帮你快速拿Offer
  43. 【面试资料】Java全集、微服务、大数据、数据结构与算法、机器学习知识最全总结,283页pdf
  44. 【leetcode刷题】24.数组中重复的数字——Java版
  45. 【leetcode刷题】23.对称二叉树——Java版
  46. 【leetcode刷题】22.二叉树的中序遍历——Java版
  47. 【leetcode刷题】21.三数之和——Java版
  48. 【leetcode刷题】20.最长回文子串——Java版
  49. 【leetcode刷题】19.回文链表——Java版
  50. 【leetcode刷题】18.反转链表——Java版
  51. 【leetcode刷题】17.相交链表——Java&python版
  52. 【leetcode刷题】16.环形链表——Java版
  53. 【leetcode刷题】15.汉明距离——Java版
  54. 【leetcode刷题】14.找到所有数组中消失的数字——Java版
  55. 【leetcode刷题】13.比特位计数——Java版
  56. oracle控制用户权限命令
  57. 三年Java开发,继阿里,鲁班二期Java架构师
  58. Oracle必须要启动的服务
  59. 万字长文!深入剖析HashMap,Java基础笔试题大全带答案
  60. 一问Kafka就心慌?我却凭着这份,图灵学院vip课程百度云